First release of /delta version
This commit is contained in:
@@ -15,7 +15,7 @@
|
||||
<script>
|
||||
Clipperz_IEisBroken = false;
|
||||
Clipperz_normalizedNewLine = '\n';
|
||||
Clipperz_dumpUrl = "/../dump/";
|
||||
Clipperz_dumpUrl = "@dump.path@";
|
||||
</script>
|
||||
|
||||
<!--[if IE]><script>
|
||||
@@ -67,12 +67,22 @@ Clipperz_normalizedNewLine = '\x0d\x0a';
|
||||
|
||||
<div id="main">
|
||||
<h3 class="loading">loading ...</h3>
|
||||
<!-- script>
|
||||
_clipperz_pm_test_user = 'joe'
|
||||
_clipperz_pm_test_passphrase = 'clipperz'
|
||||
</script -->
|
||||
|
||||
@js_EMBEDDED@
|
||||
|
||||
<script>
|
||||
Clipperz.PM.Proxy.defaultProxy = new Clipperz.PM.Proxy.JSON({'url':'@request.path@', 'shouldPayTolls':@should.pay.toll@});
|
||||
/*offline_data_placeholder*/
|
||||
|
||||
/* * /
|
||||
MochiKit.DOM.addLoadEvent(function () {
|
||||
Clipperz.Crypto.PRNG.defaultRandomGenerator().fastEntropyAccumulationForTestingPurpose();
|
||||
});
|
||||
/ * */
|
||||
</script>
|
||||
|
||||
<div id="javaScriptAlert">
|
||||
@@ -84,8 +94,8 @@ Clipperz_normalizedNewLine = '\x0d\x0a';
|
||||
</div>
|
||||
<div id="footer">
|
||||
Copyright © 2008-2013 Clipperz Srl -
|
||||
<a href="http://www.clipperz.com/terms_of_service" target="black">Terms of service</a> -
|
||||
<a href="http://www.clipperz.com/privacy_policy" target="black">Privacy policy</a>
|
||||
<a href="https://www.clipperz.com/terms_service/" target="black">Terms of service</a> -
|
||||
<a href="https://www.clipperz.com/privacy_policy/" target="black">Privacy policy</a>
|
||||
-
|
||||
Application version: <a href="https://github.com/clipperz/password-manager/tree/@application.version@" target="github">@application.version@</a>
|
||||
</div>
|
||||
|
||||
1353
frontend/delta/css/web.css
Normal file
1353
frontend/delta/css/web.css
Normal file
File diff suppressed because one or more lines are too long
1
frontend/delta/fonts/clipperz-icons.json
Normal file
1
frontend/delta/fonts/clipperz-icons.json
Normal file
File diff suppressed because one or more lines are too long
130
frontend/delta/html/index_template.html
Normal file
130
frontend/delta/html/index_template.html
Normal file
File diff suppressed because one or more lines are too long
707
frontend/delta/js/Clipperz/Async.js
Normal file
707
frontend/delta/js/Clipperz/Async.js
Normal file
@@ -0,0 +1,707 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
//Clipperz.Async = MochiKit.Async;
|
||||
|
||||
|
||||
if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
|
||||
if (typeof(Clipperz.Async) == 'undefined') { Clipperz.Async = {}; }
|
||||
|
||||
Clipperz.Async.VERSION = "0.1";
|
||||
Clipperz.Async.NAME = "Clipperz.Async";
|
||||
|
||||
Clipperz.Async.Deferred = function(aName, args) {
|
||||
args = args || {};
|
||||
|
||||
Clipperz.Async.Deferred.superclass.constructor.call(this, args.canceller);
|
||||
|
||||
this._args = args;
|
||||
this._name = aName || "Anonymous deferred";
|
||||
this._count = 0;
|
||||
this._shouldTrace = ((CLIPPERZ_DEFERRED_TRACING_ENABLED === true) || (args.trace === true));
|
||||
this._vars = null;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
||||
Clipperz.Base.extend(Clipperz.Async.Deferred, MochiKit.Async.Deferred, {
|
||||
|
||||
'name': function () {
|
||||
return this._name;
|
||||
},
|
||||
|
||||
'args': function () {
|
||||
return this._args;
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'callback': function (aValue) {
|
||||
if (this._shouldTrace) {
|
||||
Clipperz.log("CALLBACK " + this._name, aValue);
|
||||
}
|
||||
|
||||
if (this.chained == false) {
|
||||
var message;
|
||||
|
||||
message = "ERROR [" + this._name + "]";
|
||||
this.addErrback(function(aResult) {
|
||||
if (! (aResult instanceof MochiKit.Async.CancelledError)) {
|
||||
Clipperz.log(message, aResult);
|
||||
}
|
||||
return aResult;
|
||||
});
|
||||
|
||||
if (this._shouldTrace) {
|
||||
var resultMessage;
|
||||
|
||||
resultMessage = "RESULT " + this._name + " <==";
|
||||
// this.addCallback(function(aResult) {
|
||||
Clipperz.Async.Deferred.superclass.addCallback.call(this, function(aResult) {
|
||||
Clipperz.log(resultMessage, aResult);
|
||||
return aResult;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (CLIPPERZ_DEFERRED_CALL_LOGGING_ENABLED === true) {
|
||||
Clipperz.log("callback " + this._name, this);
|
||||
}
|
||||
|
||||
return Clipperz.Async.Deferred.superclass.callback.apply(this, arguments);
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'addCallback': function () {
|
||||
var message;
|
||||
|
||||
if (this._shouldTrace) {
|
||||
this._count ++;
|
||||
message = "[" + this._count + "] " + this._name + " ";
|
||||
// this.addBoth(function(aResult) {Clipperz.log(message + "-->", aResult); return aResult;});
|
||||
this.addCallbacks(
|
||||
function(aResult) {Clipperz.log("-OK- " + message + "-->"/*, aResult*/); return aResult;},
|
||||
function(aResult) {Clipperz.log("FAIL " + message + "-->"/*, aResult*/); return aResult;}
|
||||
);
|
||||
}
|
||||
|
||||
Clipperz.Async.Deferred.superclass.addCallback.apply(this, arguments);
|
||||
|
||||
if (this._shouldTrace) {
|
||||
// this.addBoth(function(aResult) {Clipperz.log(message + "<--", aResult); return aResult;});
|
||||
this.addCallbacks(
|
||||
function(aResult) {Clipperz.log("-OK- " + message + "<--", aResult); return aResult;},
|
||||
function(aResult) {Clipperz.log("FAIL " + message + "<--", aResult); return aResult;}
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
//=============================================================================
|
||||
|
||||
'addCallbackPass': function() {
|
||||
var passFunction;
|
||||
|
||||
passFunction = MochiKit.Base.partial.apply(null, arguments);
|
||||
|
||||
this.addCallback(function() {
|
||||
var result;
|
||||
|
||||
result = arguments[arguments.length -1];
|
||||
passFunction();
|
||||
|
||||
return result;
|
||||
});
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'addErrbackPass': function() {
|
||||
var passFunction;
|
||||
|
||||
passFunction = MochiKit.Base.partial.apply(null, arguments);
|
||||
|
||||
this.addErrback(function() {
|
||||
var result;
|
||||
|
||||
result = arguments[arguments.length -1];
|
||||
passFunction();
|
||||
|
||||
return result;
|
||||
});
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'addBothPass': function() {
|
||||
var passFunction;
|
||||
|
||||
passFunction = MochiKit.Base.partial.apply(null, arguments);
|
||||
|
||||
this.addBoth(function() {
|
||||
var result;
|
||||
|
||||
result = arguments[arguments.length -1];
|
||||
passFunction();
|
||||
|
||||
return result;
|
||||
});
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'addIf': function (aThenBlock, anElseBlock) {
|
||||
this.addCallback(MochiKit.Base.bind(function (aValue) {
|
||||
var deferredResult;
|
||||
|
||||
if (!MochiKit.Base.isUndefinedOrNull(aValue) && aValue) {
|
||||
deferredResult = Clipperz.Async.callbacks(this._name + " <then>", aThenBlock, null, aValue);
|
||||
} else {
|
||||
deferredResult = Clipperz.Async.callbacks(this._name + " <else>", anElseBlock, null, aValue);
|
||||
}
|
||||
|
||||
return deferredResult;
|
||||
}))
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'addMethod': function () {
|
||||
this.addCallback(MochiKit.Base.method.apply(this, arguments));
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'addMethodcaller': function () {
|
||||
this.addCallback(MochiKit.Base.methodcaller.apply(this, arguments));
|
||||
},
|
||||
|
||||
//=============================================================================
|
||||
|
||||
'addLog': function (aLog) {
|
||||
if (CLIPPERZ_DEFERRED_LOGGING_ENABLED) {
|
||||
this.addBothPass(function(res) {Clipperz.log(aLog + " ", res);});
|
||||
}
|
||||
},
|
||||
|
||||
//=============================================================================
|
||||
|
||||
'acquireLock': function (aLock) {
|
||||
// this.addCallback(function (aResult) {
|
||||
// return Clipperz.Async.callbacks("Clipperz.Async.acquireLock", [
|
||||
// MochiKit.Base.method(aLock, 'acquire'),
|
||||
// MochiKit.Base.partial(MochiKit.Async.succeed, aResult)
|
||||
// ], {trace:false});
|
||||
// });
|
||||
|
||||
this.addCallback(MochiKit.Base.method(aLock, 'acquire'));
|
||||
},
|
||||
|
||||
'releaseLock': function (aLock) {
|
||||
// this.addCallback(function (aResult) {
|
||||
// return Clipperz.Async.callbacks("Clipperz.Async.release <ok>", [
|
||||
// MochiKit.Base.method(aLock, 'release'),
|
||||
// MochiKit.Base.partial(MochiKit.Async.succeed, aResult)
|
||||
// ], {trace:false});
|
||||
// });
|
||||
// this.addErrback(function (aResult) {
|
||||
///Clipperz.log("releaseLock.addErrback:", aResult);
|
||||
// return Clipperz.Async.callbacks("Clipperz.Async.release <fail>", [
|
||||
// MochiKit.Base.method(aLock, 'release'),
|
||||
// MochiKit.Base.partial(MochiKit.Async.fail, aResult)
|
||||
// ], {trace:false});
|
||||
// });
|
||||
|
||||
// this.addBothPass(MochiKit.Base.method(aLock, 'release'));
|
||||
this.addCallbackPass(MochiKit.Base.method(aLock, 'release'));
|
||||
this.addErrback(function (anError) {
|
||||
aLock.release();
|
||||
|
||||
return anError;
|
||||
});
|
||||
},
|
||||
|
||||
//=============================================================================
|
||||
|
||||
'collectResults': function (someRequests) {
|
||||
this.addCallback(Clipperz.Async.collectResults(this._name + " <collect results>", someRequests, this._args));
|
||||
},
|
||||
|
||||
'addCallbackList': function (aRequestList) {
|
||||
this.addCallback(Clipperz.Async.callbacks, this._name + " <callback list>", aRequestList, this._args);
|
||||
},
|
||||
|
||||
//=============================================================================
|
||||
|
||||
'vars': function () {
|
||||
if (this._vars == null) {
|
||||
this._vars = {}
|
||||
}
|
||||
|
||||
return this._vars;
|
||||
},
|
||||
|
||||
'setValue': function (aKey) {
|
||||
this.addCallback(MochiKit.Base.bind(function (aValue) {
|
||||
this.vars()[aKey] = aValue;
|
||||
return aValue;
|
||||
}, this));
|
||||
},
|
||||
|
||||
'getValue': function (aKey) {
|
||||
this.addCallback(MochiKit.Base.bind(function () {
|
||||
return this.vars()[aKey];
|
||||
}, this));
|
||||
},
|
||||
|
||||
//=============================================================================
|
||||
|
||||
'wait': function (someSeconds) {
|
||||
this.addCallback(MochiKit.Async.wait, someSeconds);
|
||||
},
|
||||
|
||||
//=============================================================================
|
||||
|
||||
__syntaxFix__: "syntax fix"
|
||||
});
|
||||
|
||||
//#############################################################################
|
||||
|
||||
Clipperz.Async.DeferredSynchronizer = function(aName, someMethods) {
|
||||
this._name = aName || "Anonymous deferred Synchronizer";
|
||||
this._methods = someMethods;
|
||||
|
||||
this._numberOfMethodsDone = 0;
|
||||
this._methodResults = [];
|
||||
|
||||
this._result = new Clipperz.Async.Deferred("Clipperz.Async.DeferredSynchronizer # " + this.name(), {trace:false});
|
||||
this._result.addMethod(this, 'methodResults');
|
||||
this._result.addCallback(function(someResults) {
|
||||
var cancels;
|
||||
var errors;
|
||||
var result;
|
||||
|
||||
cancels = MochiKit.Base.filter(function(aResult) { return (aResult instanceof MochiKit.Async.CancelledError)}, someResults);
|
||||
|
||||
if (cancels.length == 0) {
|
||||
errors = MochiKit.Base.filter(function(aResult) { return (aResult instanceof Error)}, someResults);
|
||||
|
||||
if (errors.length == 0) {
|
||||
// result = MochiKit.Async.succeed(someResults);
|
||||
result = someResults;
|
||||
} else {
|
||||
result = MochiKit.Async.fail(someResults);
|
||||
}
|
||||
} else {
|
||||
result = MochiKit.Async.fail(cancels[0]);
|
||||
}
|
||||
|
||||
return result;
|
||||
}/*, this._methodResults */);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
MochiKit.Base.update(Clipperz.Async.DeferredSynchronizer.prototype, {
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'name': function() {
|
||||
return this._name;
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'methods': function() {
|
||||
return this._methods;
|
||||
},
|
||||
|
||||
'methodResults': function() {
|
||||
return this._methodResults;
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'result': function() {
|
||||
return this._result;
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'numberOfMethodsDone':function() {
|
||||
return this._numberOfMethodsDone;
|
||||
},
|
||||
|
||||
'incrementNumberOfMethodsDone': function() {
|
||||
this._numberOfMethodsDone ++;
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'run': function(args, aValue) {
|
||||
var deferredResults;
|
||||
var i, c;
|
||||
|
||||
deferredResults = [];
|
||||
args = args || {};
|
||||
|
||||
c = this.methods().length;
|
||||
for (i=0; i<c; i++) {
|
||||
var deferredResult;
|
||||
var methodCalls;
|
||||
var ii, cc;
|
||||
|
||||
//Clipperz.log("TYPEOF", typeof(this.methods()[i]));
|
||||
if (typeof(this.methods()[i]) == 'function') {
|
||||
methodCalls = [ this.methods()[i] ];
|
||||
} else {
|
||||
methodCalls = this.methods()[i];
|
||||
}
|
||||
|
||||
cc = methodCalls.length;
|
||||
deferredResult = new Clipperz.Async.Deferred("Clipperz.Async.DeferredSynchronizer.run => " + this.name() + "[" + i + "]", args);
|
||||
for (ii=0; ii<cc; ii++) {
|
||||
deferredResult.addCallback(methodCalls[ii]);
|
||||
}
|
||||
deferredResult.addBoth(MochiKit.Base.method(this, 'handleMethodCallDone', i));
|
||||
|
||||
deferredResults.push(deferredResult);
|
||||
}
|
||||
|
||||
for (i=0; i<c; i++) {
|
||||
deferredResults[i].callback(aValue);
|
||||
}
|
||||
|
||||
return this.result();
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'handleMethodCallDone': function(anIndexValue, aResult) {
|
||||
this.incrementNumberOfMethodsDone();
|
||||
this.methodResults()[anIndexValue] = aResult;
|
||||
|
||||
if (this.numberOfMethodsDone() < this.methods().length) {
|
||||
// nothing to do here other than possibly log something
|
||||
} else if (this.numberOfMethodsDone() == this.methods().length) {
|
||||
this.result().callback();
|
||||
} else if (this.numberOfMethodsDone() > this.methods().length) {
|
||||
alert("Clipperz.Async.Deferred.handleMethodCallDone -> WTF!");
|
||||
// WTF!!! :(
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
__syntaxFix__: "syntax fix"
|
||||
});
|
||||
|
||||
//#############################################################################
|
||||
|
||||
MochiKit.Base.update(Clipperz.Async, {
|
||||
|
||||
'callbacks': function (aName, someFunctions, someArguments, aCallbackValue) {
|
||||
var deferredResult;
|
||||
var i, c;
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred(aName, someArguments);
|
||||
c = someFunctions.length;
|
||||
for (i=0; i<c; i++) {
|
||||
deferredResult.addCallback(someFunctions[i]);
|
||||
}
|
||||
deferredResult.callback(aCallbackValue);
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'forkAndJoin': function (aName, someMethods, args) {
|
||||
return MochiKit.Base.partial(function (aName, someMethods, args, aValue) {
|
||||
var synchronizer;
|
||||
var result;
|
||||
|
||||
args = args || {};
|
||||
synchronizer = new Clipperz.Async.DeferredSynchronizer(aName, someMethods);
|
||||
result = synchronizer.run(args, aValue);
|
||||
|
||||
return result;
|
||||
}, aName, someMethods, args);
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'collectResults': function(aName, someRequests, args) {
|
||||
return MochiKit.Base.partial(function(aName, someRequests, args, aValue) {
|
||||
var deferredResult;
|
||||
var requestKeys;
|
||||
var methods;
|
||||
|
||||
requestKeys = MochiKit.Base.keys(someRequests);
|
||||
methods = MochiKit.Base.values(someRequests);
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred(aName, args);
|
||||
deferredResult.addCallback(Clipperz.Async.forkAndJoin(aName + " [inner forkAndJoin]", methods, args));
|
||||
deferredResult.addBoth(function(someResults) {
|
||||
var returnFunction;
|
||||
var results;
|
||||
var i,c;
|
||||
var result;
|
||||
|
||||
if (someResults instanceof MochiKit.Async.CancelledError) {
|
||||
returnFunction = MochiKit.Async.fail;
|
||||
result = someResults;
|
||||
} else {
|
||||
if (someResults instanceof Error) {
|
||||
returnFunction = MochiKit.Async.fail;
|
||||
results = someResults['message'];
|
||||
} else {
|
||||
returnFunction = MochiKit.Async.succeed;
|
||||
results = someResults;
|
||||
}
|
||||
|
||||
result = {};
|
||||
|
||||
c = requestKeys.length;
|
||||
for (i=0; i<c; i++) {
|
||||
result[requestKeys[i]] = results[i];
|
||||
}
|
||||
}
|
||||
|
||||
return returnFunction.call(null, result);
|
||||
});
|
||||
deferredResult.callback(aValue);
|
||||
|
||||
return deferredResult;
|
||||
}, aName, someRequests, args);
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'collectAll': function (someDeferredObjects) {
|
||||
var deferredResult;
|
||||
|
||||
deferredResult = new MochiKit.Async.DeferredList(someDeferredObjects, false, false, false);
|
||||
deferredResult.addCallback(function (aResultList) {
|
||||
return MochiKit.Base.map(function (aResult) {
|
||||
if (aResult[0]) {
|
||||
return aResult[1];
|
||||
} else {
|
||||
throw aResult[1];
|
||||
}
|
||||
}, aResultList);
|
||||
});
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'setItem': function (anObject, aKey, aValue) {
|
||||
anObject[aKey] = aValue;
|
||||
|
||||
return anObject;
|
||||
},
|
||||
|
||||
'setItemOnObject': function (aKey, aValue, anObject) {
|
||||
anObject[aKey] = aValue;
|
||||
|
||||
return anObject;
|
||||
},
|
||||
|
||||
'setDeferredItemOnObject': function (aKey, aDeferredFunction, anObject) {
|
||||
return Clipperz.Async.callbacks("Clipperz.Async.setDeferredItemOnObject", [
|
||||
aDeferredFunction,
|
||||
MochiKit.Base.partial(Clipperz.Async.setItem, anObject, aKey)
|
||||
], {trace:false}, anObject);
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'deferredIf': function (aName, aThenBlock, anElseBlock) {
|
||||
return function (aValue) {
|
||||
var deferredResult;
|
||||
|
||||
if (!MochiKit.Base.isUndefinedOrNull(aValue) && aValue) {
|
||||
deferredResult = Clipperz.Async.callbacks(aName + " <then>", aThenBlock, null, aValue);
|
||||
} else {
|
||||
deferredResult = Clipperz.Async.callbacks(aName + " <else>", anElseBlock, null, aValue);
|
||||
}
|
||||
|
||||
return deferredResult;
|
||||
}
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'log': function(aMessage, aResult) {
|
||||
if (CLIPPERZ_DEFERRED_LOGGING_ENABLED) {
|
||||
Clipperz.log(aMessage + " ", aResult);
|
||||
}
|
||||
|
||||
return aResult;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'deferredCompare': function (aComparator, aDeferred, bDeferred) {
|
||||
var deferredResult;
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("Clipperz.Async.deferredCompare", {trace:false});
|
||||
deferredResult.addCallback(Clipperz.Async.collectAll, [aDeferred, bDeferred]);
|
||||
deferredResult.addCallback(function (someResults) {
|
||||
var result;
|
||||
|
||||
if (aComparator(someResults[0], someResults[1]) > 0) {
|
||||
result = MochiKit.Async.succeed();
|
||||
} else {
|
||||
result = MochiKit.Async.fail();
|
||||
};
|
||||
|
||||
return result;
|
||||
});
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'insertIntoSortedArray': function (anObject, aDeferredComparator, aSortedResult) {
|
||||
var deferredResult;
|
||||
var i, c;
|
||||
|
||||
if (aSortedResult.length == 0) {
|
||||
deferredResult = MochiKit.Async.succeed([anObject]);
|
||||
} else {
|
||||
deferredResult = new Clipperz.Async.Deferred("Clipperz.Async.insertIntoSortedArray", {trace:false});
|
||||
c = aSortedResult.length + 1;
|
||||
for (i=0; i<c; i++) {
|
||||
deferredResult.addCallback(function (aDeferredComparator, aObject, bObject, aContext) {
|
||||
var innerDeferredResult;
|
||||
|
||||
innerDeferredResult = new Clipperz.Async.Deferred("Clipperz.Async.insertIntoSortedArray <inner compare>", {trace:false});
|
||||
innerDeferredResult.addCallback(aDeferredComparator, aObject, bObject);
|
||||
innerDeferredResult.addErrback(MochiKit.Async.fail, aContext);
|
||||
innerDeferredResult.callback();
|
||||
|
||||
return innerDeferredResult;
|
||||
}, aDeferredComparator, anObject, aSortedResult[i], i);
|
||||
}
|
||||
deferredResult.addMethod(aSortedResult, 'push', anObject);
|
||||
deferredResult.addErrback(function (anError) {
|
||||
aSortedResult.splice(anError.message, 0, anObject);
|
||||
})
|
||||
deferredResult.addBoth(MochiKit.Async.succeed, aSortedResult);
|
||||
deferredResult.callback();
|
||||
}
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'deferredSort': function (aDeferredComparator, someObjects) {
|
||||
var deferredResult;
|
||||
var i, c;
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("Clipperz.Async.deferredSort", {trace:false});
|
||||
c = someObjects.length;
|
||||
for (i=0; i<c; i++) {
|
||||
deferredResult.addCallback(Clipperz.Async.insertIntoSortedArray, someObjects[i], aDeferredComparator);
|
||||
if ((i % 50) == 0) {
|
||||
// Clipperz.log("######### sort wait ##########");
|
||||
deferredResult.addCallback(MochiKit.Async.wait, 0.5);
|
||||
}
|
||||
}
|
||||
deferredResult.callback([]);
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'deferredFilter': function (aFunction, someObjects) {
|
||||
var deferredResult;
|
||||
var i, c;
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("Clipperz.Async.deferredFilter", {trace:false});
|
||||
c = someObjects.length;
|
||||
for (i=0; i<c; i++) {
|
||||
deferredResult.addCallback(function (aFunction, anObject, anIndex, aResult) {
|
||||
var innerDeferredResult;
|
||||
|
||||
innerDeferredResult = new Clipperz.Async.Deferred("Clipperz.Async.deferredFilter <inner - " + anIndex + ">", {trace:false});
|
||||
innerDeferredResult.addCallback(aFunction, anObject);
|
||||
innerDeferredResult.addCallback(function (aFilterResult) {
|
||||
if (aFilterResult) {
|
||||
aResult.push(anObject);
|
||||
};
|
||||
});
|
||||
innerDeferredResult.addBoth(MochiKit.Async.succeed, aResult);
|
||||
innerDeferredResult.callback();
|
||||
|
||||
return innerDeferredResult;
|
||||
}, aFunction, someObjects[i], i);
|
||||
}
|
||||
deferredResult.callback([]);
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
'forEach': function (aFunction) {
|
||||
return MochiKit.Base.partial(function (aFunction, anIterable) {
|
||||
MochiKit.Iter.forEach(anIterable, aFunction);
|
||||
}, aFunction);
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'or': function (someValues) {
|
||||
return Clipperz.Async.callbacks("Clipperz.Async.or", [
|
||||
MochiKit.Base.values,
|
||||
MochiKit.Base.flattenArguments,
|
||||
//function (aValue) { Clipperz.log("Record.hasAnyCleanTextData - flatten", aValue); return aValue; },
|
||||
function(someInnerValues) {
|
||||
return MochiKit.Iter.some(someInnerValues, MochiKit.Base.operator.identity);
|
||||
}
|
||||
], {trace:false}, someValues);
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'clearResult': function () {},
|
||||
|
||||
//=========================================================================
|
||||
__syntaxFix__: "syntax fix"
|
||||
});
|
||||
|
||||
|
||||
//#############################################################################
|
||||
|
||||
CLIPPERZ_DEFERRED_LOGGING_ENABLED = true;
|
||||
CLIPPERZ_DEFERRED_TRACING_ENABLED = false;
|
||||
CLIPPERZ_DEFERRED_CALL_LOGGING_ENABLED = false;
|
||||
514
frontend/delta/js/Clipperz/Base.js
Normal file
514
frontend/delta/js/Clipperz/Base.js
Normal file
@@ -0,0 +1,514 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
|
||||
if (typeof(Clipperz.Base) == 'undefined') { Clipperz.Base = {}; }
|
||||
|
||||
Clipperz.Base.VERSION = "0.2";
|
||||
Clipperz.Base.NAME = "Clipperz.Base";
|
||||
|
||||
MochiKit.Base.update(Clipperz.Base, {
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'__repr__': function () {
|
||||
return "[" + this.NAME + " " + this.VERSION + "]";
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'toString': function () {
|
||||
return this.__repr__();
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'itemgetter': function (aKeyPath) {
|
||||
// return MochiKit.Base.compose.apply(null, [MochiKit.Base.itemgetter('key3')]);
|
||||
return MochiKit.Base.compose.apply(null,
|
||||
MochiKit.Base.map(
|
||||
MochiKit.Base.itemgetter,
|
||||
MochiKit.Iter.reversed(
|
||||
aKeyPath.split('.')
|
||||
)
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'isUrl': function (aValue) {
|
||||
return (MochiKit.Base.urlRegExp.test(aValue));
|
||||
},
|
||||
|
||||
'isEmail': function (aValue) {
|
||||
return (MochiKit.Base.emailRegExp.test(aValue));
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'caseInsensitiveCompare': function (a, b) {
|
||||
return MochiKit.Base.compare(a.toLowerCase(), b.toLowerCase());
|
||||
},
|
||||
|
||||
'reverseComparator': function (aComparator) {
|
||||
return MochiKit.Base.compose(function(aResult) { return -aResult; }, aComparator);
|
||||
},
|
||||
|
||||
'caseInsensitiveKeyComparator': function (aKey) {
|
||||
return function (a, b) {
|
||||
return MochiKit.Base.compare(a[aKey].toLowerCase(), b[aKey].toLowerCase());
|
||||
}
|
||||
},
|
||||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
'dependsOn': function(module, deps) {
|
||||
if (!(module in Clipperz)) {
|
||||
MochiKit[module] = {};
|
||||
}
|
||||
|
||||
if (typeof(dojo) != 'undefined') {
|
||||
dojo.provide('Clipperz.' + module);
|
||||
}
|
||||
for (var i = 0; i < deps.length; i++) {
|
||||
if (typeof(dojo) != 'undefined') {
|
||||
dojo.require('Clipperz.' + deps[i]);
|
||||
}
|
||||
if (typeof(JSAN) != 'undefined') {
|
||||
JSAN.use('Clipperz.' + deps[i], []);
|
||||
}
|
||||
if (!(deps[i] in Clipperz)) {
|
||||
throw 'Clipperz.' + module + ' depends on Clipperz.' + deps[i] + '!'
|
||||
}
|
||||
}
|
||||
},
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'trim': function (aValue) {
|
||||
return aValue.replace(/^\s+|\s+$/g, "");
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'stringToByteArray': function (aValue) {
|
||||
var result;
|
||||
var i, c;
|
||||
|
||||
result = [];
|
||||
|
||||
c = aValue.length;
|
||||
for (i=0; i<c; i++) {
|
||||
result[i] = aValue.charCodeAt(i);
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//.........................................................................
|
||||
|
||||
'byteArrayToString': function (anArrayOfBytes) {
|
||||
var result;
|
||||
var i, c;
|
||||
|
||||
result = "";
|
||||
|
||||
c = anArrayOfBytes.length;
|
||||
for (i=0; i<c; i++) {
|
||||
result += String.fromCharCode(anArrayOfBytes[i]);
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'getValueForKeyInFormContent': function (aFormContent, aKey) {
|
||||
return aFormContent[1][MochiKit.Base.find(aFormContent[0], aKey)];
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'indexOfObjectInArray': function(anObject, anArray) {
|
||||
var result;
|
||||
var i, c;
|
||||
|
||||
result = -1;
|
||||
|
||||
c = anArray.length;
|
||||
for (i=0; ((i<c) && (result < 0)); i++) {
|
||||
if (anArray[i] === anObject) {
|
||||
result = i;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'removeObjectAtIndexFromArray': function(anIndex, anArray) {
|
||||
anArray.splice(anIndex, 1);
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'removeObjectFromArray': function(anObject, anArray) {
|
||||
var objectIndex;
|
||||
|
||||
objectIndex = Clipperz.Base.indexOfObjectInArray(anObject, anArray);
|
||||
if (objectIndex > -1) {
|
||||
Clipperz.Base.removeObjectAtIndexFromArray(objectIndex, anArray);
|
||||
} else {
|
||||
Clipperz.log("Trying to remove an object not present in the array");
|
||||
throw Clipperz.Base.exception.ObjectNotFound;
|
||||
}
|
||||
},
|
||||
|
||||
'removeFromArray': function(anArray, anObject) {
|
||||
return Clipperz.Base.removeObjectFromArray(anObject, anArray);
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'splitStringAtFixedTokenSize': function(aString, aTokenSize) {
|
||||
var result;
|
||||
var stringToProcess;
|
||||
|
||||
stringToProcess = aString;
|
||||
result = [];
|
||||
if (stringToProcess != null) {
|
||||
while (stringToProcess.length > aTokenSize) {
|
||||
result.push(stringToProcess.substring(0, aTokenSize));
|
||||
stringToProcess = stringToProcess.substring(aTokenSize);
|
||||
}
|
||||
|
||||
result.push(stringToProcess);
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'objectType': function(anObject) {
|
||||
var result;
|
||||
|
||||
if (anObject == null) {
|
||||
result = null;
|
||||
} else {
|
||||
result = typeof(anObject);
|
||||
|
||||
if (result == "object") {
|
||||
if (anObject instanceof Array) {
|
||||
result = 'array'
|
||||
} else if (anObject.constructor == Boolean) {
|
||||
result = 'boolean'
|
||||
} else if (anObject instanceof Date) {
|
||||
result = 'date'
|
||||
} else if (anObject instanceof Error) {
|
||||
result = 'error'
|
||||
} else if (anObject instanceof Function) {
|
||||
result = 'function'
|
||||
} else if (anObject.constructor == Number) {
|
||||
result = 'number'
|
||||
} else if (anObject.constructor == String) {
|
||||
result = 'string'
|
||||
} else if (anObject instanceof Object) {
|
||||
result = 'object'
|
||||
} else {
|
||||
throw Clipperz.Base.exception.UnknownType;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'escapeHTML': function(aValue) {
|
||||
var result;
|
||||
|
||||
result = aValue;
|
||||
result = result.replace(/</g, "<");
|
||||
result = result.replace(/>/g, ">");
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'deepClone': function(anObject) {
|
||||
var result;
|
||||
|
||||
result = Clipperz.Base.evalJSON(Clipperz.Base.serializeJSON(anObject));
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
// 'deepCompare': function (aObject, bObject) {
|
||||
// return (Clipperz.Base.serializeJSON(aObject) == Clipperz.Base.serializeJSON(bObject));
|
||||
// },
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'evalJSON': function(aString) {
|
||||
return JSON.parse(aString);
|
||||
},
|
||||
|
||||
'serializeJSON': function(anObject) {
|
||||
return JSON.stringify(anObject);
|
||||
},
|
||||
|
||||
'formatJSON': function (anObject, sIndent) {
|
||||
var realTypeOf = function (v) {
|
||||
if (typeof(v) == "object") {
|
||||
if (v === null) return "null";
|
||||
if (v.constructor == (new Array).constructor) return "array";
|
||||
if (v.constructor == (new Date).constructor) return "date";
|
||||
if (v.constructor == (new RegExp).constructor) return "regex";
|
||||
return "object";
|
||||
}
|
||||
return typeof(v);
|
||||
};
|
||||
|
||||
// function FormatJSON(oData, sIndent) {
|
||||
if (arguments.length < 2) {
|
||||
var sIndent = "";
|
||||
}
|
||||
// var sIndentStyle = " ";
|
||||
var sIndentStyle = " ";
|
||||
var sDataType = realTypeOf(anObject);
|
||||
|
||||
// open object
|
||||
if (sDataType == "array") {
|
||||
if (anObject.length == 0) {
|
||||
return "[]";
|
||||
}
|
||||
var sHTML = "[";
|
||||
} else if (sDataType == "object") {
|
||||
var sHTML = "{";
|
||||
} else {
|
||||
return "{}";
|
||||
}
|
||||
// } else {
|
||||
// var iCount = 0;
|
||||
// $.each(anObject, function() {
|
||||
// iCount++;
|
||||
// return;
|
||||
// });
|
||||
// if (iCount == 0) { // object is empty
|
||||
// return "{}";
|
||||
// }
|
||||
// var sHTML = "{";
|
||||
// }
|
||||
|
||||
// loop through items
|
||||
var iCount = 0;
|
||||
// $.each(anObject, function(sKey, vValue) {
|
||||
MochiKit.Iter.forEach(MochiKit.Base.keys(anObject), function(sKey) {
|
||||
var vValue = anObject[sKey];
|
||||
|
||||
if (iCount > 0) {
|
||||
sHTML += ",";
|
||||
}
|
||||
if (sDataType == "array") {
|
||||
sHTML += ("\n" + sIndent + sIndentStyle);
|
||||
} else {
|
||||
sHTML += ("\n" + sIndent + sIndentStyle + "\"" + sKey + "\"" + ": ");
|
||||
}
|
||||
|
||||
// display relevant data type
|
||||
switch (realTypeOf(vValue)) {
|
||||
case "array":
|
||||
case "object":
|
||||
sHTML += Clipperz.Base.formatJSON(vValue, (sIndent + sIndentStyle));
|
||||
break;
|
||||
case "boolean":
|
||||
case "number":
|
||||
sHTML += vValue.toString();
|
||||
break;
|
||||
case "null":
|
||||
sHTML += "null";
|
||||
break;
|
||||
case "string":
|
||||
sHTML += ("\"" + vValue + "\"");
|
||||
break;
|
||||
default:
|
||||
sHTML += ("TYPEOF: " + typeof(vValue));
|
||||
}
|
||||
|
||||
// loop
|
||||
iCount++;
|
||||
});
|
||||
|
||||
// close object
|
||||
if (sDataType == "array") {
|
||||
sHTML += ("\n" + sIndent + "]");
|
||||
} else {
|
||||
sHTML += ("\n" + sIndent + "}");
|
||||
}
|
||||
|
||||
// return
|
||||
return sHTML;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'mergeItems': function (anArrayOfValues) {
|
||||
var result;
|
||||
var i, c;
|
||||
|
||||
result = {};
|
||||
|
||||
c = anArrayOfValues.length;
|
||||
for (i=0; i<c; i++) {
|
||||
result[anArrayOfValues[i][0]] = anArrayOfValues[i][1];
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'map': function (fn, lstObj/*, lst... */) {
|
||||
var result;
|
||||
|
||||
if (MochiKit.Base.isArrayLike(lstObj)) {
|
||||
result = MochiKit.Base.map.apply(this, arguments);
|
||||
} else {
|
||||
var keys;
|
||||
var values;
|
||||
var computedValues;
|
||||
|
||||
keys = MochiKit.Base.keys(lstObj);
|
||||
values = MochiKit.Base.values(lstObj);
|
||||
computedValues = MochiKit.Base.map(fn, values);
|
||||
|
||||
result = Clipperz.Base.mergeItems(MochiKit.Base.zip(keys, computedValues));
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'sanitizeString': function(aValue) {
|
||||
var result;
|
||||
|
||||
if (Clipperz.Base.objectType(aValue) == 'string') {
|
||||
result = aValue;
|
||||
result = result.replace(/</img,"<");
|
||||
result = result.replace(/>/img,">");
|
||||
} else {
|
||||
result = aValue;
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'module': function(aValue) {
|
||||
// aValue = 'Clipperz.PM.Compact'
|
||||
//
|
||||
// if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
|
||||
// if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
|
||||
// if (typeof(Clipperz.PM.UI.Common.Components) == 'undefined') { Clipperz.PM.UI.Common.Components = {}; }
|
||||
|
||||
var currentScope;
|
||||
var pathElements;
|
||||
var i,c;
|
||||
|
||||
currentScope = window;
|
||||
pathElements = aValue.split('.');
|
||||
c = pathElements.length;
|
||||
for (i=0; i<c; i++) {
|
||||
if (typeof(currentScope[pathElements[i]]) == 'undefined') {
|
||||
currentScope[pathElements[i]] = {};
|
||||
}
|
||||
|
||||
currentScope = currentScope[pathElements[i]];
|
||||
}
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'exception': {
|
||||
'AbstractMethod': new MochiKit.Base.NamedError("Clipperz.Base.exception.AbstractMethod"),
|
||||
'UnknownType': new MochiKit.Base.NamedError("Clipperz.Base.exception.UnknownType"),
|
||||
'VulnerabilityIssue': new MochiKit.Base.NamedError("Clipperz.Base.exception.VulnerabilityIssue"),
|
||||
'MandatoryParameter': new MochiKit.Base.NamedError("Clipperz.Base.exception.MandatoryParameter"),
|
||||
'ObjectNotFound': new MochiKit.Base.NamedError("Clipperz.Base.exception.ObjectNotFound"),
|
||||
'raise': function (aName) {
|
||||
throw Clipperz.Base.exception[aName];
|
||||
}
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'extend': YAHOO.extendX,
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
__syntaxFix__: "syntax fix"
|
||||
|
||||
});
|
||||
|
||||
// Original regExp courtesy of John Gruber: http://daringfireball.net/2009/11/liberal_regex_for_matching_urls
|
||||
// Updated to match Clipperz usage pattern.
|
||||
//MochiKit.Base.urlRegExp = new RegExp(/\b(([\w-]+:\/\/?|www[.])[^\s()<>]+(?:\([\w\d]+\)|([^[:punct:]\s]|\/)))/);
|
||||
MochiKit.Base.urlRegExp = new RegExp(/^((([\w-]+:\/\/?)|(www\.))[^\s()<>]+((?:\([\w\d]+\)|([^[:punct:]\s]|\/)))?)/);
|
||||
|
||||
// RegExp found here: http://www.tipsntracks.com/117/validate-an-email-address-using-regular-expressions.html
|
||||
MochiKit.Base.emailRegExp = new RegExp(/^([a-zA-Z0-9_\-\.]+)@(([a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3}))|(([01]?\d\d?|2[0-4]\d|25[0-5])\.){3}([01]?\d\d?|25[0-5]|2[0-4]\d))$/);
|
||||
|
||||
|
||||
MochiKit.Base.registerComparator('Object dummy comparator',
|
||||
function(a, b) {
|
||||
return ((a.constructor == Object) && (b.constructor == Object));
|
||||
},
|
||||
function(a, b) {
|
||||
var result;
|
||||
var aKeys;
|
||||
var bKeys;
|
||||
|
||||
aKeys = MochiKit.Base.keys(a).sort();
|
||||
bKeys = MochiKit.Base.keys(b).sort();
|
||||
result = MochiKit.Base.compare(aKeys, bKeys);
|
||||
|
||||
if (result == 0) {
|
||||
var i, c;
|
||||
|
||||
c = aKeys.length;
|
||||
for (i=0; (i<c) && (result == 0); i++) {
|
||||
result = MochiKit.Base.compare(a[aKeys[i]], b[bKeys[i]]);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
true
|
||||
);
|
||||
1459
frontend/delta/js/Clipperz/ByteArray.js
Normal file
1459
frontend/delta/js/Clipperz/ByteArray.js
Normal file
File diff suppressed because it is too large
Load Diff
344
frontend/delta/js/Clipperz/CSVProcessor.js
Normal file
344
frontend/delta/js/Clipperz/CSVProcessor.js
Normal file
@@ -0,0 +1,344 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
|
||||
|
||||
|
||||
Clipperz.CSVProcessor = function(args) {
|
||||
args = args || {};
|
||||
|
||||
// this._status = undefined;
|
||||
// this._error_input = undefined;
|
||||
// this._string = undefined;
|
||||
// this._fields = undefined;
|
||||
|
||||
this._quoteChar = args['quoteChar'] || "\042";
|
||||
this._eol = args['eol'] || "";
|
||||
this._escapeChar = args['escapeChar'] || "\042";
|
||||
this._separatorChar = args['separatorChar'] || ",";
|
||||
this._binary = args['binary'] || false;
|
||||
this._alwaysQuote = args['alwaysQuote'] || false;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
||||
Clipperz.CSVProcessor.prototype = MochiKit.Base.update(null, {
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'quoteChar': function() {
|
||||
return this._quoteChar;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'eol': function() {
|
||||
return this._eol;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'escapeChar': function() {
|
||||
return this._escapeChar;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'separatorChar': function() {
|
||||
return this._separatorChar;
|
||||
},
|
||||
|
||||
'setSeparatorChar': function(aValue) {
|
||||
this._separatorChar = aValue;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'binary': function() {
|
||||
return this._binary;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'alwaysQuote': function() {
|
||||
return this._alwaysQuote;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
'parse': function(aValue) {
|
||||
var result;
|
||||
var lines;
|
||||
var parameter;
|
||||
|
||||
//Clipperz.logDebug(">>> CSVProcessor.parse");
|
||||
result = [];
|
||||
|
||||
lines = aValue.replace(/\r?\n/g, "\n").replace(/^\n* /g, "").replace(/\n$/g, "");;
|
||||
parameter = {
|
||||
line: lines
|
||||
}
|
||||
|
||||
do {
|
||||
var fields;
|
||||
|
||||
fields = this.parseLine(parameter);
|
||||
|
||||
if (fields != null) {
|
||||
result.push(fields);
|
||||
}
|
||||
|
||||
parameter.line = parameter.line.replace(/^\n* /g, "").replace(/\n$/g, "");
|
||||
|
||||
//Clipperz.logDebug("line: '" + parameter.line + "'");
|
||||
} while (parameter.line != "");
|
||||
//Clipperz.logDebug("--- CSVProcessor.parse - result: " + Clipperz.Base.serializeJSON(result));
|
||||
//Clipperz.logDebug("<<< CSVProcessor.parse");
|
||||
|
||||
return result;
|
||||
},
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'deferredParse_core': function(aContext) {
|
||||
var deferredResult;
|
||||
|
||||
if (aContext.line == "") {
|
||||
deferredResult = MochiKit.Async.succeed(aContext.result);
|
||||
} else {
|
||||
var fields;
|
||||
|
||||
fields = this.parseLine(aContext);
|
||||
if (fields != null) {
|
||||
aContext.result.push(fields);
|
||||
}
|
||||
|
||||
aContext.line = aContext.line.replace(/^\n*/g, "").replace(/\n$/g, "");
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("CVSProcessor.deferredParse_core");
|
||||
// deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'importProcessorProgressUpdate', {status:'processing', size:aContext.size, progress:(aContext.size - aContext.line.length)});
|
||||
deferredResult.addCallbackPass(MochiKit.Signal.signal, this, 'importProcessorProgressUpdate', {status:'processing', size:aContext.size, progress:(aContext.size - aContext.line.length)});
|
||||
deferredResult.addCallback(MochiKit.Async.wait, 0.2);
|
||||
deferredResult.addMethod(this, 'deferredParse_core')
|
||||
deferredResult.callback(aContext);
|
||||
}
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//.........................................................................
|
||||
|
||||
'deferredParse': function(aValue) {
|
||||
var deferredResult;
|
||||
var lines;
|
||||
var context;
|
||||
|
||||
lines = aValue.replace(/\r?\n/g, "\n").replace(/^\n*/g, "").replace(/\n$/g, "");
|
||||
|
||||
context = {
|
||||
line: lines,
|
||||
size: lines.length,
|
||||
result: []
|
||||
}
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("CSVProcessor.deferredParse");
|
||||
deferredResult.addMethod(this, 'deferredParse_core');
|
||||
deferredResult.callback(context);
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'parseLine': function(aParameter) {
|
||||
var result;
|
||||
var palatable;
|
||||
var line;
|
||||
var processedField;
|
||||
|
||||
result = [];
|
||||
|
||||
do {
|
||||
processedField = this.parseField(aParameter);
|
||||
if (processedField != null) {
|
||||
result.push(processedField)
|
||||
};
|
||||
} while (processedField != null);
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'parseField': function(aParameter) {
|
||||
var result;
|
||||
|
||||
var inQuotes;
|
||||
var validRegExp;
|
||||
var singleQuoteBeginRegexp;
|
||||
var escapedQuoteBeginRegexp;
|
||||
var singleQuoteCommaEndRegexp;
|
||||
var singleQuoteNewLineEndRegexp;
|
||||
var commaBeginRegexp;
|
||||
var newlineRegexp;
|
||||
|
||||
|
||||
singleQuoteBeginRegexp = new RegExp("^" + '\\' + this.quoteChar());
|
||||
escapedQuoteBeginRegexp = new RegExp("^" + '\\' + this.escapeChar() + '\\' + this.quoteChar());
|
||||
singleQuoteCommaEndRegexp = new RegExp("^" + '\\' + this.quoteChar() + '\\' + this.separatorChar());
|
||||
singleQuoteNewLineEndRegexp = new RegExp("^" + '\\' + this.quoteChar() + "\n");
|
||||
commaBeginRegexp = new RegExp("^" + '\\' + this.separatorChar());
|
||||
newlineRegexp = new RegExp("^\n");
|
||||
|
||||
inQuotes = false;
|
||||
|
||||
//Clipperz.logDebug("#################################### '" + aParameter.line + "'");
|
||||
if (aParameter.line == "") {
|
||||
if (aParameter.isThereAnEmptyFinalField == true) {
|
||||
aParameter.isThereAnEmptyFinalField = false;
|
||||
result = "";
|
||||
} else {
|
||||
result = null;
|
||||
}
|
||||
} else {
|
||||
if (this.binary()) {
|
||||
validRegexp = /^./;
|
||||
// validRegexp = /^[^\\]/;
|
||||
} else {
|
||||
validRegexp = /^[\t\040-\176]/;
|
||||
}
|
||||
|
||||
try {
|
||||
var done;
|
||||
|
||||
done = false;
|
||||
result = "";
|
||||
|
||||
while (!done) {
|
||||
if (aParameter.line.length < 1) {
|
||||
//Clipperz.logDebug("---> 1: '" + aParameter.line.replace(/\n/g, "\\n") + "'");
|
||||
if (inQuotes == true) {
|
||||
//Clipperz.logDebug("---> 1.1: '" + aParameter.line.replace(/\n/g, "\\n") + "'");
|
||||
throw new Error("CSV Parsing error; end of string, missing closing double-quote...");
|
||||
} else {
|
||||
//Clipperz.logDebug("---> 1.2: '" + aParameter.line.replace(/\n/g, "\\n") + "'");
|
||||
done = true;
|
||||
}
|
||||
} else if (escapedQuoteBeginRegexp.test(aParameter.line)) {
|
||||
//Clipperz.logDebug("---> 2.1: '" + aParameter.line.replace(/\n/g, "\\n") + "'");
|
||||
result += this.quoteChar();
|
||||
aParameter.line = aParameter.line.substr(2, aParameter.line.length - 1);
|
||||
//Clipperz.logDebug("<--- 2.2: '" + aParameter.line.replace(/\n/g, "\\n") + "'");
|
||||
} else if (singleQuoteBeginRegexp.test(aParameter.line)) {
|
||||
//Clipperz.logDebug("---> 3: '" + aParameter.line.replace(/\n/g, "\\n") + "'");
|
||||
if (inQuotes == true) {
|
||||
if (aParameter.line.length == 1) {
|
||||
//Clipperz.logDebug("---> 3.1: '" + aParameter.line.replace(/\n/g, "\\n") + "'");
|
||||
aParameter.line = '';
|
||||
done = true;
|
||||
} else if (singleQuoteCommaEndRegexp.test(aParameter.line)) {
|
||||
//Clipperz.logDebug("---> 3.3: '" + aParameter.line.replace(/\n/g, "\\n") + "'");
|
||||
aParameter.line = aParameter.line.substr(2, aParameter.line.length - 1);
|
||||
done = true;
|
||||
//Clipperz.logDebug("<--- 3.3: '" + aParameter.line.replace(/\n/g, "\\n") + "'");
|
||||
} else if (singleQuoteNewLineEndRegexp.test(aParameter.line)) {
|
||||
aParameter.line = aParameter.line.substr(1, aParameter.line.length - 1);
|
||||
done = true;
|
||||
} else {
|
||||
throw new Error("CSV Parsing error; double-quote, followed by undesirable character (bad character sequence)... " + aParameter.line);
|
||||
}
|
||||
} else {
|
||||
//Clipperz.logDebug("---> 4: '" + aParameter.line.replace(/\n/g, "\\n") + "'");
|
||||
if (result == "") {
|
||||
//Clipperz.logDebug("---> 4.1: '" + aParameter.line.replace(/\n/g, "\\n") + "'");
|
||||
inQuotes = true;
|
||||
aParameter.line = aParameter.line.substr(1, aParameter.line.length - 1);
|
||||
//Clipperz.logDebug("<--- 4.1: '" + aParameter.line.replace(/\n/g, "\\n") + "'");
|
||||
} else {
|
||||
throw new Error("CSV Parsing error; double-quote, outside of double-quotes (bad character sequence)...");
|
||||
}
|
||||
}
|
||||
} else if (commaBeginRegexp.test(aParameter.line)) {
|
||||
//Clipperz.logDebug("---> 5: '" + aParameter.line.replace(/\n/g, "\\n") + "'");
|
||||
if (inQuotes) {
|
||||
//Clipperz.logDebug("---> 5.1: '" + aParameter.line.replace(/\n/g, "\\n") + "'");
|
||||
result += aParameter.line.substr(0 ,1);
|
||||
aParameter.line = aParameter.line.substr(1, aParameter.line.length - 1);
|
||||
//Clipperz.logDebug("<--- 5.1: '" + aParameter.line.replace(/\n/g, "\\n") + "'");
|
||||
} else {
|
||||
//Clipperz.logDebug("---> 5.2: '" + aParameter.line.replace(/\n/g, "\\n") + "'");
|
||||
aParameter.line = aParameter.line.substr(1, aParameter.line.length - 1);
|
||||
if (newlineRegexp.test(aParameter.line) || aParameter.line == "") {
|
||||
//Clipperz.logDebug("######");
|
||||
aParameter.isThereAnEmptyFinalField = true;
|
||||
};
|
||||
done = true;
|
||||
//Clipperz.logDebug("<--- 5.2: '" + aParameter.line.replace(/\n/g, "\\n") + "'");
|
||||
}
|
||||
} else if (validRegexp.test(aParameter.line)) {
|
||||
//Clipperz.logDebug("---> 6: '" + aParameter.line.replace(/\n/g, "\\n") + "'");
|
||||
result += aParameter.line.substr(0, 1);
|
||||
aParameter.line = aParameter.line.substr(1, aParameter.line.length - 1);
|
||||
//Clipperz.logDebug("<--- 6: '" + aParameter.line.replace(/\n/g, "\\n") + "'");
|
||||
} else if (newlineRegexp.test(aParameter.line)) {
|
||||
if (inQuotes == true) {
|
||||
result += aParameter.line.substr(0 ,1);
|
||||
aParameter.line = aParameter.line.substr(1, aParameter.line.length - 1);
|
||||
} else {
|
||||
if (result == "") {
|
||||
if (aParameter.isThereAnEmptyFinalField == true) {
|
||||
aParameter.isThereAnEmptyFinalField = false;
|
||||
} else {
|
||||
result = null;
|
||||
}
|
||||
}
|
||||
|
||||
done = true;
|
||||
}
|
||||
} else {
|
||||
throw new Error("CSV Parsing error; an undesirable character... '" + aParameter.line.substr(0,1) + "'");
|
||||
}
|
||||
}
|
||||
} catch(exception) {
|
||||
Clipperz.logError(exception.message);
|
||||
// result = null;
|
||||
throw exception;
|
||||
}
|
||||
}
|
||||
|
||||
//if (result != null) {
|
||||
// Clipperz.logDebug("<=== result: '" + result.replace(/\n/g, "\\n") + "'");
|
||||
//} else {
|
||||
// Clipperz.logDebug("<=== result: NULL");
|
||||
//}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
__syntaxFix__: "syntax fix"
|
||||
});
|
||||
|
||||
|
||||
859
frontend/delta/js/Clipperz/Crypto/AES.js
Normal file
859
frontend/delta/js/Clipperz/Crypto/AES.js
Normal file
@@ -0,0 +1,859 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
try { if (typeof(Clipperz.ByteArray) == 'undefined') { throw ""; }} catch (e) {
|
||||
throw "Clipperz.Crypto.AES depends on Clipperz.ByteArray!";
|
||||
}
|
||||
|
||||
// Dependency commented to avoid a circular reference
|
||||
//try { if (typeof(Clipperz.Crypto.PRNG) == 'undefined') { throw ""; }} catch (e) {
|
||||
// throw "Clipperz.Crypto.AES depends on Clipperz.Crypto.PRNG!";
|
||||
//}
|
||||
|
||||
if (typeof(Clipperz.Crypto.AES) == 'undefined') { Clipperz.Crypto.AES = {}; }
|
||||
|
||||
//#############################################################################
|
||||
|
||||
Clipperz.Crypto.AES.DeferredExecutionContext = function(args) {
|
||||
args = args || {};
|
||||
|
||||
this._key = args.key;
|
||||
this._message = args.message;
|
||||
this._result = args.message.clone();
|
||||
this._nonce = args.nonce;
|
||||
this._messageLength = this._message.length();
|
||||
|
||||
this._messageArray = this._message.arrayValues();
|
||||
this._resultArray = this._result.arrayValues();
|
||||
this._nonceArray = this._nonce.arrayValues();
|
||||
|
||||
this._executionStep = 0;
|
||||
|
||||
// this._elaborationChunkSize = 1024; // 4096; // 16384; // 4096;
|
||||
this._elaborationChunks = 10;
|
||||
this._pauseTime = 0.02; // 0.02 // 0.2;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
Clipperz.Crypto.AES.DeferredExecutionContext.prototype = MochiKit.Base.update(null, {
|
||||
|
||||
'key': function() {
|
||||
return this._key;
|
||||
},
|
||||
|
||||
'message': function() {
|
||||
return this._message;
|
||||
},
|
||||
|
||||
'messageLength': function() {
|
||||
return this._messageLength;
|
||||
},
|
||||
|
||||
'result': function() {
|
||||
return new Clipperz.ByteArray(this.resultArray());
|
||||
},
|
||||
|
||||
'nonce': function() {
|
||||
return this._nonce;
|
||||
},
|
||||
|
||||
'messageArray': function() {
|
||||
return this._messageArray;
|
||||
},
|
||||
|
||||
'resultArray': function() {
|
||||
return this._resultArray;
|
||||
},
|
||||
|
||||
'nonceArray': function() {
|
||||
return this._nonceArray;
|
||||
},
|
||||
|
||||
'elaborationChunkSize': function() {
|
||||
// return Clipperz.Crypto.AES.DeferredExecution.chunkSize;
|
||||
// return this._elaborationChunkSize;
|
||||
return (this._elaborationChunks * 1024);
|
||||
},
|
||||
|
||||
'executionStep': function() {
|
||||
return this._executionStep;
|
||||
},
|
||||
|
||||
'setExecutionStep': function(aValue) {
|
||||
this._executionStep = aValue;
|
||||
},
|
||||
|
||||
'tuneExecutionParameters': function (anElapsedTime) {
|
||||
//var originalChunks = this._elaborationChunks;
|
||||
if (anElapsedTime > 0) {
|
||||
this._elaborationChunks = Math.round(this._elaborationChunks * ((anElapsedTime + 1000)/(anElapsedTime * 2)));
|
||||
}
|
||||
//Clipperz.log("tuneExecutionParameters - elapsedTime: " + anElapsedTime + /*originalChunks,*/ " chunks # " + this._elaborationChunks + " [" + this._executionStep + " / " + this._messageLength + "]");
|
||||
},
|
||||
|
||||
'pause': function(aValue) {
|
||||
// return MochiKit.Async.wait(Clipperz.Crypto.AES.DeferredExecution.pauseTime, aValue);
|
||||
return MochiKit.Async.wait(this._pauseTime, aValue);
|
||||
},
|
||||
|
||||
'isDone': function () {
|
||||
return (this._executionStep >= this._messageLength);
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
__syntaxFix__: "syntax fix"
|
||||
|
||||
});
|
||||
|
||||
//#############################################################################
|
||||
|
||||
Clipperz.Crypto.AES.Key = function(args) {
|
||||
args = args || {};
|
||||
|
||||
this._key = args.key;
|
||||
this._keySize = args.keySize || this.key().length();
|
||||
|
||||
if (this.keySize() == 128/8) {
|
||||
this._b = 176;
|
||||
this._numberOfRounds = 10;
|
||||
} else if (this.keySize() == 256/8) {
|
||||
this._b = 240;
|
||||
this._numberOfRounds = 14;
|
||||
} else {
|
||||
Clipperz.logError("AES unsupported key size: " + (this.keySize() * 8) + " bits");
|
||||
throw Clipperz.Crypto.AES.exception.UnsupportedKeySize;
|
||||
}
|
||||
|
||||
this._stretchedKey = null;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
Clipperz.Crypto.AES.Key.prototype = MochiKit.Base.update(null, {
|
||||
|
||||
'asString': function() {
|
||||
return "Clipperz.Crypto.AES.Key (" + this.key().toHexString() + ")";
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'key': function() {
|
||||
return this._key;
|
||||
},
|
||||
|
||||
'keySize': function() {
|
||||
return this._keySize;
|
||||
},
|
||||
|
||||
'b': function() {
|
||||
return this._b;
|
||||
},
|
||||
|
||||
'numberOfRounds': function() {
|
||||
return this._numberOfRounds;
|
||||
},
|
||||
//=========================================================================
|
||||
|
||||
'keyScheduleCore': function(aWord, aRoundConstantsIndex) {
|
||||
var result;
|
||||
var sbox;
|
||||
|
||||
sbox = Clipperz.Crypto.AES.sbox();
|
||||
|
||||
result = [ sbox[aWord[1]] ^ Clipperz.Crypto.AES.roundConstants()[aRoundConstantsIndex],
|
||||
sbox[aWord[2]],
|
||||
sbox[aWord[3]],
|
||||
sbox[aWord[0]] ];
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'xorWithPreviousStretchValues': function(aKey, aWord, aPreviousWordIndex) {
|
||||
var result;
|
||||
var i,c;
|
||||
|
||||
result = [];
|
||||
c = 4;
|
||||
for (i=0; i<c; i++) {
|
||||
result[i] = aWord[i] ^ aKey.byteAtIndex(aPreviousWordIndex + i);
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'sboxShakeup': function(aWord) {
|
||||
var result;
|
||||
var sbox;
|
||||
var i,c;
|
||||
|
||||
result = [];
|
||||
sbox = Clipperz.Crypto.AES.sbox();
|
||||
c =4;
|
||||
for (i=0; i<c; i++) {
|
||||
result[i] = sbox[aWord[i]];
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'stretchKey': function(aKey) {
|
||||
var currentWord;
|
||||
var keyLength;
|
||||
var previousStretchIndex;
|
||||
var i,c;
|
||||
|
||||
keyLength = aKey.length();
|
||||
previousStretchIndex = keyLength - this.keySize();
|
||||
|
||||
currentWord = [ aKey.byteAtIndex(keyLength - 4),
|
||||
aKey.byteAtIndex(keyLength - 3),
|
||||
aKey.byteAtIndex(keyLength - 2),
|
||||
aKey.byteAtIndex(keyLength - 1) ];
|
||||
currentWord = this.keyScheduleCore(currentWord, keyLength / this.keySize());
|
||||
|
||||
if (this.keySize() == 256/8) {
|
||||
c = 8;
|
||||
} else if (this.keySize() == 128/8){
|
||||
c = 4;
|
||||
}
|
||||
|
||||
for (i=0; i<c; i++) {
|
||||
if (i == 4) {
|
||||
// fifth streatch word
|
||||
currentWord = this.sboxShakeup(currentWord);
|
||||
}
|
||||
|
||||
currentWord = this.xorWithPreviousStretchValues(aKey, currentWord, previousStretchIndex + (i*4));
|
||||
aKey.appendBytes(currentWord);
|
||||
}
|
||||
|
||||
return aKey;
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'stretchedKey': function() {
|
||||
if (this._stretchedKey == null) {
|
||||
var stretchedKey;
|
||||
|
||||
stretchedKey = this.key().clone();
|
||||
|
||||
while (stretchedKey.length() < this.keySize()) {
|
||||
stretchedKey.appendByte(0);
|
||||
}
|
||||
|
||||
while (stretchedKey.length() < this.b()) {
|
||||
stretchedKey = this.stretchKey(stretchedKey);
|
||||
}
|
||||
|
||||
this._stretchedKey = stretchedKey.split(0, this.b());
|
||||
}
|
||||
|
||||
return this._stretchedKey;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
__syntaxFix__: "syntax fix"
|
||||
});
|
||||
|
||||
//#############################################################################
|
||||
|
||||
Clipperz.Crypto.AES.State = function(args) {
|
||||
args = args || {};
|
||||
|
||||
this._data = args.block;
|
||||
this._key = args.key;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
Clipperz.Crypto.AES.State.prototype = MochiKit.Base.update(null, {
|
||||
|
||||
'key': function() {
|
||||
return this._key;
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'data': function() {
|
||||
return this._data;
|
||||
},
|
||||
|
||||
'setData': function(aValue) {
|
||||
this._data = aValue;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'addRoundKey': function(aRoundNumber) {
|
||||
// each byte of the state is combined with the round key; each round key is derived from the cipher key using a key schedule.
|
||||
var data;
|
||||
var stretchedKey;
|
||||
var firstStretchedKeyIndex;
|
||||
var i,c;
|
||||
|
||||
data = this.data();
|
||||
stretchedKey = this.key().stretchedKey();
|
||||
firstStretchedKeyIndex = aRoundNumber * (128/8);
|
||||
c = 128/8;
|
||||
for (i=0; i<c; i++) {
|
||||
data[i] = data[i] ^ stretchedKey.byteAtIndex(firstStretchedKeyIndex + i);
|
||||
}
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'subBytes': function() {
|
||||
// a non-linear substitution step where each byte is replaced with another according to a lookup table.
|
||||
var i,c;
|
||||
var data;
|
||||
var sbox;
|
||||
|
||||
data = this.data();
|
||||
sbox = Clipperz.Crypto.AES.sbox();
|
||||
|
||||
c = 16;
|
||||
for (i=0; i<c; i++) {
|
||||
data[i] = sbox[data[i]];
|
||||
}
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'shiftRows': function() {
|
||||
// a transposition step where each row of the state is shifted cyclically a certain number of steps.
|
||||
var newValue;
|
||||
var data;
|
||||
var shiftMapping;
|
||||
var i,c;
|
||||
|
||||
newValue = new Array(16);
|
||||
data = this.data();
|
||||
shiftMapping = Clipperz.Crypto.AES.shiftRowMapping();
|
||||
// [0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, 1, 6, 11];
|
||||
c = 16;
|
||||
for (i=0; i<c; i++) {
|
||||
newValue[i] = data[shiftMapping[i]];
|
||||
}
|
||||
for (i=0; i<c; i++) {
|
||||
data[i] = newValue[i];
|
||||
}
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/*
|
||||
'mixColumnsWithValues': function(someValues) {
|
||||
var result;
|
||||
var a;
|
||||
var i,c;
|
||||
|
||||
c = 4;
|
||||
result = [];
|
||||
a = [];
|
||||
for (i=0; i<c; i++) {
|
||||
a[i] = [];
|
||||
a[i][1] = someValues[i]
|
||||
if ((a[i][1] & 0x80) == 0x80) {
|
||||
a[i][2] = (a[i][1] << 1) ^ 0x11b;
|
||||
} else {
|
||||
a[i][2] = a[i][1] << 1;
|
||||
}
|
||||
|
||||
a[i][3] = a[i][2] ^ a[i][1];
|
||||
}
|
||||
|
||||
for (i=0; i<c; i++) {
|
||||
var x;
|
||||
|
||||
x = Clipperz.Crypto.AES.mixColumnsMatrix()[i];
|
||||
result[i] = a[0][x[0]] ^ a[1][x[1]] ^ a[2][x[2]] ^ a[3][x[3]];
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
'mixColumns': function() {
|
||||
// a mixing operation which operates on the columns of the state, combining the four bytes in each column using a linear transformation.
|
||||
var data;
|
||||
var i, c;
|
||||
|
||||
data = this.data();
|
||||
c = 4;
|
||||
for(i=0; i<c; i++) {
|
||||
var blockIndex;
|
||||
var mixedValues;
|
||||
|
||||
blockIndex = i * 4;
|
||||
mixedValues = this.mixColumnsWithValues([ data[blockIndex + 0],
|
||||
data[blockIndex + 1],
|
||||
data[blockIndex + 2],
|
||||
data[blockIndex + 3]]);
|
||||
data[blockIndex + 0] = mixedValues[0];
|
||||
data[blockIndex + 1] = mixedValues[1];
|
||||
data[blockIndex + 2] = mixedValues[2];
|
||||
data[blockIndex + 3] = mixedValues[3];
|
||||
}
|
||||
},
|
||||
*/
|
||||
|
||||
'mixColumns': function() {
|
||||
// a mixing operation which operates on the columns of the state, combining the four bytes in each column using a linear transformation.
|
||||
var data;
|
||||
var i, c;
|
||||
var a_1;
|
||||
var a_2;
|
||||
|
||||
a_1 = new Array(4);
|
||||
a_2 = new Array(4);
|
||||
|
||||
data = this.data();
|
||||
c = 4;
|
||||
for(i=0; i<c; i++) {
|
||||
var blockIndex;
|
||||
var ii, cc;
|
||||
|
||||
blockIndex = i * 4;
|
||||
|
||||
cc = 4;
|
||||
for (ii=0; ii<cc; ii++) {
|
||||
var value;
|
||||
|
||||
value = data[blockIndex + ii];
|
||||
a_1[ii] = value;
|
||||
a_2[ii] = (value & 0x80) ? ((value << 1) ^ 0x011b) : (value << 1);
|
||||
}
|
||||
|
||||
data[blockIndex + 0] = a_2[0] ^ a_1[1] ^ a_2[1] ^ a_1[2] ^ a_1[3];
|
||||
data[blockIndex + 1] = a_1[0] ^ a_2[1] ^ a_1[2] ^ a_2[2] ^ a_1[3];
|
||||
data[blockIndex + 2] = a_1[0] ^ a_1[1] ^ a_2[2] ^ a_1[3] ^ a_2[3];
|
||||
data[blockIndex + 3] = a_1[0] ^ a_2[0] ^ a_1[1] ^ a_1[2] ^ a_2[3];
|
||||
}
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'spinRound': function(aRoundNumber) {
|
||||
this.addRoundKey(aRoundNumber);
|
||||
this.subBytes();
|
||||
this.shiftRows();
|
||||
this.mixColumns();
|
||||
},
|
||||
|
||||
'spinLastRound': function() {
|
||||
this.addRoundKey(this.key().numberOfRounds() - 1);
|
||||
this.subBytes();
|
||||
this.shiftRows();
|
||||
this.addRoundKey(this.key().numberOfRounds());
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'encrypt': function() {
|
||||
var i,c;
|
||||
|
||||
c = this.key().numberOfRounds() - 1;
|
||||
for (i=0; i<c; i++) {
|
||||
this.spinRound(i);
|
||||
}
|
||||
|
||||
this.spinLastRound();
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
__syntaxFix__: "syntax fix"
|
||||
});
|
||||
|
||||
//#############################################################################
|
||||
|
||||
Clipperz.Crypto.AES.VERSION = "0.1";
|
||||
Clipperz.Crypto.AES.NAME = "Clipperz.Crypto.AES";
|
||||
|
||||
MochiKit.Base.update(Clipperz.Crypto.AES, {
|
||||
|
||||
// http://www.cs.eku.edu/faculty/styer/460/Encrypt/JS-AES.html
|
||||
// http://en.wikipedia.org/wiki/Advanced_Encryption_Standard
|
||||
// http://en.wikipedia.org/wiki/Rijndael_key_schedule
|
||||
// http://en.wikipedia.org/wiki/Rijndael_S-box
|
||||
|
||||
'__repr__': function () {
|
||||
return "[" + this.NAME + " " + this.VERSION + "]";
|
||||
},
|
||||
|
||||
'toString': function () {
|
||||
return this.__repr__();
|
||||
},
|
||||
|
||||
//=============================================================================
|
||||
|
||||
'_sbox': null,
|
||||
'sbox': function() {
|
||||
if (Clipperz.Crypto.AES._sbox == null) {
|
||||
Clipperz.Crypto.AES._sbox = [
|
||||
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
|
||||
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
|
||||
0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
|
||||
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
|
||||
0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
|
||||
0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
|
||||
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
|
||||
0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
|
||||
0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
|
||||
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
|
||||
0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
|
||||
0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
|
||||
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
|
||||
0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
|
||||
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
|
||||
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
|
||||
];
|
||||
}
|
||||
|
||||
return Clipperz.Crypto.AES._sbox;
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// 0 4 8 12 0 4 8 12
|
||||
// 1 5 9 13 => 5 9 13 1
|
||||
// 2 6 10 14 10 14 2 6
|
||||
// 3 7 11 15 15 3 7 11
|
||||
//
|
||||
'_shiftRowMapping': null,
|
||||
'shiftRowMapping': function() {
|
||||
if (Clipperz.Crypto.AES._shiftRowMapping == null) {
|
||||
Clipperz.Crypto.AES._shiftRowMapping = [0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, 1, 6, 11];
|
||||
}
|
||||
|
||||
return Clipperz.Crypto.AES._shiftRowMapping;
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'_mixColumnsMatrix': null,
|
||||
'mixColumnsMatrix': function() {
|
||||
if (Clipperz.Crypto.AES._mixColumnsMatrix == null) {
|
||||
Clipperz.Crypto.AES._mixColumnsMatrix = [ [2, 3, 1 ,1],
|
||||
[1, 2, 3, 1],
|
||||
[1, 1, 2, 3],
|
||||
[3, 1, 1, 2] ];
|
||||
}
|
||||
|
||||
return Clipperz.Crypto.AES._mixColumnsMatrix;
|
||||
},
|
||||
|
||||
'_roundConstants': null,
|
||||
'roundConstants': function() {
|
||||
if (Clipperz.Crypto.AES._roundConstants == null) {
|
||||
Clipperz.Crypto.AES._roundConstants = [ , 1, 2, 4, 8, 16, 32, 64, 128, 27, 54, 108, 216, 171, 77, 154];
|
||||
// Clipperz.Crypto.AES._roundConstants = [ , 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a];
|
||||
}
|
||||
|
||||
return Clipperz.Crypto.AES._roundConstants;
|
||||
},
|
||||
|
||||
//=============================================================================
|
||||
|
||||
'incrementNonce': function(aNonce) {
|
||||
//Clipperz.Profile.start("Clipperz.Crypto.AES.incrementNonce");
|
||||
var i;
|
||||
var done;
|
||||
|
||||
done = false;
|
||||
i = aNonce.length - 1;
|
||||
|
||||
while ((i>=0) && (done == false)) {
|
||||
var currentByteValue;
|
||||
|
||||
currentByteValue = aNonce[i];
|
||||
|
||||
if (currentByteValue == 0xff) {
|
||||
aNonce[i] = 0;
|
||||
if (i>= 0) {
|
||||
i --;
|
||||
} else {
|
||||
done = true;
|
||||
}
|
||||
} else {
|
||||
aNonce[i] = currentByteValue + 1;
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
//Clipperz.Profile.stop("Clipperz.Crypto.AES.incrementNonce");
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'encryptBlock': function(aKey, aBlock) {
|
||||
var result;
|
||||
var state;
|
||||
|
||||
state = new Clipperz.Crypto.AES.State({block:aBlock, key:aKey});
|
||||
//is(state.data(), 'before');
|
||||
state.encrypt();
|
||||
result = state.data();
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'encryptBlocks': function(aKey, aMessage, aNonce) {
|
||||
var result;
|
||||
var nonce;
|
||||
var self;
|
||||
var messageIndex;
|
||||
var messageLength;
|
||||
var blockSize;
|
||||
|
||||
self = Clipperz.Crypto.AES;
|
||||
blockSize = 128/8;
|
||||
messageLength = aMessage.length;
|
||||
nonce = aNonce;
|
||||
|
||||
result = aMessage;
|
||||
messageIndex = 0;
|
||||
while (messageIndex < messageLength) {
|
||||
var encryptedBlock;
|
||||
var i,c;
|
||||
|
||||
self.incrementNonce(nonce);
|
||||
encryptedBlock = self.encryptBlock(aKey, nonce);
|
||||
|
||||
if ((messageLength - messageIndex) > blockSize) {
|
||||
c = blockSize;
|
||||
} else {
|
||||
c = messageLength - messageIndex;
|
||||
}
|
||||
|
||||
for (i=0; i<c; i++) {
|
||||
result[messageIndex + i] = result[messageIndex + i] ^ encryptedBlock[i];
|
||||
}
|
||||
|
||||
messageIndex += blockSize;
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'encrypt': function(aKey, someData, aNonce) {
|
||||
var result;
|
||||
var nonce;
|
||||
var encryptedData;
|
||||
var key;
|
||||
|
||||
key = new Clipperz.Crypto.AES.Key({key:aKey});
|
||||
nonce = aNonce ? aNonce.clone() : Clipperz.Crypto.PRNG.defaultRandomGenerator().getRandomBytes(128/8);
|
||||
|
||||
encryptedData = Clipperz.Crypto.AES.encryptBlocks(key, someData.arrayValues(), nonce.arrayValues());
|
||||
|
||||
result = nonce.appendBytes(encryptedData);
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'decrypt': function(aKey, someData) {
|
||||
var result;
|
||||
var nonce;
|
||||
var encryptedData;
|
||||
var decryptedData;
|
||||
var dataIterator;
|
||||
var key;
|
||||
|
||||
key = new Clipperz.Crypto.AES.Key({key:aKey});
|
||||
|
||||
encryptedData = someData.arrayValues();
|
||||
nonce = encryptedData.slice(0, (128/8));
|
||||
encryptedData = encryptedData.slice(128/8);
|
||||
decryptedData = Clipperz.Crypto.AES.encryptBlocks(key, encryptedData, nonce);
|
||||
|
||||
result = new Clipperz.ByteArray(decryptedData);
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//=============================================================================
|
||||
|
||||
'deferredEncryptExecutionChunk': function(anExecutionContext) {
|
||||
var result;
|
||||
var nonce;
|
||||
var self;
|
||||
var messageIndex;
|
||||
var messageLength;
|
||||
var blockSize;
|
||||
var executionLimit;
|
||||
var startTime, endTime;
|
||||
|
||||
self = Clipperz.Crypto.AES;
|
||||
startTime = new Date();
|
||||
blockSize = 128/8;
|
||||
messageLength = anExecutionContext.messageArray().length;
|
||||
nonce = anExecutionContext.nonceArray();
|
||||
result = anExecutionContext.resultArray();
|
||||
|
||||
messageIndex = anExecutionContext.executionStep();
|
||||
executionLimit = messageIndex + anExecutionContext.elaborationChunkSize();
|
||||
executionLimit = Math.min(executionLimit, messageLength);
|
||||
|
||||
while (messageIndex < executionLimit) {
|
||||
var encryptedBlock;
|
||||
var i,c;
|
||||
|
||||
self.incrementNonce(nonce);
|
||||
encryptedBlock = self.encryptBlock(anExecutionContext.key(), nonce);
|
||||
|
||||
if ((executionLimit - messageIndex) > blockSize) {
|
||||
c = blockSize;
|
||||
} else {
|
||||
c = executionLimit - messageIndex;
|
||||
}
|
||||
|
||||
for (i=0; i<c; i++) {
|
||||
result[messageIndex + i] = result[messageIndex + i] ^ encryptedBlock[i];
|
||||
}
|
||||
|
||||
messageIndex += blockSize;
|
||||
}
|
||||
anExecutionContext.setExecutionStep(messageIndex);
|
||||
endTime = new Date();
|
||||
anExecutionContext.tuneExecutionParameters(endTime - startTime);
|
||||
|
||||
return anExecutionContext;
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/*
|
||||
'deferredEncryptBlocks': function(anExecutionContext) {
|
||||
var deferredResult;
|
||||
var messageSize;
|
||||
var i,c;
|
||||
|
||||
messageSize = anExecutionContext.messageLength();
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("AES.deferredEncryptBloks");
|
||||
|
||||
c = Math.ceil(messageSize / anExecutionContext.elaborationChunkSize());
|
||||
for (i=0; i<c; i++) {
|
||||
deferredResult.addCallback(Clipperz.Crypto.AES.deferredEncryptExecutionChunk);
|
||||
deferredResult.addMethod(anExecutionContext, 'pause');
|
||||
}
|
||||
|
||||
deferredResult.callback(anExecutionContext);
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
*/
|
||||
|
||||
'deferredEncryptBlocks': function(anExecutionContext) {
|
||||
var deferredResult;
|
||||
|
||||
if (! anExecutionContext.isDone()) {
|
||||
deferredResult = Clipperz.Async.callbacks("Clipperz.Crypto.AES.deferredEncryptBloks", [
|
||||
Clipperz.Crypto.AES.deferredEncryptExecutionChunk,
|
||||
MochiKit.Base.method(anExecutionContext, 'pause'),
|
||||
Clipperz.Crypto.AES.deferredEncryptBlocks
|
||||
], {trace:false}, anExecutionContext);
|
||||
} else {
|
||||
deferredResult = MochiKit.Async.succeed(anExecutionContext);
|
||||
}
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'deferredEncrypt': function(aKey, someData, aNonce) {
|
||||
var deferredResult;
|
||||
var executionContext;
|
||||
var result;
|
||||
var nonce;
|
||||
var key;
|
||||
|
||||
key = new Clipperz.Crypto.AES.Key({key:aKey});
|
||||
nonce = aNonce ? aNonce.clone() : Clipperz.Crypto.PRNG.defaultRandomGenerator().getRandomBytes(128/8);
|
||||
|
||||
executionContext = new Clipperz.Crypto.AES.DeferredExecutionContext({key:key, message:someData, nonce:nonce});
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("AES.deferredEncrypt");
|
||||
deferredResult.addCallback(Clipperz.Crypto.AES.deferredEncryptBlocks);
|
||||
deferredResult.addCallback(function(anExecutionContext) {
|
||||
var result;
|
||||
|
||||
result = anExecutionContext.nonce().clone();
|
||||
result.appendBytes(anExecutionContext.resultArray());
|
||||
|
||||
return result;
|
||||
});
|
||||
deferredResult.callback(executionContext)
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'deferredDecrypt': function(aKey, someData) {
|
||||
var deferredResult
|
||||
var nonce;
|
||||
var message;
|
||||
var key;
|
||||
|
||||
key = new Clipperz.Crypto.AES.Key({key:aKey});
|
||||
nonce = someData.split(0, (128/8));
|
||||
message = someData.split(128/8);
|
||||
executionContext = new Clipperz.Crypto.AES.DeferredExecutionContext({key:key, message:message, nonce:nonce});
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("AES.deferredDecrypt");
|
||||
deferredResult.addCallback(Clipperz.Crypto.AES.deferredEncryptBlocks);
|
||||
deferredResult.addCallback(function(anExecutionContext) {
|
||||
return anExecutionContext.result();
|
||||
});
|
||||
deferredResult.callback(executionContext);
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
__syntaxFix__: "syntax fix"
|
||||
|
||||
});
|
||||
|
||||
//#############################################################################
|
||||
|
||||
//Clipperz.Crypto.AES.DeferredExecution = {
|
||||
// 'chunkSize': 16384, // 4096, // 1024 4096 8192 16384 32768;
|
||||
// 'pauseTime': 0.02 // 0.2
|
||||
//}
|
||||
|
||||
Clipperz.Crypto.AES.exception = {
|
||||
'UnsupportedKeySize': new MochiKit.Base.NamedError("Clipperz.Crypto.AES.exception.UnsupportedKeySize")
|
||||
};
|
||||
843
frontend/delta/js/Clipperz/Crypto/AES_2.js
Normal file
843
frontend/delta/js/Clipperz/Crypto/AES_2.js
Normal file
@@ -0,0 +1,843 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
try { if (typeof(Clipperz.ByteArray) == 'undefined') { throw ""; }} catch (e) {
|
||||
throw "Clipperz.Crypto.AES_2 depends on Clipperz.ByteArray!";
|
||||
}
|
||||
|
||||
// Dependency commented to avoid a circular reference
|
||||
//try { if (typeof(Clipperz.Crypto.PRNG) == 'undefined') { throw ""; }} catch (e) {
|
||||
// throw "Clipperz.Crypto.AES_2 depends on Clipperz.Crypto.PRNG!";
|
||||
//}
|
||||
|
||||
if (typeof(Clipperz.Crypto.AES_2) == 'undefined') { Clipperz.Crypto.AES_2 = {}; }
|
||||
|
||||
//#############################################################################
|
||||
|
||||
Clipperz.Crypto.AES_2.DeferredExecutionContext = function(args) {
|
||||
args = args || {};
|
||||
|
||||
this._key = args.key;
|
||||
this._message = args.message;
|
||||
this._result = args.message.clone();
|
||||
this._nonce = args.nonce;
|
||||
this._messageLength = this._message.length();
|
||||
|
||||
this._messageArray = this._message.arrayValues();
|
||||
this._resultArray = this._result.arrayValues();
|
||||
this._nonceArray = this._nonce.arrayValues();
|
||||
|
||||
this._executionStep = 0;
|
||||
|
||||
// this._elaborationChunkSize = 1024; // 4096; // 16384; // 4096;
|
||||
this._elaborationChunks = 10;
|
||||
this._pauseTime = 0.02; // 0.02 // 0.2;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
Clipperz.Crypto.AES_2.DeferredExecutionContext.prototype = MochiKit.Base.update(null, {
|
||||
|
||||
'key': function() {
|
||||
return this._key;
|
||||
},
|
||||
|
||||
'message': function() {
|
||||
return this._message;
|
||||
},
|
||||
|
||||
'messageLength': function() {
|
||||
return this._messageLength;
|
||||
},
|
||||
|
||||
'result': function() {
|
||||
return new Clipperz.ByteArray(this.resultArray());
|
||||
},
|
||||
|
||||
'nonce': function() {
|
||||
return this._nonce;
|
||||
},
|
||||
|
||||
'messageArray': function() {
|
||||
return this._messageArray;
|
||||
},
|
||||
|
||||
'resultArray': function() {
|
||||
return this._resultArray;
|
||||
},
|
||||
|
||||
'nonceArray': function() {
|
||||
return this._nonceArray;
|
||||
},
|
||||
|
||||
'elaborationChunkSize': function() {
|
||||
// return Clipperz.Crypto.AES_2.DeferredExecution.chunkSize;
|
||||
// return this._elaborationChunkSize;
|
||||
return (this._elaborationChunks * 1024);
|
||||
},
|
||||
|
||||
'executionStep': function() {
|
||||
return this._executionStep;
|
||||
},
|
||||
|
||||
'setExecutionStep': function(aValue) {
|
||||
this._executionStep = aValue;
|
||||
},
|
||||
|
||||
'tuneExecutionParameters': function (anElapsedTime) {
|
||||
//var originalChunks = this._elaborationChunks;
|
||||
if (anElapsedTime > 0) {
|
||||
this._elaborationChunks = Math.round(this._elaborationChunks * ((anElapsedTime + 1000)/(anElapsedTime * 2)));
|
||||
}
|
||||
//Clipperz.log("tuneExecutionParameters - elapsedTime: " + anElapsedTime + /*originalChunks,*/ " chunks # " + this._elaborationChunks + " [" + this._executionStep + " / " + this._messageLength + "]");
|
||||
},
|
||||
|
||||
'pause': function(aValue) {
|
||||
// return MochiKit.Async.wait(Clipperz.Crypto.AES_2.DeferredExecution.pauseTime, aValue);
|
||||
return MochiKit.Async.wait(this._pauseTime, aValue);
|
||||
},
|
||||
|
||||
'isDone': function () {
|
||||
return (this._executionStep >= this._messageLength);
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
__syntaxFix__: "syntax fix"
|
||||
|
||||
});
|
||||
|
||||
//#############################################################################
|
||||
|
||||
Clipperz.Crypto.AES_2.Key = function(args) {
|
||||
args = args || {};
|
||||
|
||||
this._key = args.key;
|
||||
this._keySize = args.keySize || this.key().length();
|
||||
|
||||
if (this.keySize() == 128/8) {
|
||||
this._b = 176;
|
||||
this._numberOfRounds = 10;
|
||||
} else if (this.keySize() == 256/8) {
|
||||
this._b = 240;
|
||||
this._numberOfRounds = 14;
|
||||
} else {
|
||||
Clipperz.logError("AES unsupported key size: " + (this.keySize() * 8) + " bits");
|
||||
throw Clipperz.Crypto.AES_2.exception.UnsupportedKeySize;
|
||||
}
|
||||
|
||||
this._stretchedKey = null;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
Clipperz.Crypto.AES_2.Key.prototype = MochiKit.Base.update(null, {
|
||||
|
||||
'asString': function() {
|
||||
return "Clipperz.Crypto.AES_2.Key (" + this.key().toHexString() + ")";
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'key': function() {
|
||||
return this._key;
|
||||
},
|
||||
|
||||
'keySize': function() {
|
||||
return this._keySize;
|
||||
},
|
||||
|
||||
'b': function() {
|
||||
return this._b;
|
||||
},
|
||||
|
||||
'numberOfRounds': function() {
|
||||
return this._numberOfRounds;
|
||||
},
|
||||
//=========================================================================
|
||||
|
||||
'keyScheduleCore': function(aWord, aRoundConstantsIndex) {
|
||||
var result;
|
||||
var sbox;
|
||||
|
||||
sbox = Clipperz.Crypto.AES_2.sbox();
|
||||
|
||||
result = [ sbox[aWord[1]] ^ Clipperz.Crypto.AES_2.roundConstants()[aRoundConstantsIndex],
|
||||
sbox[aWord[2]],
|
||||
sbox[aWord[3]],
|
||||
sbox[aWord[0]] ];
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'xorWithPreviousStretchValues': function(aKey, aWord, aPreviousWordIndex) {
|
||||
var result;
|
||||
var i,c;
|
||||
|
||||
result = [];
|
||||
c = 4;
|
||||
for (i=0; i<c; i++) {
|
||||
result[i] = aWord[i] ^ aKey.byteAtIndex(aPreviousWordIndex + i);
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'sboxShakeup': function(aWord) {
|
||||
var result;
|
||||
var sbox;
|
||||
var i,c;
|
||||
|
||||
result = [];
|
||||
sbox = Clipperz.Crypto.AES_2.sbox();
|
||||
c =4;
|
||||
for (i=0; i<c; i++) {
|
||||
result[i] = sbox[aWord[i]];
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'stretchKey': function(aKey) {
|
||||
var currentWord;
|
||||
var keyLength;
|
||||
var previousStretchIndex;
|
||||
var i,c;
|
||||
|
||||
keyLength = aKey.length();
|
||||
previousStretchIndex = keyLength - this.keySize();
|
||||
|
||||
currentWord = [ aKey.byteAtIndex(keyLength - 4),
|
||||
aKey.byteAtIndex(keyLength - 3),
|
||||
aKey.byteAtIndex(keyLength - 2),
|
||||
aKey.byteAtIndex(keyLength - 1) ];
|
||||
currentWord = this.keyScheduleCore(currentWord, keyLength / this.keySize());
|
||||
|
||||
if (this.keySize() == 256/8) {
|
||||
c = 8;
|
||||
} else if (this.keySize() == 128/8){
|
||||
c = 4;
|
||||
}
|
||||
|
||||
for (i=0; i<c; i++) {
|
||||
if (i == 4) {
|
||||
// fifth streatch word
|
||||
currentWord = this.sboxShakeup(currentWord);
|
||||
}
|
||||
|
||||
currentWord = this.xorWithPreviousStretchValues(aKey, currentWord, previousStretchIndex + (i*4));
|
||||
aKey.appendBytes(currentWord);
|
||||
}
|
||||
|
||||
return aKey;
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'stretchedKey': function() {
|
||||
if (this._stretchedKey == null) {
|
||||
var stretchedKey;
|
||||
|
||||
stretchedKey = this.key().clone();
|
||||
|
||||
while (stretchedKey.length() < this.keySize()) {
|
||||
stretchedKey.appendByte(0);
|
||||
}
|
||||
|
||||
while (stretchedKey.length() < this.b()) {
|
||||
stretchedKey = this.stretchKey(stretchedKey);
|
||||
}
|
||||
|
||||
this._stretchedKey = stretchedKey.split(0, this.b());
|
||||
}
|
||||
|
||||
return this._stretchedKey;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
__syntaxFix__: "syntax fix"
|
||||
});
|
||||
|
||||
//#############################################################################
|
||||
|
||||
Clipperz.Crypto.AES_2.State = function(args) {
|
||||
args = args || {};
|
||||
|
||||
this._data = args.block.slice(0);
|
||||
this._key = args.key;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
Clipperz.Crypto.AES_2.State.prototype = MochiKit.Base.update(null, {
|
||||
|
||||
'key': function() {
|
||||
return this._key;
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'data': function() {
|
||||
return this._data;
|
||||
},
|
||||
|
||||
'setData': function(aValue) {
|
||||
this._data = aValue;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'addRoundKey': function(aRoundNumber) {
|
||||
// each byte of the state is combined with the round key; each round key is derived from the cipher key using a key schedule.
|
||||
var data;
|
||||
var stretchedKey;
|
||||
var firstStretchedKeyIndex;
|
||||
var i,c;
|
||||
|
||||
data = this.data();
|
||||
stretchedKey = this.key().stretchedKey();
|
||||
firstStretchedKeyIndex = aRoundNumber * (128/8);
|
||||
c = 128/8;
|
||||
for (i=0; i<c; i++) {
|
||||
data[i] = data[i] ^ stretchedKey.byteAtIndex(firstStretchedKeyIndex + i);
|
||||
}
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'subBytes': function() {
|
||||
// a non-linear substitution step where each byte is replaced with another according to a lookup table.
|
||||
var i,c;
|
||||
var data;
|
||||
var sbox;
|
||||
|
||||
data = this.data();
|
||||
sbox = Clipperz.Crypto.AES_2.sbox();
|
||||
|
||||
c = 16;
|
||||
for (i=0; i<c; i++) {
|
||||
data[i] = sbox[data[i]];
|
||||
}
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'shiftRows': function() {
|
||||
// a transposition step where each row of the state is shifted cyclically a certain number of steps.
|
||||
var newValue;
|
||||
var data;
|
||||
var shiftMapping;
|
||||
var i,c;
|
||||
|
||||
newValue = new Array(16);
|
||||
data = this.data();
|
||||
shiftMapping = Clipperz.Crypto.AES_2.shiftRowMapping();
|
||||
// [0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, 1, 6, 11];
|
||||
c = 16;
|
||||
for (i=0; i<c; i++) {
|
||||
newValue[i] = data[shiftMapping[i]];
|
||||
}
|
||||
for (i=0; i<c; i++) {
|
||||
data[i] = newValue[i];
|
||||
}
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/*
|
||||
'mixColumnsWithValues': function(someValues) {
|
||||
var result;
|
||||
var a;
|
||||
var i,c;
|
||||
|
||||
c = 4;
|
||||
result = [];
|
||||
a = [];
|
||||
for (i=0; i<c; i++) {
|
||||
a[i] = [];
|
||||
a[i][1] = someValues[i]
|
||||
if ((a[i][1] & 0x80) == 0x80) {
|
||||
a[i][2] = (a[i][1] << 1) ^ 0x11b;
|
||||
} else {
|
||||
a[i][2] = a[i][1] << 1;
|
||||
}
|
||||
|
||||
a[i][3] = a[i][2] ^ a[i][1];
|
||||
}
|
||||
|
||||
for (i=0; i<c; i++) {
|
||||
var x;
|
||||
|
||||
x = Clipperz.Crypto.AES_2.mixColumnsMatrix()[i];
|
||||
result[i] = a[0][x[0]] ^ a[1][x[1]] ^ a[2][x[2]] ^ a[3][x[3]];
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
'mixColumns': function() {
|
||||
// a mixing operation which operates on the columns of the state, combining the four bytes in each column using a linear transformation.
|
||||
var data;
|
||||
var i, c;
|
||||
|
||||
data = this.data();
|
||||
c = 4;
|
||||
for(i=0; i<c; i++) {
|
||||
var blockIndex;
|
||||
var mixedValues;
|
||||
|
||||
blockIndex = i * 4;
|
||||
mixedValues = this.mixColumnsWithValues([ data[blockIndex + 0],
|
||||
data[blockIndex + 1],
|
||||
data[blockIndex + 2],
|
||||
data[blockIndex + 3]]);
|
||||
data[blockIndex + 0] = mixedValues[0];
|
||||
data[blockIndex + 1] = mixedValues[1];
|
||||
data[blockIndex + 2] = mixedValues[2];
|
||||
data[blockIndex + 3] = mixedValues[3];
|
||||
}
|
||||
},
|
||||
*/
|
||||
|
||||
'mixColumns': function() {
|
||||
// a mixing operation which operates on the columns of the state, combining the four bytes in each column using a linear transformation.
|
||||
var data;
|
||||
var i, c;
|
||||
var a_1;
|
||||
var a_2;
|
||||
|
||||
a_1 = new Array(4);
|
||||
a_2 = new Array(4);
|
||||
|
||||
data = this.data();
|
||||
c = 4;
|
||||
for(i=0; i<c; i++) {
|
||||
var blockIndex;
|
||||
var ii, cc;
|
||||
|
||||
blockIndex = i * 4;
|
||||
|
||||
cc = 4;
|
||||
for (ii=0; ii<cc; ii++) {
|
||||
var value;
|
||||
|
||||
value = data[blockIndex + ii];
|
||||
a_1[ii] = value;
|
||||
a_2[ii] = (value & 0x80) ? ((value << 1) ^ 0x011b) : (value << 1);
|
||||
}
|
||||
|
||||
data[blockIndex + 0] = a_2[0] ^ a_1[1] ^ a_2[1] ^ a_1[2] ^ a_1[3];
|
||||
data[blockIndex + 1] = a_1[0] ^ a_2[1] ^ a_1[2] ^ a_2[2] ^ a_1[3];
|
||||
data[blockIndex + 2] = a_1[0] ^ a_1[1] ^ a_2[2] ^ a_1[3] ^ a_2[3];
|
||||
data[blockIndex + 3] = a_1[0] ^ a_2[0] ^ a_1[1] ^ a_1[2] ^ a_2[3];
|
||||
}
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'spinRound': function(aRoundNumber) {
|
||||
this.addRoundKey(aRoundNumber);
|
||||
this.subBytes();
|
||||
this.shiftRows();
|
||||
this.mixColumns();
|
||||
},
|
||||
|
||||
'spinLastRound': function() {
|
||||
this.addRoundKey(this.key().numberOfRounds() - 1);
|
||||
this.subBytes();
|
||||
this.shiftRows();
|
||||
this.addRoundKey(this.key().numberOfRounds());
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'encrypt': function() {
|
||||
var i,c;
|
||||
|
||||
c = this.key().numberOfRounds() - 1;
|
||||
for (i=0; i<c; i++) {
|
||||
this.spinRound(i);
|
||||
}
|
||||
|
||||
this.spinLastRound();
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
__syntaxFix__: "syntax fix"
|
||||
});
|
||||
|
||||
//#############################################################################
|
||||
|
||||
Clipperz.Crypto.AES_2.VERSION = "0.1";
|
||||
Clipperz.Crypto.AES_2.NAME = "Clipperz.Crypto.AES_2";
|
||||
|
||||
MochiKit.Base.update(Clipperz.Crypto.AES_2, {
|
||||
|
||||
// http://www.cs.eku.edu/faculty/styer/460/Encrypt/JS-AES.html
|
||||
// http://en.wikipedia.org/wiki/Advanced_Encryption_Standard
|
||||
// http://en.wikipedia.org/wiki/Rijndael_key_schedule
|
||||
// http://en.wikipedia.org/wiki/Rijndael_S-box
|
||||
|
||||
'__repr__': function () {
|
||||
return "[" + this.NAME + " " + this.VERSION + "]";
|
||||
},
|
||||
|
||||
'toString': function () {
|
||||
return this.__repr__();
|
||||
},
|
||||
|
||||
//=============================================================================
|
||||
|
||||
'_sbox': null,
|
||||
'sbox': function() {
|
||||
if (Clipperz.Crypto.AES_2._sbox == null) {
|
||||
Clipperz.Crypto.AES_2._sbox = [
|
||||
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
|
||||
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
|
||||
0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
|
||||
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
|
||||
0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
|
||||
0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
|
||||
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
|
||||
0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
|
||||
0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
|
||||
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
|
||||
0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
|
||||
0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
|
||||
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
|
||||
0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
|
||||
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
|
||||
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
|
||||
];
|
||||
}
|
||||
|
||||
return Clipperz.Crypto.AES_2._sbox;
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// 0 4 8 12 0 4 8 12
|
||||
// 1 5 9 13 => 5 9 13 1
|
||||
// 2 6 10 14 10 14 2 6
|
||||
// 3 7 11 15 15 3 7 11
|
||||
//
|
||||
'_shiftRowMapping': null,
|
||||
'shiftRowMapping': function() {
|
||||
if (Clipperz.Crypto.AES_2._shiftRowMapping == null) {
|
||||
Clipperz.Crypto.AES_2._shiftRowMapping = [0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, 1, 6, 11];
|
||||
}
|
||||
|
||||
return Clipperz.Crypto.AES_2._shiftRowMapping;
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'_mixColumnsMatrix': null,
|
||||
'mixColumnsMatrix': function() {
|
||||
if (Clipperz.Crypto.AES_2._mixColumnsMatrix == null) {
|
||||
Clipperz.Crypto.AES_2._mixColumnsMatrix = [ [2, 3, 1 ,1],
|
||||
[1, 2, 3, 1],
|
||||
[1, 1, 2, 3],
|
||||
[3, 1, 1, 2] ];
|
||||
}
|
||||
|
||||
return Clipperz.Crypto.AES_2._mixColumnsMatrix;
|
||||
},
|
||||
|
||||
'_roundConstants': null,
|
||||
'roundConstants': function() {
|
||||
if (Clipperz.Crypto.AES_2._roundConstants == null) {
|
||||
Clipperz.Crypto.AES_2._roundConstants = [ , 1, 2, 4, 8, 16, 32, 64, 128, 27, 54, 108, 216, 171, 77, 154];
|
||||
// Clipperz.Crypto.AES_2._roundConstants = [ , 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a];
|
||||
}
|
||||
|
||||
return Clipperz.Crypto.AES_2._roundConstants;
|
||||
},
|
||||
|
||||
//=============================================================================
|
||||
|
||||
'incrementNonce': function(nonce) {
|
||||
var i;
|
||||
var done;
|
||||
|
||||
done = false;
|
||||
i = nonce.length - 1;
|
||||
|
||||
while ((i>=0) && (done == false)) {
|
||||
var currentByteValue;
|
||||
|
||||
currentByteValue = nonce[i];
|
||||
|
||||
if (currentByteValue == 0xff) {
|
||||
nonce[i] = 0;
|
||||
if (i>= 0) {
|
||||
i --;
|
||||
} else {
|
||||
done = true;
|
||||
}
|
||||
} else {
|
||||
nonce[i] = currentByteValue + 1;
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'encryptBlock': function(aKey, aBlock) {
|
||||
var result;
|
||||
var state;
|
||||
|
||||
state = new Clipperz.Crypto.AES_2.State({block:aBlock, key:aKey});
|
||||
//is(state.data(), 'before');
|
||||
state.encrypt();
|
||||
result = state.data();
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'encryptBlocks': function(aKey, aMessage, aNonce) {
|
||||
var result;
|
||||
var nonce;
|
||||
var self;
|
||||
var messageIndex;
|
||||
var messageLength;
|
||||
var blockSize;
|
||||
|
||||
self = Clipperz.Crypto.AES_2;
|
||||
blockSize = 128/8;
|
||||
messageLength = aMessage.length;
|
||||
nonce = aNonce;
|
||||
|
||||
result = aMessage;
|
||||
messageIndex = 0;
|
||||
while (messageIndex < messageLength) {
|
||||
var encryptedBlock;
|
||||
var i,c;
|
||||
|
||||
encryptedBlock = self.encryptBlock(aKey, nonce);
|
||||
|
||||
if ((messageLength - messageIndex) > blockSize) {
|
||||
c = blockSize;
|
||||
} else {
|
||||
c = messageLength - messageIndex;
|
||||
}
|
||||
|
||||
for (i=0; i<c; i++) {
|
||||
result[messageIndex + i] = result[messageIndex + i] ^ encryptedBlock[i];
|
||||
}
|
||||
|
||||
messageIndex += blockSize;
|
||||
// nonce = self.incrementNonce(nonce);
|
||||
self.incrementNonce(nonce)
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'encrypt': function(aKey, someData, aNonce) {
|
||||
var result;
|
||||
var nonce;
|
||||
var encryptedData;
|
||||
var key;
|
||||
|
||||
key = new Clipperz.Crypto.AES_2.Key({key:aKey});
|
||||
nonce = aNonce ? aNonce.clone() : Clipperz.Crypto.PRNG.defaultRandomGenerator().getRandomBytes(128/8);
|
||||
|
||||
encryptedData = Clipperz.Crypto.AES_2.encryptBlocks(key, someData.arrayValues(), nonce.arrayValues());
|
||||
|
||||
result = nonce.appendBytes(encryptedData);
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'decrypt': function(aKey, someData) {
|
||||
var result;
|
||||
var nonce;
|
||||
var encryptedData;
|
||||
var decryptedData;
|
||||
var dataIterator;
|
||||
var key;
|
||||
|
||||
key = new Clipperz.Crypto.AES_2.Key({key:aKey});
|
||||
|
||||
encryptedData = someData.arrayValues();
|
||||
nonce = encryptedData.slice(0, (128/8));
|
||||
encryptedData = encryptedData.slice(128/8);
|
||||
decryptedData = Clipperz.Crypto.AES_2.encryptBlocks(key, encryptedData, nonce);
|
||||
|
||||
result = new Clipperz.ByteArray(decryptedData);
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//=============================================================================
|
||||
|
||||
'deferredEncryptExecutionChunk': function(anExecutionContext) {
|
||||
var result;
|
||||
var nonce;
|
||||
var self;
|
||||
var messageIndex;
|
||||
var messageLength;
|
||||
var blockSize;
|
||||
var executionLimit;
|
||||
var startTime, endTime;
|
||||
|
||||
self = Clipperz.Crypto.AES_2;
|
||||
startTime = new Date();
|
||||
blockSize = 128/8;
|
||||
messageLength = anExecutionContext.messageArray().length;
|
||||
nonce = anExecutionContext.nonceArray();
|
||||
result = anExecutionContext.resultArray();
|
||||
|
||||
messageIndex = anExecutionContext.executionStep();
|
||||
executionLimit = messageIndex + anExecutionContext.elaborationChunkSize();
|
||||
executionLimit = Math.min(executionLimit, messageLength);
|
||||
|
||||
while (messageIndex < executionLimit) {
|
||||
var encryptedBlock;
|
||||
var i,c;
|
||||
|
||||
//console.log("+++ nonce: [" + nonce + "]")
|
||||
encryptedBlock = self.encryptBlock(anExecutionContext.key(), nonce);
|
||||
|
||||
if ((executionLimit - messageIndex) > blockSize) {
|
||||
c = blockSize;
|
||||
} else {
|
||||
c = executionLimit - messageIndex;
|
||||
}
|
||||
|
||||
for (i=0; i<c; i++) {
|
||||
result[messageIndex + i] = result[messageIndex + i] ^ encryptedBlock[i];
|
||||
}
|
||||
|
||||
messageIndex += blockSize;
|
||||
// nonce = self.incrementNonce(nonce);
|
||||
self.incrementNonce(nonce);
|
||||
}
|
||||
anExecutionContext.setExecutionStep(messageIndex);
|
||||
endTime = new Date();
|
||||
anExecutionContext.tuneExecutionParameters(endTime - startTime);
|
||||
|
||||
return anExecutionContext;
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'deferredEncryptBlocks': function(anExecutionContext) {
|
||||
var deferredResult;
|
||||
|
||||
//console.log("executionContext", anExecutionContext)
|
||||
//console.log(" --- nonce: " + anExecutionContext.nonceArray())
|
||||
if (! anExecutionContext.isDone()) {
|
||||
deferredResult = Clipperz.Async.callbacks("Clipperz.Crypto.AES_2.deferredEncryptBloks", [
|
||||
Clipperz.Crypto.AES_2.deferredEncryptExecutionChunk,
|
||||
MochiKit.Base.method(anExecutionContext, 'pause'),
|
||||
Clipperz.Crypto.AES_2.deferredEncryptBlocks
|
||||
], {trace:false}, anExecutionContext);
|
||||
} else {
|
||||
deferredResult = MochiKit.Async.succeed(anExecutionContext);
|
||||
}
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'deferredEncrypt': function(aKey, someData, aNonce) {
|
||||
var deferredResult;
|
||||
var executionContext;
|
||||
var result;
|
||||
var nonce;
|
||||
var key;
|
||||
|
||||
key = new Clipperz.Crypto.AES_2.Key({key:aKey});
|
||||
nonce = aNonce ? aNonce.clone() : Clipperz.Crypto.PRNG.defaultRandomGenerator().getRandomBytes(128/8);
|
||||
|
||||
executionContext = new Clipperz.Crypto.AES_2.DeferredExecutionContext({key:key, message:someData, nonce:nonce});
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("AES.deferredEncrypt");
|
||||
deferredResult.addCallback(Clipperz.Crypto.AES_2.deferredEncryptBlocks);
|
||||
deferredResult.addCallback(function(anExecutionContext) {
|
||||
var result;
|
||||
|
||||
result = anExecutionContext.nonce().clone();
|
||||
result.appendBytes(anExecutionContext.resultArray());
|
||||
|
||||
return result;
|
||||
});
|
||||
deferredResult.callback(executionContext)
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'deferredDecrypt': function(aKey, someData) {
|
||||
var deferredResult
|
||||
var nonce;
|
||||
var message;
|
||||
var key;
|
||||
|
||||
key = new Clipperz.Crypto.AES_2.Key({key:aKey});
|
||||
nonce = someData.split(0, (128/8));
|
||||
//console.log("nonce: [" + nonce.arrayValues() + "]")
|
||||
message = someData.split(128/8);
|
||||
//console.log("message: [" + message.arrayValues() + "]")
|
||||
executionContext = new Clipperz.Crypto.AES_2.DeferredExecutionContext({key:key, message:message, nonce:nonce});
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("AES.deferredDecrypt");
|
||||
deferredResult.addCallback(Clipperz.Crypto.AES_2.deferredEncryptBlocks);
|
||||
deferredResult.addCallback(function(anExecutionContext) {
|
||||
return anExecutionContext.result();
|
||||
});
|
||||
deferredResult.callback(executionContext);
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
__syntaxFix__: "syntax fix"
|
||||
|
||||
});
|
||||
|
||||
//#############################################################################
|
||||
|
||||
//Clipperz.Crypto.AES_2.DeferredExecution = {
|
||||
// 'chunkSize': 16384, // 4096, // 1024 4096 8192 16384 32768;
|
||||
// 'pauseTime': 0.02 // 0.2
|
||||
//}
|
||||
|
||||
Clipperz.Crypto.AES_2.exception = {
|
||||
'UnsupportedKeySize': new MochiKit.Base.NamedError("Clipperz.Crypto.AES_2.exception.UnsupportedKeySize")
|
||||
};
|
||||
1847
frontend/delta/js/Clipperz/Crypto/Base.js
Normal file
1847
frontend/delta/js/Clipperz/Crypto/Base.js
Normal file
File diff suppressed because it is too large
Load Diff
1754
frontend/delta/js/Clipperz/Crypto/BigInt.js
Normal file
1754
frontend/delta/js/Clipperz/Crypto/BigInt.js
Normal file
File diff suppressed because it is too large
Load Diff
1644
frontend/delta/js/Clipperz/Crypto/BigInt_scoped.js
Normal file
1644
frontend/delta/js/Clipperz/Crypto/BigInt_scoped.js
Normal file
File diff suppressed because it is too large
Load Diff
500
frontend/delta/js/Clipperz/Crypto/ECC/BinaryField/Curve.js
Normal file
500
frontend/delta/js/Clipperz/Crypto/ECC/BinaryField/Curve.js
Normal file
@@ -0,0 +1,500 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
//try { if (typeof(Clipperz.ByteArray) == 'undefined') { throw ""; }} catch (e) {
|
||||
// throw "Clipperz.Crypto.ECC depends on Clipperz.ByteArray!";
|
||||
//}
|
||||
if (typeof(Clipperz.Crypto.ECC) == 'undefined') { Clipperz.Crypto.ECC = {}; }
|
||||
if (typeof(Clipperz.Crypto.ECC.BinaryField) == 'undefined') { Clipperz.Crypto.ECC.BinaryField = {}; }
|
||||
|
||||
Clipperz.Crypto.ECC.BinaryField.Curve = function(args) {
|
||||
args = args || {};
|
||||
|
||||
this._modulus = args.modulus;
|
||||
|
||||
this._a = args.a;
|
||||
this._b = args.b;
|
||||
this._G = args.G;
|
||||
this._r = args.r;
|
||||
this._h = args.h;
|
||||
|
||||
this._finiteField = null;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
Clipperz.Crypto.ECC.BinaryField.Curve.prototype = MochiKit.Base.update(null, {
|
||||
|
||||
'asString': function() {
|
||||
return "Clipperz.Crypto.ECC.BinaryField.Curve";
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'modulus': function() {
|
||||
return this._modulus;
|
||||
},
|
||||
|
||||
'a': function() {
|
||||
return this._a;
|
||||
},
|
||||
|
||||
'b': function() {
|
||||
return this._b;
|
||||
},
|
||||
|
||||
'G': function() {
|
||||
return this._G;
|
||||
},
|
||||
|
||||
'r': function() {
|
||||
return this._r;
|
||||
},
|
||||
|
||||
'h': function() {
|
||||
return this._h;
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'finiteField': function() {
|
||||
if (this._finiteField == null) {
|
||||
this._finiteField = new Clipperz.Crypto.ECC.BinaryField.FiniteField({modulus:this.modulus()})
|
||||
}
|
||||
|
||||
return this._finiteField;
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'negate': function(aPointA) {
|
||||
var result;
|
||||
|
||||
result = new Clipperz.Crypto.ECC.Point({x:aPointA.x(), y:this.finiteField().add(aPointA.y(), aPointA.x())})
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'add': function(aPointA, aPointB) {
|
||||
var result;
|
||||
|
||||
if (aPointA.isZero()) {
|
||||
result = aPointB;
|
||||
} else if (aPointB.isZero()) {
|
||||
result = aPointA;
|
||||
} else if ( (aPointA.x().compare(aPointB.x()) == 0) && ((aPointA.y().compare(aPointB.y()) != 0) || aPointB.x().isZero())) {
|
||||
result = new Clipperz.Crypto.ECC.BinaryField.Point({x:Clipperz.Crypto.ECC.BinaryField.Value.O, y:Clipperz.Crypto.ECC.BinaryField.Value.O});
|
||||
} else {
|
||||
var f2m;
|
||||
var x, y;
|
||||
var lambda;
|
||||
var aX, aY, bX, bY;
|
||||
|
||||
aX = aPointA.x()._value;
|
||||
aY = aPointA.y()._value;
|
||||
bX = aPointB.x()._value;
|
||||
bY = aPointB.y()._value;
|
||||
|
||||
f2m = this.finiteField();
|
||||
|
||||
if (aPointA.x().compare(aPointB.x()) != 0) {
|
||||
lambda = f2m._fastMultiply(
|
||||
f2m._add(aY, bY),
|
||||
f2m._inverse(f2m._add(aX, bX))
|
||||
);
|
||||
x = f2m._add(this.a()._value, f2m._square(lambda));
|
||||
f2m._overwriteAdd(x, lambda);
|
||||
f2m._overwriteAdd(x, aX);
|
||||
f2m._overwriteAdd(x, bX);
|
||||
} else {
|
||||
lambda = f2m._add(bX, f2m._fastMultiply(bY, f2m._inverse(bX)));
|
||||
x = f2m._add(this.a()._value, f2m._square(lambda));
|
||||
f2m._overwriteAdd(x, lambda);
|
||||
}
|
||||
|
||||
y = f2m._fastMultiply(f2m._add(bX, x), lambda);
|
||||
f2m._overwriteAdd(y, x);
|
||||
f2m._overwriteAdd(y, bY);
|
||||
|
||||
result = new Clipperz.Crypto.ECC.BinaryField.Point({x:new Clipperz.Crypto.ECC.BinaryField.Value(x), y:new Clipperz.Crypto.ECC.BinaryField.Value(y)})
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'addTwice': function(aPointA) {
|
||||
return this.add(aPointA, aPointA);
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'overwriteAdd': function(aPointA, aPointB) {
|
||||
if (aPointA.isZero()) {
|
||||
// result = aPointB;
|
||||
aPointA._x._value = aPointB._x._value;
|
||||
aPointA._y._value = aPointB._y._value;
|
||||
} else if (aPointB.isZero()) {
|
||||
// result = aPointA;
|
||||
} else if ( (aPointA.x().compare(aPointB.x()) == 0) && ((aPointA.y().compare(aPointB.y()) != 0) || aPointB.x().isZero())) {
|
||||
// result = new Clipperz.Crypto.ECC.BinaryField.Point({x:Clipperz.Crypto.ECC.BinaryField.Value.O, y:Clipperz.Crypto.ECC.BinaryField.Value.O});
|
||||
aPointA._x = Clipperz.Crypto.ECC.BinaryField.Value.O;
|
||||
aPointA._y = Clipperz.Crypto.ECC.BinaryField.Value.O;
|
||||
} else {
|
||||
var f2m;
|
||||
var x, y;
|
||||
var lambda;
|
||||
var aX, aY, bX, bY;
|
||||
|
||||
aX = aPointA.x()._value;
|
||||
aY = aPointA.y()._value;
|
||||
bX = aPointB.x()._value;
|
||||
bY = aPointB.y()._value;
|
||||
|
||||
f2m = this.finiteField();
|
||||
|
||||
if (aPointA.x().compare(aPointB.x()) != 0) {
|
||||
lambda = f2m._fastMultiply(
|
||||
f2m._add(aY, bY),
|
||||
f2m._inverse(f2m._add(aX, bX))
|
||||
);
|
||||
x = f2m._add(this.a()._value, f2m._square(lambda));
|
||||
f2m._overwriteAdd(x, lambda);
|
||||
f2m._overwriteAdd(x, aX);
|
||||
f2m._overwriteAdd(x, bX);
|
||||
} else {
|
||||
lambda = f2m._add(bX, f2m._fastMultiply(bY, f2m._inverse(bX)));
|
||||
x = f2m._add(this.a()._value, f2m._square(lambda));
|
||||
f2m._overwriteAdd(x, lambda);
|
||||
}
|
||||
|
||||
y = f2m._fastMultiply(f2m._add(bX, x), lambda);
|
||||
f2m._overwriteAdd(y, x);
|
||||
f2m._overwriteAdd(y, bY);
|
||||
|
||||
// result = new Clipperz.Crypto.ECC.BinaryField.Point({x:new Clipperz.Crypto.ECC.BinaryField.Value(x), y:new Clipperz.Crypto.ECC.BinaryField.Value(y)})
|
||||
aPointA._x._value = x;
|
||||
aPointA._y._value = y;
|
||||
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'multiply': function(aValue, aPoint) {
|
||||
var result;
|
||||
|
||||
//console.profile();
|
||||
result = new Clipperz.Crypto.ECC.BinaryField.Point({x:Clipperz.Crypto.ECC.BinaryField.Value.O, y:Clipperz.Crypto.ECC.BinaryField.Value.O});
|
||||
|
||||
if (aValue.isZero() == false) {
|
||||
var k, Q;
|
||||
var i;
|
||||
var countIndex; countIndex = 0;
|
||||
|
||||
if (aValue.compare(Clipperz.Crypto.ECC.BinaryField.Value.O) > 0) {
|
||||
k = aValue;
|
||||
Q = aPoint;
|
||||
} else {
|
||||
Clipperz.logError("The Clipperz.Crypto.ECC.BinaryFields.Value does not work with negative values!!!!");
|
||||
k = aValue.negate();
|
||||
Q = this.negate(aPoint);
|
||||
}
|
||||
|
||||
for (i=k.bitSize()-1; i>=0; i--) {
|
||||
result = this.add(result, result);
|
||||
// this.overwriteAdd(result, result);
|
||||
if (k.isBitSet(i)) {
|
||||
result = this.add(result, Q);
|
||||
// this.overwriteAdd(result, Q);
|
||||
}
|
||||
|
||||
// if (countIndex==100) {Clipperz.log("multiply.break"); break;} else countIndex++;
|
||||
}
|
||||
}
|
||||
//console.profileEnd();
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'deferredMultiply': function(aValue, aPoint) {
|
||||
var deferredResult;
|
||||
var result;
|
||||
|
||||
Clipperz.log(">>> deferredMultiply - value: " + aValue + ", point: " + aPoint);
|
||||
//console.profile("ECC.Curve.multiply");
|
||||
deferredResult = new MochiKit.Async.Deferred();
|
||||
//deferredResult.addCallback(function(res) {console.profile("ECC.Curve.deferredMultiply"); return res;} );
|
||||
//deferredResult.addBoth(function(res) {Clipperz.logDebug("# 1: " + res); return res;});
|
||||
|
||||
result = new Clipperz.Crypto.ECC.BinaryField.Point({x:Clipperz.Crypto.ECC.BinaryField.Value.O, y:Clipperz.Crypto.ECC.BinaryField.Value.O});
|
||||
//deferredResult.addBoth(function(res) {Clipperz.logDebug("# 2: " + res); return res;});
|
||||
|
||||
if (aValue.isZero() == false) {
|
||||
var k, Q;
|
||||
var i;
|
||||
var countIndex; countIndex = 0;
|
||||
|
||||
if (aValue.compare(Clipperz.Crypto.ECC.BinaryField.Value.O) > 0) {
|
||||
k = aValue;
|
||||
Q = aPoint;
|
||||
} else {
|
||||
Clipperz.logError("The Clipperz.Crypto.ECC.BinaryFields.Value does not work with negative values!!!!");
|
||||
k = aValue.negate();
|
||||
Q = this.negate(aPoint);
|
||||
}
|
||||
|
||||
|
||||
for (i=k.bitSize()-1; i>=0; i--) {
|
||||
deferredResult.addMethod(this, "addTwice");
|
||||
//# result = this.add(result, result);
|
||||
// this.overwriteAdd(result, result);
|
||||
if (k.isBitSet(i)) {
|
||||
deferredResult.addMethod(this, "add", Q);
|
||||
//# result = this.add(result, Q);
|
||||
// this.overwriteAdd(result, Q);
|
||||
}
|
||||
if (i%20 == 0) {deferredResult.addCallback(MochiKit.Async.wait, 0.1);}
|
||||
}
|
||||
}
|
||||
//#console.profileEnd();
|
||||
//deferredResult.addBoth(function(res) {console.profileEnd(); return res;});
|
||||
deferredResult.callback(result);
|
||||
|
||||
//# return result;
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
__syntaxFix__: "syntax fix"
|
||||
});
|
||||
|
||||
|
||||
//#############################################################################
|
||||
|
||||
Clipperz.Crypto.ECC.StandardCurves = {};
|
||||
|
||||
MochiKit.Base.update(Clipperz.Crypto.ECC.StandardCurves, {
|
||||
/*
|
||||
'_K571': null,
|
||||
'K571': function() {
|
||||
if (Clipperz.Crypto.ECC.StandardCurves._K571 == null) {
|
||||
Clipperz.Crypto.ECC.StandardCurves._K571 = new Clipperz.Crypto.ECC.BinaryField.Curve({
|
||||
modulus: new Clipperz.Crypto.ECC.BinaryField.Value('08000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000425', 16),
|
||||
a: new Clipperz.Crypto.ECC.BinaryField.Value('0', 16),
|
||||
b: new Clipperz.Crypto.ECC.BinaryField.Value('1', 16),
|
||||
G: new Clipperz.Crypto.ECC.BinaryField.Point({
|
||||
x: new Clipperz.Crypto.ECC.BinaryField.Value('026eb7a8 59923fbc 82189631 f8103fe4 ac9ca297 0012d5d4 60248048 01841ca4 43709584 93b205e6 47da304d b4ceb08c bbd1ba39 494776fb 988b4717 4dca88c7 e2945283 a01c8972', 16),
|
||||
y: new Clipperz.Crypto.ECC.BinaryField.Value('0349dc80 7f4fbf37 4f4aeade 3bca9531 4dd58cec 9f307a54 ffc61efc 006d8a2c 9d4979c0 ac44aea7 4fbebbb9 f772aedc b620b01a 7ba7af1b 320430c8 591984f6 01cd4c14 3ef1c7a3', 16)
|
||||
}),
|
||||
r: new Clipperz.Crypto.ECC.BinaryField.Value('02000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 131850e1 f19a63e4 b391a8db 917f4138 b630d84b e5d63938 1e91deb4 5cfe778f 637c1001', 16),
|
||||
h: new Clipperz.Crypto.ECC.BinaryField.Value('4', 16)
|
||||
});
|
||||
}
|
||||
|
||||
return Clipperz.Crypto.ECC.StandardCurves._K571;
|
||||
},
|
||||
|
||||
|
||||
|
||||
'_K283': null,
|
||||
'K283': function() { // f(z) = z^283 + z^12 + z^7 + z^5 + 1
|
||||
if (Clipperz.Crypto.ECC.StandardCurves._K283 == null) {
|
||||
Clipperz.Crypto.ECC.StandardCurves._K283 = new Clipperz.Crypto.ECC.BinaryField.Curve({
|
||||
modulus: new Clipperz.Crypto.ECC.BinaryField.Value('08000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 000010a1', 16),
|
||||
a: new Clipperz.Crypto.ECC.BinaryField.Value('0', 16),
|
||||
b: new Clipperz.Crypto.ECC.BinaryField.Value('1', 16),
|
||||
G: new Clipperz.Crypto.ECC.BinaryField.Point({
|
||||
x: new Clipperz.Crypto.ECC.BinaryField.Value('0503213f 78ca4488 3f1a3b81 62f188e5 53cd265f 23c1567a 16876913 b0c2ac24 58492836', 16),
|
||||
y: new Clipperz.Crypto.ECC.BinaryField.Value('01ccda38 0f1c9e31 8d90f95d 07e5426f e87e45c0 e8184698 e4596236 4e341161 77dd2259', 16)
|
||||
}),
|
||||
r: new Clipperz.Crypto.ECC.BinaryField.Value('01ffffff ffffffff ffffffff ffffffff ffffe9ae 2ed07577 265dff7f 94451e06 1e163c61', 16),
|
||||
h: new Clipperz.Crypto.ECC.BinaryField.Value('4', 16)
|
||||
});
|
||||
}
|
||||
|
||||
return Clipperz.Crypto.ECC.StandardCurves._K283;
|
||||
},
|
||||
*/
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'_B571': null,
|
||||
'B571': function() { // f(z) = z^571 + z^10 + z^5 + z^2 + 1
|
||||
if (Clipperz.Crypto.ECC.StandardCurves._B571 == null) {
|
||||
Clipperz.Crypto.ECC.StandardCurves._B571 = new Clipperz.Crypto.ECC.BinaryField.Curve({
|
||||
modulus: new Clipperz.Crypto.ECC.BinaryField.Value('80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000425', 16),
|
||||
a: new Clipperz.Crypto.ECC.BinaryField.Value('1', 16),
|
||||
b: new Clipperz.Crypto.ECC.BinaryField.Value('02f40e7e2221f295de297117b7f3d62f5c6a97ffcb8ceff1cd6ba8ce4a9a18ad84ffabbd8efa59332be7ad6756a66e294afd185a78ff12aa520e4de739baca0c7ffeff7f2955727a', 16),
|
||||
G: new Clipperz.Crypto.ECC.BinaryField.Point({
|
||||
x: new Clipperz.Crypto.ECC.BinaryField.Value('0303001d 34b85629 6c16c0d4 0d3cd775 0a93d1d2 955fa80a a5f40fc8 db7b2abd bde53950 f4c0d293 cdd711a3 5b67fb14 99ae6003 8614f139 4abfa3b4 c850d927 e1e7769c 8eec2d19', 16),
|
||||
y: new Clipperz.Crypto.ECC.BinaryField.Value('037bf273 42da639b 6dccfffe b73d69d7 8c6c27a6 009cbbca 1980f853 3921e8a6 84423e43 bab08a57 6291af8f 461bb2a8 b3531d2f 0485c19b 16e2f151 6e23dd3c 1a4827af 1b8ac15b', 16)
|
||||
}),
|
||||
r: new Clipperz.Crypto.ECC.BinaryField.Value('03ffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff e661ce18 ff559873 08059b18 6823851e c7dd9ca1 161de93d 5174d66e 8382e9bb 2fe84e47', 16),
|
||||
h: new Clipperz.Crypto.ECC.BinaryField.Value('2', 16)
|
||||
|
||||
// S: new Clipperz.Crypto.ECC.BinaryField.Value('2aa058f73a0e33ab486b0f610410c53a7f132310', 10),
|
||||
// n: new Clipperz.Crypto.ECC.BinaryField.Value('03ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe661ce18ff55987308059b186823851ec7dd9ca1161de93d5174d66e8382e9bb2fe84e47', 16)
|
||||
});
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Guide to Elliptic Curve Cryptography
|
||||
// Darrel Hankerson, Alfred Menezes, Scott Vanstone
|
||||
// - Pag: 56, Alorithm 2.45 (with a typo!!!)
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// http://www.milw0rm.com/papers/136
|
||||
//
|
||||
// -------------------------------------------------------------------------
|
||||
// Polynomial Reduction Algorithm Modulo f571
|
||||
// -------------------------------------------------------------------------
|
||||
//
|
||||
// Input: Polynomial p(x) of degree 1140 or less, stored as
|
||||
// an array of 2T machinewords.
|
||||
// Output: p(x) mod f571(x)
|
||||
//
|
||||
// FOR i = T-1, ..., 0 DO
|
||||
// SET X := P[i+T]
|
||||
// P[i] := P[i] ^ (X<<5) ^ (X<<7) ^ (X<<10) ^ (X<<15)
|
||||
// P[i+1] := P[i+1] ^ (X>>17) ^ (X>>22) ^ (X>>25) ^ (X>>27)
|
||||
//
|
||||
// SET X := P[T-1] >> 27
|
||||
// P[0] := P[0] ^ X ^ (X<<2) ^ (X<<5) ^ (X<<10)
|
||||
// P[T-1] := P[T-1] & 0x07ffffff
|
||||
//
|
||||
// RETURN P[T-1],...,P[0]
|
||||
//
|
||||
// -------------------------------------------------------------------------
|
||||
//
|
||||
Clipperz.Crypto.ECC.StandardCurves._B571.finiteField().slowModule = Clipperz.Crypto.ECC.StandardCurves._B571.finiteField().module;
|
||||
Clipperz.Crypto.ECC.StandardCurves._B571.finiteField().module = function(aValue) {
|
||||
var result;
|
||||
|
||||
if (aValue.bitSize() > 1140) {
|
||||
Clipperz.logWarning("ECC.StandarCurves.B571.finiteField().module: falling back to default implementation");
|
||||
result = Clipperz.Crypto.ECC.StandardCurves._B571.finiteField().slowModule(aValue);
|
||||
} else {
|
||||
var C, T;
|
||||
var i;
|
||||
|
||||
C = aValue._value.slice(0);
|
||||
for (i=35; i>=18; i--) {
|
||||
T = C[i];
|
||||
C[i-18] = (((C[i-18] ^ (T<<5) ^ (T<<7) ^ (T<<10) ^ (T<<15)) & 0xffffffff) >>> 0);
|
||||
C[i-17] = ((C[i-17] ^ (T>>>27) ^ (T>>>25) ^ (T>>>22) ^ (T>>>17)) >>> 0);
|
||||
}
|
||||
T = (C[17] >>> 27);
|
||||
C[0] = ((C[0] ^ T ^ ((T<<2) ^ (T<<5) ^ (T<<10)) & 0xffffffff) >>> 0);
|
||||
C[17] = (C[17] & 0x07ffffff);
|
||||
|
||||
for(i=18; i<=35; i++) {
|
||||
C[i] = 0;
|
||||
}
|
||||
|
||||
result = new Clipperz.Crypto.ECC.BinaryField.Value(C);
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
}
|
||||
|
||||
return Clipperz.Crypto.ECC.StandardCurves._B571;
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'_B283': null,
|
||||
'B283': function() { // f(z) = z^283 + z^12 + z^7 + z^5 + 1
|
||||
if (Clipperz.Crypto.ECC.StandardCurves._B283 == null) {
|
||||
Clipperz.Crypto.ECC.StandardCurves._B283 = new Clipperz.Crypto.ECC.BinaryField.Curve({
|
||||
// modulus: new Clipperz.Crypto.ECC.BinaryField.Value('10000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 000010a1', 16),
|
||||
modulus: new Clipperz.Crypto.ECC.BinaryField.Value('08000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 000010a1', 16),
|
||||
a: new Clipperz.Crypto.ECC.BinaryField.Value('1', 16),
|
||||
b: new Clipperz.Crypto.ECC.BinaryField.Value('027b680a c8b8596d a5a4af8a 19a0303f ca97fd76 45309fa2 a581485a f6263e31 3b79a2f5', 16),
|
||||
G: new Clipperz.Crypto.ECC.BinaryField.Point({
|
||||
x: new Clipperz.Crypto.ECC.BinaryField.Value('05f93925 8db7dd90 e1934f8c 70b0dfec 2eed25b8 557eac9c 80e2e198 f8cdbecd 86b12053', 16),
|
||||
y: new Clipperz.Crypto.ECC.BinaryField.Value('03676854 fe24141c b98fe6d4 b20d02b4 516ff702 350eddb0 826779c8 13f0df45 be8112f4', 16)
|
||||
}),
|
||||
r: new Clipperz.Crypto.ECC.BinaryField.Value('03ffffff ffffffff ffffffff ffffffff ffffef90 399660fc 938a9016 5b042a7c efadb307', 16),
|
||||
h: new Clipperz.Crypto.ECC.BinaryField.Value('2', 16)
|
||||
|
||||
// S: new Clipperz.Crypto.ECC.BinaryField.Value('2aa058f73a0e33ab486b0f610410c53a7f132310', 10),
|
||||
// n: new Clipperz.Crypto.ECC.BinaryField.Value('03ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe661ce18ff55987308059b186823851ec7dd9ca1161de93d5174d66e8382e9bb2fe84e47', 16)
|
||||
});
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Guide to Elliptic Curve Cryptography
|
||||
// Darrel Hankerson, Alfred Menezes, Scott Vanstone
|
||||
// - Pag: 56, Alorithm 2.43
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
Clipperz.Crypto.ECC.StandardCurves._B283.finiteField().slowModule = Clipperz.Crypto.ECC.StandardCurves._B283.finiteField().module;
|
||||
Clipperz.Crypto.ECC.StandardCurves._B283.finiteField().module = function(aValue) {
|
||||
var result;
|
||||
|
||||
if (aValue.bitSize() > 564) {
|
||||
Clipperz.logWarning("ECC.StandarCurves.B283.finiteField().module: falling back to default implementation");
|
||||
result = Clipperz.Crypto.ECC.StandardCurves._B283.finiteField().slowModule(aValue);
|
||||
} else {
|
||||
var C, T;
|
||||
var i;
|
||||
|
||||
C = aValue._value.slice(0);
|
||||
for (i=17; i>=9; i--) {
|
||||
T = C[i];
|
||||
C[i-9] = (((C[i-9] ^ (T<<5) ^ (T<<10) ^ (T<<12) ^ (T<<17)) & 0xffffffff) >>> 0);
|
||||
C[i-8] = ((C[i-8] ^ (T>>>27) ^ (T>>>22) ^ (T>>>20) ^ (T>>>15)) >>> 0);
|
||||
}
|
||||
T = (C[8] >>> 27);
|
||||
C[0] = ((C[0] ^ T ^ ((T<<5) ^ (T<<7) ^ (T<<12)) & 0xffffffff) >>> 0);
|
||||
C[8] = (C[8] & 0x07ffffff);
|
||||
|
||||
for(i=9; i<=17; i++) {
|
||||
C[i] = 0;
|
||||
}
|
||||
|
||||
result = new Clipperz.Crypto.ECC.BinaryField.Value(C);
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
}
|
||||
|
||||
return Clipperz.Crypto.ECC.StandardCurves._B283;
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
__syntaxFix__: "syntax fix"
|
||||
});
|
||||
|
||||
//#############################################################################
|
||||
|
||||
519
frontend/delta/js/Clipperz/Crypto/ECC/BinaryField/FiniteField.js
Normal file
519
frontend/delta/js/Clipperz/Crypto/ECC/BinaryField/FiniteField.js
Normal file
@@ -0,0 +1,519 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
//try { if (typeof(Clipperz.ByteArray) == 'undefined') { throw ""; }} catch (e) {
|
||||
// throw "Clipperz.Crypto.ECC depends on Clipperz.ByteArray!";
|
||||
//}
|
||||
if (typeof(Clipperz.Crypto.ECC) == 'undefined') { Clipperz.Crypto.ECC = {}; }
|
||||
if (typeof(Clipperz.Crypto.ECC.BinaryField) == 'undefined') { Clipperz.Crypto.ECC.BinaryField = {}; }
|
||||
|
||||
Clipperz.Crypto.ECC.BinaryField.FiniteField = function(args) {
|
||||
args = args || {};
|
||||
this._modulus = args.modulus;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
Clipperz.Crypto.ECC.BinaryField.FiniteField.prototype = MochiKit.Base.update(null, {
|
||||
|
||||
'asString': function() {
|
||||
return "Clipperz.Crypto.ECC.BinaryField.FiniteField (" + this.modulus().asString() + ")";
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'modulus': function() {
|
||||
return this._modulus;
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'_module': function(aValue) {
|
||||
var result;
|
||||
var modulusComparison;
|
||||
|
||||
modulusComparison = Clipperz.Crypto.ECC.BinaryField.Value._compare(aValue, this.modulus()._value);
|
||||
|
||||
if (modulusComparison < 0) {
|
||||
result = aValue;
|
||||
} else if (modulusComparison == 0) {
|
||||
result = [0];
|
||||
} else {
|
||||
var modulusBitSize;
|
||||
var resultBitSize;
|
||||
|
||||
result = aValue;
|
||||
|
||||
modulusBitSize = this.modulus().bitSize();
|
||||
resultBitSize = Clipperz.Crypto.ECC.BinaryField.Value._bitSize(result);
|
||||
while (resultBitSize >= modulusBitSize) {
|
||||
Clipperz.Crypto.ECC.BinaryField.Value._overwriteXor(result, Clipperz.Crypto.ECC.BinaryField.Value._shiftLeft(this.modulus()._value, resultBitSize - modulusBitSize));
|
||||
resultBitSize = Clipperz.Crypto.ECC.BinaryField.Value._bitSize(result);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
'module': function(aValue) {
|
||||
return new Clipperz.Crypto.ECC.BinaryField.Value(this._module(aValue._value.slice(0)));
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'_add': function(a, b) {
|
||||
return Clipperz.Crypto.ECC.BinaryField.Value._xor(a, b);
|
||||
},
|
||||
|
||||
'_overwriteAdd': function(a, b) {
|
||||
Clipperz.Crypto.ECC.BinaryField.Value._overwriteXor(a, b);
|
||||
},
|
||||
|
||||
'add': function(a, b) {
|
||||
return new Clipperz.Crypto.ECC.BinaryField.Value(this._add(a._value, b._value));
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'negate': function(aValue) {
|
||||
return aValue.clone();
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'_multiply': function(a, b) {
|
||||
var result;
|
||||
var valueToXor;
|
||||
var i,c;
|
||||
|
||||
result = [0];
|
||||
valueToXor = b;
|
||||
c = Clipperz.Crypto.ECC.BinaryField.Value._bitSize(a);
|
||||
for (i=0; i<c; i++) {
|
||||
if (Clipperz.Crypto.ECC.BinaryField.Value._isBitSet(a, i) === true) {
|
||||
Clipperz.Crypto.ECC.BinaryField.Value._overwriteXor(result, valueToXor);
|
||||
}
|
||||
valueToXor = Clipperz.Crypto.ECC.BinaryField.Value._overwriteShiftLeft(valueToXor, 1);
|
||||
}
|
||||
result = this._module(result);
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
'multiply': function(a, b) {
|
||||
return new Clipperz.Crypto.ECC.BinaryField.Value(this._multiply(a._value, b._value));
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'_fastMultiply': function(a, b) {
|
||||
var result;
|
||||
var B;
|
||||
var i,c;
|
||||
|
||||
result = [0];
|
||||
B = b.slice(0); // Is this array copy avoidable?
|
||||
c = 32;
|
||||
for (i=0; i<c; i++) {
|
||||
var ii, cc;
|
||||
|
||||
cc = a.length;
|
||||
for (ii=0; ii<cc; ii++) {
|
||||
if (((a[ii] >>> i) & 0x01) == 1) {
|
||||
Clipperz.Crypto.ECC.BinaryField.Value._overwriteXor(result, B, ii);
|
||||
}
|
||||
}
|
||||
|
||||
if (i < (c-1)) {
|
||||
B = Clipperz.Crypto.ECC.BinaryField.Value._overwriteShiftLeft(B, 1);
|
||||
}
|
||||
}
|
||||
result = this._module(result);
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
'fastMultiply': function(a, b) {
|
||||
return new Clipperz.Crypto.ECC.BinaryField.Value(this._fastMultiply(a._value, b._value));
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Guide to Elliptic Curve Cryptography
|
||||
// Darrel Hankerson, Alfred Menezes, Scott Vanstone
|
||||
// - Pag: 49, Alorithm 2.34
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'_square': function(aValue) {
|
||||
var result;
|
||||
var value;
|
||||
var c,i;
|
||||
var precomputedValues;
|
||||
|
||||
value = aValue;
|
||||
result = new Array(value.length * 2);
|
||||
precomputedValues = Clipperz.Crypto.ECC.BinaryField.FiniteField.squarePrecomputedBytes;
|
||||
|
||||
c = value.length;
|
||||
for (i=0; i<c; i++) {
|
||||
result[i*2] = precomputedValues[(value[i] & 0x000000ff)];
|
||||
result[i*2] |= ((precomputedValues[(value[i] & 0x0000ff00) >>> 8]) << 16);
|
||||
|
||||
result[i*2 + 1] = precomputedValues[(value[i] & 0x00ff0000) >>> 16];
|
||||
result[i*2 + 1] |= ((precomputedValues[(value[i] & 0xff000000) >>> 24]) << 16);
|
||||
}
|
||||
|
||||
return this._module(result);
|
||||
},
|
||||
|
||||
'square': function(aValue) {
|
||||
return new Clipperz.Crypto.ECC.BinaryField.Value(this._square(aValue._value));
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'_inverse': function(aValue) {
|
||||
var result;
|
||||
var b, c;
|
||||
var u, v;
|
||||
|
||||
// b = Clipperz.Crypto.ECC.BinaryField.Value.I._value;
|
||||
b = [1];
|
||||
// c = Clipperz.Crypto.ECC.BinaryField.Value.O._value;
|
||||
c = [0];
|
||||
u = this._module(aValue);
|
||||
v = this.modulus()._value.slice(0);
|
||||
|
||||
while (Clipperz.Crypto.ECC.BinaryField.Value._bitSize(u) > 1) {
|
||||
var bitDifferenceSize;
|
||||
|
||||
bitDifferenceSize = Clipperz.Crypto.ECC.BinaryField.Value._bitSize(u) - Clipperz.Crypto.ECC.BinaryField.Value._bitSize(v);
|
||||
if (bitDifferenceSize < 0) {
|
||||
var swap;
|
||||
|
||||
swap = u;
|
||||
u = v;
|
||||
v = swap;
|
||||
|
||||
swap = c;
|
||||
c = b;
|
||||
b = swap;
|
||||
|
||||
bitDifferenceSize = -bitDifferenceSize;
|
||||
}
|
||||
|
||||
u = this._add(u, Clipperz.Crypto.ECC.BinaryField.Value._shiftLeft(v, bitDifferenceSize));
|
||||
b = this._add(b, Clipperz.Crypto.ECC.BinaryField.Value._shiftLeft(c, bitDifferenceSize));
|
||||
// this._overwriteAdd(u, Clipperz.Crypto.ECC.BinaryField.Value._shiftLeft(v, bitDifferenceSize));
|
||||
// this._overwriteAdd(b, Clipperz.Crypto.ECC.BinaryField.Value._shiftLeft(c, bitDifferenceSize));
|
||||
}
|
||||
|
||||
result = this._module(b);
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
'inverse': function(aValue) {
|
||||
return new Clipperz.Crypto.ECC.BinaryField.Value(this._inverse(aValue._value));
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
__syntaxFix__: "syntax fix"
|
||||
});
|
||||
|
||||
|
||||
Clipperz.Crypto.ECC.BinaryField.FiniteField.squarePrecomputedBytes = [
|
||||
0x0000, // 0 = 0000 0000 -> 0000 0000 0000 0000
|
||||
0x0001, // 1 = 0000 0001 -> 0000 0000 0000 0001
|
||||
0x0004, // 2 = 0000 0010 -> 0000 0000 0000 0100
|
||||
0x0005, // 3 = 0000 0011 -> 0000 0000 0000 0101
|
||||
0x0010, // 4 = 0000 0100 -> 0000 0000 0001 0000
|
||||
0x0011, // 5 = 0000 0101 -> 0000 0000 0001 0001
|
||||
0x0014, // 6 = 0000 0110 -> 0000 0000 0001 0100
|
||||
0x0015, // 7 = 0000 0111 -> 0000 0000 0001 0101
|
||||
0x0040, // 8 = 0000 1000 -> 0000 0000 0100 0000
|
||||
0x0041, // 9 = 0000 1001 -> 0000 0000 0100 0001
|
||||
0x0044, // 10 = 0000 1010 -> 0000 0000 0100 0100
|
||||
0x0045, // 11 = 0000 1011 -> 0000 0000 0100 0101
|
||||
0x0050, // 12 = 0000 1100 -> 0000 0000 0101 0000
|
||||
0x0051, // 13 = 0000 1101 -> 0000 0000 0101 0001
|
||||
0x0054, // 14 = 0000 1110 -> 0000 0000 0101 0100
|
||||
0x0055, // 15 = 0000 1111 -> 0000 0000 0101 0101
|
||||
|
||||
0x0100, // 16 = 0001 0000 -> 0000 0001 0000 0000
|
||||
0x0101, // 17 = 0001 0001 -> 0000 0001 0000 0001
|
||||
0x0104, // 18 = 0001 0010 -> 0000 0001 0000 0100
|
||||
0x0105, // 19 = 0001 0011 -> 0000 0001 0000 0101
|
||||
0x0110, // 20 = 0001 0100 -> 0000 0001 0001 0000
|
||||
0x0111, // 21 = 0001 0101 -> 0000 0001 0001 0001
|
||||
0x0114, // 22 = 0001 0110 -> 0000 0001 0001 0100
|
||||
0x0115, // 23 = 0001 0111 -> 0000 0001 0001 0101
|
||||
0x0140, // 24 = 0001 1000 -> 0000 0001 0100 0000
|
||||
0x0141, // 25 = 0001 1001 -> 0000 0001 0100 0001
|
||||
0x0144, // 26 = 0001 1010 -> 0000 0001 0100 0100
|
||||
0x0145, // 27 = 0001 1011 -> 0000 0001 0100 0101
|
||||
0x0150, // 28 = 0001 1100 -> 0000 0001 0101 0000
|
||||
0x0151, // 28 = 0001 1101 -> 0000 0001 0101 0001
|
||||
0x0154, // 30 = 0001 1110 -> 0000 0001 0101 0100
|
||||
0x0155, // 31 = 0001 1111 -> 0000 0001 0101 0101
|
||||
|
||||
0x0400, // 32 = 0010 0000 -> 0000 0100 0000 0000
|
||||
0x0401, // 33 = 0010 0001 -> 0000 0100 0000 0001
|
||||
0x0404, // 34 = 0010 0010 -> 0000 0100 0000 0100
|
||||
0x0405, // 35 = 0010 0011 -> 0000 0100 0000 0101
|
||||
0x0410, // 36 = 0010 0100 -> 0000 0100 0001 0000
|
||||
0x0411, // 37 = 0010 0101 -> 0000 0100 0001 0001
|
||||
0x0414, // 38 = 0010 0110 -> 0000 0100 0001 0100
|
||||
0x0415, // 39 = 0010 0111 -> 0000 0100 0001 0101
|
||||
0x0440, // 40 = 0010 1000 -> 0000 0100 0100 0000
|
||||
0x0441, // 41 = 0010 1001 -> 0000 0100 0100 0001
|
||||
0x0444, // 42 = 0010 1010 -> 0000 0100 0100 0100
|
||||
0x0445, // 43 = 0010 1011 -> 0000 0100 0100 0101
|
||||
0x0450, // 44 = 0010 1100 -> 0000 0100 0101 0000
|
||||
0x0451, // 45 = 0010 1101 -> 0000 0100 0101 0001
|
||||
0x0454, // 46 = 0010 1110 -> 0000 0100 0101 0100
|
||||
0x0455, // 47 = 0010 1111 -> 0000 0100 0101 0101
|
||||
|
||||
0x0500, // 48 = 0011 0000 -> 0000 0101 0000 0000
|
||||
0x0501, // 49 = 0011 0001 -> 0000 0101 0000 0001
|
||||
0x0504, // 50 = 0011 0010 -> 0000 0101 0000 0100
|
||||
0x0505, // 51 = 0011 0011 -> 0000 0101 0000 0101
|
||||
0x0510, // 52 = 0011 0100 -> 0000 0101 0001 0000
|
||||
0x0511, // 53 = 0011 0101 -> 0000 0101 0001 0001
|
||||
0x0514, // 54 = 0011 0110 -> 0000 0101 0001 0100
|
||||
0x0515, // 55 = 0011 0111 -> 0000 0101 0001 0101
|
||||
0x0540, // 56 = 0011 1000 -> 0000 0101 0100 0000
|
||||
0x0541, // 57 = 0011 1001 -> 0000 0101 0100 0001
|
||||
0x0544, // 58 = 0011 1010 -> 0000 0101 0100 0100
|
||||
0x0545, // 59 = 0011 1011 -> 0000 0101 0100 0101
|
||||
0x0550, // 60 = 0011 1100 -> 0000 0101 0101 0000
|
||||
0x0551, // 61 = 0011 1101 -> 0000 0101 0101 0001
|
||||
0x0554, // 62 = 0011 1110 -> 0000 0101 0101 0100
|
||||
0x0555, // 63 = 0011 1111 -> 0000 0101 0101 0101
|
||||
|
||||
0x1000, // 64 = 0100 0000 -> 0001 0000 0000 0000
|
||||
0x1001, // 65 = 0100 0001 -> 0001 0000 0000 0001
|
||||
0x1004, // 66 = 0100 0010 -> 0001 0000 0000 0100
|
||||
0x1005, // 67 = 0100 0011 -> 0001 0000 0000 0101
|
||||
0x1010, // 68 = 0100 0100 -> 0001 0000 0001 0000
|
||||
0x1011, // 69 = 0100 0101 -> 0001 0000 0001 0001
|
||||
0x1014, // 70 = 0100 0110 -> 0001 0000 0001 0100
|
||||
0x1015, // 71 = 0100 0111 -> 0001 0000 0001 0101
|
||||
0x1040, // 72 = 0100 1000 -> 0001 0000 0100 0000
|
||||
0x1041, // 73 = 0100 1001 -> 0001 0000 0100 0001
|
||||
0x1044, // 74 = 0100 1010 -> 0001 0000 0100 0100
|
||||
0x1045, // 75 = 0100 1011 -> 0001 0000 0100 0101
|
||||
0x1050, // 76 = 0100 1100 -> 0001 0000 0101 0000
|
||||
0x1051, // 77 = 0100 1101 -> 0001 0000 0101 0001
|
||||
0x1054, // 78 = 0100 1110 -> 0001 0000 0101 0100
|
||||
0x1055, // 79 = 0100 1111 -> 0001 0000 0101 0101
|
||||
|
||||
0x1100, // 80 = 0101 0000 -> 0001 0001 0000 0000
|
||||
0x1101, // 81 = 0101 0001 -> 0001 0001 0000 0001
|
||||
0x1104, // 82 = 0101 0010 -> 0001 0001 0000 0100
|
||||
0x1105, // 83 = 0101 0011 -> 0001 0001 0000 0101
|
||||
0x1110, // 84 = 0101 0100 -> 0001 0001 0001 0000
|
||||
0x1111, // 85 = 0101 0101 -> 0001 0001 0001 0001
|
||||
0x1114, // 86 = 0101 0110 -> 0001 0001 0001 0100
|
||||
0x1115, // 87 = 0101 0111 -> 0001 0001 0001 0101
|
||||
0x1140, // 88 = 0101 1000 -> 0001 0001 0100 0000
|
||||
0x1141, // 89 = 0101 1001 -> 0001 0001 0100 0001
|
||||
0x1144, // 90 = 0101 1010 -> 0001 0001 0100 0100
|
||||
0x1145, // 91 = 0101 1011 -> 0001 0001 0100 0101
|
||||
0x1150, // 92 = 0101 1100 -> 0001 0001 0101 0000
|
||||
0x1151, // 93 = 0101 1101 -> 0001 0001 0101 0001
|
||||
0x1154, // 94 = 0101 1110 -> 0001 0001 0101 0100
|
||||
0x1155, // 95 = 0101 1111 -> 0001 0001 0101 0101
|
||||
|
||||
0x1400, // 96 = 0110 0000 -> 0001 0100 0000 0000
|
||||
0x1401, // 97 = 0110 0001 -> 0001 0100 0000 0001
|
||||
0x1404, // 98 = 0110 0010 -> 0001 0100 0000 0100
|
||||
0x1405, // 99 = 0110 0011 -> 0001 0100 0000 0101
|
||||
0x1410, // 100 = 0110 0100 -> 0001 0100 0001 0000
|
||||
0x1411, // 101 = 0110 0101 -> 0001 0100 0001 0001
|
||||
0x1414, // 102 = 0110 0110 -> 0001 0100 0001 0100
|
||||
0x1415, // 103 = 0110 0111 -> 0001 0100 0001 0101
|
||||
0x1440, // 104 = 0110 1000 -> 0001 0100 0100 0000
|
||||
0x1441, // 105 = 0110 1001 -> 0001 0100 0100 0001
|
||||
0x1444, // 106 = 0110 1010 -> 0001 0100 0100 0100
|
||||
0x1445, // 107 = 0110 1011 -> 0001 0100 0100 0101
|
||||
0x1450, // 108 = 0110 1100 -> 0001 0100 0101 0000
|
||||
0x1451, // 109 = 0110 1101 -> 0001 0100 0101 0001
|
||||
0x1454, // 110 = 0110 1110 -> 0001 0100 0101 0100
|
||||
0x1455, // 111 = 0110 1111 -> 0001 0100 0101 0101
|
||||
|
||||
0x1500, // 112 = 0111 0000 -> 0001 0101 0000 0000
|
||||
0x1501, // 113 = 0111 0001 -> 0001 0101 0000 0001
|
||||
0x1504, // 114 = 0111 0010 -> 0001 0101 0000 0100
|
||||
0x1505, // 115 = 0111 0011 -> 0001 0101 0000 0101
|
||||
0x1510, // 116 = 0111 0100 -> 0001 0101 0001 0000
|
||||
0x1511, // 117 = 0111 0101 -> 0001 0101 0001 0001
|
||||
0x1514, // 118 = 0111 0110 -> 0001 0101 0001 0100
|
||||
0x1515, // 119 = 0111 0111 -> 0001 0101 0001 0101
|
||||
0x1540, // 120 = 0111 1000 -> 0001 0101 0100 0000
|
||||
0x1541, // 121 = 0111 1001 -> 0001 0101 0100 0001
|
||||
0x1544, // 122 = 0111 1010 -> 0001 0101 0100 0100
|
||||
0x1545, // 123 = 0111 1011 -> 0001 0101 0100 0101
|
||||
0x1550, // 124 = 0111 1100 -> 0001 0101 0101 0000
|
||||
0x1551, // 125 = 0111 1101 -> 0001 0101 0101 0001
|
||||
0x1554, // 126 = 0111 1110 -> 0001 0101 0101 0100
|
||||
0x1555, // 127 = 0111 1111 -> 0001 0101 0101 0101
|
||||
|
||||
0x4000, // 128 = 1000 0000 -> 0100 0000 0000 0000
|
||||
0x4001, // 129 = 1000 0001 -> 0100 0000 0000 0001
|
||||
0x4004, // 130 = 1000 0010 -> 0100 0000 0000 0100
|
||||
0x4005, // 131 = 1000 0011 -> 0100 0000 0000 0101
|
||||
0x4010, // 132 = 1000 0100 -> 0100 0000 0001 0000
|
||||
0x4011, // 133 = 1000 0101 -> 0100 0000 0001 0001
|
||||
0x4014, // 134 = 1000 0110 -> 0100 0000 0001 0100
|
||||
0x4015, // 135 = 1000 0111 -> 0100 0000 0001 0101
|
||||
0x4040, // 136 = 1000 1000 -> 0100 0000 0100 0000
|
||||
0x4041, // 137 = 1000 1001 -> 0100 0000 0100 0001
|
||||
0x4044, // 138 = 1000 1010 -> 0100 0000 0100 0100
|
||||
0x4045, // 139 = 1000 1011 -> 0100 0000 0100 0101
|
||||
0x4050, // 140 = 1000 1100 -> 0100 0000 0101 0000
|
||||
0x4051, // 141 = 1000 1101 -> 0100 0000 0101 0001
|
||||
0x4054, // 142 = 1000 1110 -> 0100 0000 0101 0100
|
||||
0x4055, // 143 = 1000 1111 -> 0100 0000 0101 0101
|
||||
|
||||
0x4100, // 144 = 1001 0000 -> 0100 0001 0000 0000
|
||||
0x4101, // 145 = 1001 0001 -> 0100 0001 0000 0001
|
||||
0x4104, // 146 = 1001 0010 -> 0100 0001 0000 0100
|
||||
0x4105, // 147 = 1001 0011 -> 0100 0001 0000 0101
|
||||
0x4110, // 148 = 1001 0100 -> 0100 0001 0001 0000
|
||||
0x4111, // 149 = 1001 0101 -> 0100 0001 0001 0001
|
||||
0x4114, // 150 = 1001 0110 -> 0100 0001 0001 0100
|
||||
0x4115, // 151 = 1001 0111 -> 0100 0001 0001 0101
|
||||
0x4140, // 152 = 1001 1000 -> 0100 0001 0100 0000
|
||||
0x4141, // 153 = 1001 1001 -> 0100 0001 0100 0001
|
||||
0x4144, // 154 = 1001 1010 -> 0100 0001 0100 0100
|
||||
0x4145, // 155 = 1001 1011 -> 0100 0001 0100 0101
|
||||
0x4150, // 156 = 1001 1100 -> 0100 0001 0101 0000
|
||||
0x4151, // 157 = 1001 1101 -> 0100 0001 0101 0001
|
||||
0x4154, // 158 = 1001 1110 -> 0100 0001 0101 0100
|
||||
0x4155, // 159 = 1001 1111 -> 0100 0001 0101 0101
|
||||
|
||||
0x4400, // 160 = 1010 0000 -> 0100 0100 0000 0000
|
||||
0x4401, // 161 = 1010 0001 -> 0100 0100 0000 0001
|
||||
0x4404, // 162 = 1010 0010 -> 0100 0100 0000 0100
|
||||
0x4405, // 163 = 1010 0011 -> 0100 0100 0000 0101
|
||||
0x4410, // 164 = 1010 0100 -> 0100 0100 0001 0000
|
||||
0x4411, // 165 = 1010 0101 -> 0100 0100 0001 0001
|
||||
0x4414, // 166 = 1010 0110 -> 0100 0100 0001 0100
|
||||
0x4415, // 167 = 1010 0111 -> 0100 0100 0001 0101
|
||||
0x4440, // 168 = 1010 1000 -> 0100 0100 0100 0000
|
||||
0x4441, // 169 = 1010 1001 -> 0100 0100 0100 0001
|
||||
0x4444, // 170 = 1010 1010 -> 0100 0100 0100 0100
|
||||
0x4445, // 171 = 1010 1011 -> 0100 0100 0100 0101
|
||||
0x4450, // 172 = 1010 1100 -> 0100 0100 0101 0000
|
||||
0x4451, // 173 = 1010 1101 -> 0100 0100 0101 0001
|
||||
0x4454, // 174 = 1010 1110 -> 0100 0100 0101 0100
|
||||
0x4455, // 175 = 1010 1111 -> 0100 0100 0101 0101
|
||||
|
||||
0x4500, // 176 = 1011 0000 -> 0100 0101 0000 0000
|
||||
0x4501, // 177 = 1011 0001 -> 0100 0101 0000 0001
|
||||
0x4504, // 178 = 1011 0010 -> 0100 0101 0000 0100
|
||||
0x4505, // 179 = 1011 0011 -> 0100 0101 0000 0101
|
||||
0x4510, // 180 = 1011 0100 -> 0100 0101 0001 0000
|
||||
0x4511, // 181 = 1011 0101 -> 0100 0101 0001 0001
|
||||
0x4514, // 182 = 1011 0110 -> 0100 0101 0001 0100
|
||||
0x4515, // 183 = 1011 0111 -> 0100 0101 0001 0101
|
||||
0x4540, // 184 = 1011 1000 -> 0100 0101 0100 0000
|
||||
0x4541, // 185 = 1011 1001 -> 0100 0101 0100 0001
|
||||
0x4544, // 186 = 1011 1010 -> 0100 0101 0100 0100
|
||||
0x4545, // 187 = 1011 1011 -> 0100 0101 0100 0101
|
||||
0x4550, // 188 = 1011 1100 -> 0100 0101 0101 0000
|
||||
0x4551, // 189 = 1011 1101 -> 0100 0101 0101 0001
|
||||
0x4554, // 190 = 1011 1110 -> 0100 0101 0101 0100
|
||||
0x4555, // 191 = 1011 1111 -> 0100 0101 0101 0101
|
||||
|
||||
0x5000, // 192 = 1100 0000 -> 0101 0000 0000 0000
|
||||
0x5001, // 193 = 1100 0001 -> 0101 0000 0000 0001
|
||||
0x5004, // 194 = 1100 0010 -> 0101 0000 0000 0100
|
||||
0x5005, // 195 = 1100 0011 -> 0101 0000 0000 0101
|
||||
0x5010, // 196 = 1100 0100 -> 0101 0000 0001 0000
|
||||
0x5011, // 197 = 1100 0101 -> 0101 0000 0001 0001
|
||||
0x5014, // 198 = 1100 0110 -> 0101 0000 0001 0100
|
||||
0x5015, // 199 = 1100 0111 -> 0101 0000 0001 0101
|
||||
0x5040, // 200 = 1100 1000 -> 0101 0000 0100 0000
|
||||
0x5041, // 201 = 1100 1001 -> 0101 0000 0100 0001
|
||||
0x5044, // 202 = 1100 1010 -> 0101 0000 0100 0100
|
||||
0x5045, // 203 = 1100 1011 -> 0101 0000 0100 0101
|
||||
0x5050, // 204 = 1100 1100 -> 0101 0000 0101 0000
|
||||
0x5051, // 205 = 1100 1101 -> 0101 0000 0101 0001
|
||||
0x5054, // 206 = 1100 1110 -> 0101 0000 0101 0100
|
||||
0x5055, // 207 = 1100 1111 -> 0101 0000 0101 0101
|
||||
|
||||
0x5100, // 208 = 1101 0000 -> 0101 0001 0000 0000
|
||||
0x5101, // 209 = 1101 0001 -> 0101 0001 0000 0001
|
||||
0x5104, // 210 = 1101 0010 -> 0101 0001 0000 0100
|
||||
0x5105, // 211 = 1101 0011 -> 0101 0001 0000 0101
|
||||
0x5110, // 212 = 1101 0100 -> 0101 0001 0001 0000
|
||||
0x5111, // 213 = 1101 0101 -> 0101 0001 0001 0001
|
||||
0x5114, // 214 = 1101 0110 -> 0101 0001 0001 0100
|
||||
0x5115, // 215 = 1101 0111 -> 0101 0001 0001 0101
|
||||
0x5140, // 216 = 1101 1000 -> 0101 0001 0100 0000
|
||||
0x5141, // 217 = 1101 1001 -> 0101 0001 0100 0001
|
||||
0x5144, // 218 = 1101 1010 -> 0101 0001 0100 0100
|
||||
0x5145, // 219 = 1101 1011 -> 0101 0001 0100 0101
|
||||
0x5150, // 220 = 1101 1100 -> 0101 0001 0101 0000
|
||||
0x5151, // 221 = 1101 1101 -> 0101 0001 0101 0001
|
||||
0x5154, // 222 = 1101 1110 -> 0101 0001 0101 0100
|
||||
0x5155, // 223 = 1101 1111 -> 0101 0001 0101 0101
|
||||
|
||||
0x5400, // 224 = 1110 0000 -> 0101 0100 0000 0000
|
||||
0x5401, // 225 = 1110 0001 -> 0101 0100 0000 0001
|
||||
0x5404, // 226 = 1110 0010 -> 0101 0100 0000 0100
|
||||
0x5405, // 227 = 1110 0011 -> 0101 0100 0000 0101
|
||||
0x5410, // 228 = 1110 0100 -> 0101 0100 0001 0000
|
||||
0x5411, // 229 = 1110 0101 -> 0101 0100 0001 0001
|
||||
0x5414, // 230 = 1110 0110 -> 0101 0100 0001 0100
|
||||
0x5415, // 231 = 1110 0111 -> 0101 0100 0001 0101
|
||||
0x5440, // 232 = 1110 1000 -> 0101 0100 0100 0000
|
||||
0x5441, // 233 = 1110 1001 -> 0101 0100 0100 0001
|
||||
0x5444, // 234 = 1110 1010 -> 0101 0100 0100 0100
|
||||
0x5445, // 235 = 1110 1011 -> 0101 0100 0100 0101
|
||||
0x5450, // 236 = 1110 1100 -> 0101 0100 0101 0000
|
||||
0x5451, // 237 = 1110 1101 -> 0101 0100 0101 0001
|
||||
0x5454, // 238 = 1110 1110 -> 0101 0100 0101 0100
|
||||
0x5455, // 239 = 1110 1111 -> 0101 0100 0101 0101
|
||||
|
||||
0x5500, // 240 = 1111 0000 -> 0101 0101 0000 0000
|
||||
0x5501, // 241 = 1111 0001 -> 0101 0101 0000 0001
|
||||
0x5504, // 242 = 1111 0010 -> 0101 0101 0000 0100
|
||||
0x5505, // 243 = 1111 0011 -> 0101 0101 0000 0101
|
||||
0x5510, // 244 = 1111 0100 -> 0101 0101 0001 0000
|
||||
0x5511, // 245 = 1111 0101 -> 0101 0101 0001 0001
|
||||
0x5514, // 246 = 1111 0110 -> 0101 0101 0001 0100
|
||||
0x5515, // 247 = 1111 0111 -> 0101 0101 0001 0101
|
||||
0x5540, // 248 = 1111 1000 -> 0101 0101 0100 0000
|
||||
0x5541, // 249 = 1111 1001 -> 0101 0101 0100 0001
|
||||
0x5544, // 250 = 1111 1010 -> 0101 0101 0100 0100
|
||||
0x5545, // 251 = 1111 1011 -> 0101 0101 0100 0101
|
||||
0x5550, // 252 = 1111 1100 -> 0101 0101 0101 0000
|
||||
0x5551, // 253 = 1111 1101 -> 0101 0101 0101 0001
|
||||
0x5554, // 254 = 1111 1110 -> 0101 0101 0101 0100
|
||||
0x5555 // 255 = 1111 1111 -> 0101 0101 0101 0101
|
||||
|
||||
]
|
||||
62
frontend/delta/js/Clipperz/Crypto/ECC/BinaryField/Point.js
Normal file
62
frontend/delta/js/Clipperz/Crypto/ECC/BinaryField/Point.js
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
//try { if (typeof(Clipperz.ByteArray) == 'undefined') { throw ""; }} catch (e) {
|
||||
// throw "Clipperz.Crypto.ECC depends on Clipperz.ByteArray!";
|
||||
//}
|
||||
if (typeof(Clipperz.Crypto.ECC) == 'undefined') { Clipperz.Crypto.ECC = {}; }
|
||||
if (typeof(Clipperz.Crypto.ECC.BinaryField) == 'undefined') { Clipperz.Crypto.ECC.BinaryField = {}; }
|
||||
|
||||
Clipperz.Crypto.ECC.BinaryField.Point = function(args) {
|
||||
args = args || {};
|
||||
this._x = args.x;
|
||||
this._y = args.y;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
Clipperz.Crypto.ECC.BinaryField.Point.prototype = MochiKit.Base.update(null, {
|
||||
|
||||
'asString': function() {
|
||||
return "Clipperz.Crypto.ECC.BinaryField.Point (" + this.x() + ", " + this.y() + ")";
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'x': function() {
|
||||
return this._x;
|
||||
},
|
||||
|
||||
'y': function() {
|
||||
return this._y;
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'isZero': function() {
|
||||
return (this.x().isZero() && this.y().isZero())
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
__syntaxFix__: "syntax fix"
|
||||
});
|
||||
379
frontend/delta/js/Clipperz/Crypto/ECC/BinaryField/Value.js
Normal file
379
frontend/delta/js/Clipperz/Crypto/ECC/BinaryField/Value.js
Normal file
@@ -0,0 +1,379 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
//try { if (typeof(Clipperz.ByteArray) == 'undefined') { throw ""; }} catch (e) {
|
||||
// throw "Clipperz.Crypto.ECC depends on Clipperz.ByteArray!";
|
||||
//}
|
||||
if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
|
||||
if (typeof(Clipperz.Crypto) == 'undefined') { Clipperz.Crypto = {}; }
|
||||
if (typeof(Clipperz.Crypto.ECC) == 'undefined') { Clipperz.Crypto.ECC = {}; }
|
||||
if (typeof(Clipperz.Crypto.ECC.BinaryField) == 'undefined') { Clipperz.Crypto.ECC.BinaryField = {}; }
|
||||
|
||||
Clipperz.Crypto.ECC.BinaryField.Value = function(aValue, aBase, aBitSize) {
|
||||
if (aValue.constructor == String) {
|
||||
var value;
|
||||
var stringLength;
|
||||
var numberOfWords;
|
||||
var i,c;
|
||||
|
||||
if (aBase != 16) {
|
||||
throw Clipperz.Crypto.ECC.BinaryField.Value.exception.UnsupportedBase;
|
||||
}
|
||||
|
||||
value = aValue.replace(/ /g, '');
|
||||
stringLength = value.length;
|
||||
numberOfWords = Math.ceil(stringLength / 8);
|
||||
this._value = new Array(numberOfWords);
|
||||
|
||||
c = numberOfWords;
|
||||
for (i=0; i<c; i++) {
|
||||
var word;
|
||||
|
||||
if (i < (c-1)) {
|
||||
word = parseInt(value.substr(stringLength-((i+1)*8), 8), 16);
|
||||
} else {
|
||||
word = parseInt(value.substr(0, stringLength-(i*8)), 16);
|
||||
}
|
||||
|
||||
this._value[i] = word;
|
||||
}
|
||||
} else if (aValue.constructor == Array) {
|
||||
var itemsToCopy;
|
||||
|
||||
itemsToCopy = aValue.length;
|
||||
while (aValue[itemsToCopy - 1] == 0) {
|
||||
itemsToCopy --;
|
||||
}
|
||||
|
||||
this._value = aValue.slice(0, itemsToCopy);
|
||||
} else if (aValue.constructor == Number) {
|
||||
this._value = [aValue];
|
||||
} else {
|
||||
// throw Clipperz.Crypto.ECC.BinaryField.Value.exception.UnsupportedConstructorValueType;
|
||||
}
|
||||
|
||||
this._bitSize == aBitSize || null;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
Clipperz.Crypto.ECC.BinaryField.Value.prototype = MochiKit.Base.update(null, {
|
||||
|
||||
'value': function() {
|
||||
return this._value;
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'wordSize': function() {
|
||||
return this._value.length
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'clone': function() {
|
||||
return new Clipperz.Crypto.ECC.BinaryField.Value(this._value.slice(0), null, this._bitSize);
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'isZero': function() {
|
||||
return (this.compare(Clipperz.Crypto.ECC.BinaryField.Value.O) == 0);
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'asString': function(aBase) {
|
||||
var result;
|
||||
var i,c;
|
||||
|
||||
if (aBase != 16) {
|
||||
throw Clipperz.Crypto.ECC.BinaryField.Value.exception.UnsupportedBase;
|
||||
}
|
||||
|
||||
result = "";
|
||||
c = this.wordSize();
|
||||
for (i=0; i<c; i++) {
|
||||
var wordAsString;
|
||||
|
||||
// wordAsString = ("00000000" + this.value()[i].toString(16));
|
||||
wordAsString = ("00000000" + this._value[i].toString(16));
|
||||
wordAsString = wordAsString.substring(wordAsString.length - 8);
|
||||
result = wordAsString + result;
|
||||
}
|
||||
|
||||
result = result.replace(/^(00)*/, "");
|
||||
|
||||
if (result == "") {
|
||||
result = "0";
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'shiftLeft': function(aNumberOfBitsToShift) {
|
||||
// this method seems like it is never called. :-(
|
||||
return new Clipperz.Crypto.ECC.BinaryField.Value(Clipperz.Crypto.ECC.BinaryField.Value._shiftLeft(this._value, aNumberOfBitsToShift));
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'bitSize': function() {
|
||||
if (this._bitSize == null) {
|
||||
this._bitSize = Clipperz.Crypto.ECC.BinaryField.Value._bitSize(this._value);
|
||||
}
|
||||
|
||||
return this._bitSize;
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'isBitSet': function(aBitPosition) {
|
||||
return Clipperz.Crypto.ECC.BinaryField.Value._isBitSet(this._value, aBitPosition);
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'xor': function(aValue) {
|
||||
return new Clipperz.Crypto.ECC.BinaryField.Value(Clipperz.Crypto.ECC.BinaryField.Value._xor(this._value, aValue._value));
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'compare': function(aValue) {
|
||||
return Clipperz.Crypto.ECC.BinaryField.Value._compare(this._value, aValue._value);
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
__syntaxFix__: "syntax fix"
|
||||
});
|
||||
|
||||
Clipperz.Crypto.ECC.BinaryField.Value.O = new Clipperz.Crypto.ECC.BinaryField.Value('0', 16);
|
||||
Clipperz.Crypto.ECC.BinaryField.Value.I = new Clipperz.Crypto.ECC.BinaryField.Value('1', 16);
|
||||
|
||||
Clipperz.Crypto.ECC.BinaryField.Value._xor = function(a, b, aFirstItemOffset) {
|
||||
var result;
|
||||
var resultSize;
|
||||
var i,c;
|
||||
var firstItemOffset;
|
||||
|
||||
firstItemOffset = aFirstItemOffset || 0;
|
||||
resultSize = Math.max((a.length - firstItemOffset), b.length) + firstItemOffset;
|
||||
|
||||
result = new Array(resultSize);
|
||||
|
||||
c = firstItemOffset;
|
||||
for (i=0; i<c; i++) {
|
||||
result[i] = a[i];
|
||||
}
|
||||
|
||||
c = resultSize;
|
||||
for (i=firstItemOffset; i<c; i++) {
|
||||
result[i] = (((a[i] || 0) ^ (b[i - firstItemOffset] || 0)) >>> 0);
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
Clipperz.Crypto.ECC.BinaryField.Value._overwriteXor = function(a, b, aFirstItemOffset) {
|
||||
var i,c;
|
||||
var firstItemOffset;
|
||||
|
||||
firstItemOffset = aFirstItemOffset || 0;
|
||||
|
||||
c = Math.max((a.length - firstItemOffset), b.length) + firstItemOffset;
|
||||
for (i=firstItemOffset; i<c; i++) {
|
||||
a[i] = (((a[i] || 0) ^ (b[i - firstItemOffset] || 0)) >>> 0);
|
||||
}
|
||||
};
|
||||
|
||||
Clipperz.Crypto.ECC.BinaryField.Value._shiftLeft = function(aWordArray, aNumberOfBitsToShift) {
|
||||
var numberOfWordsToShift;
|
||||
var numberOfBitsToShift;
|
||||
var result;
|
||||
var overflowValue;
|
||||
var nextOverflowValue;
|
||||
var i,c;
|
||||
|
||||
numberOfWordsToShift = Math.floor(aNumberOfBitsToShift / 32);
|
||||
numberOfBitsToShift = aNumberOfBitsToShift % 32;
|
||||
|
||||
result = new Array(aWordArray.length + numberOfWordsToShift);
|
||||
|
||||
c = numberOfWordsToShift;
|
||||
for (i=0; i<c; i++) {
|
||||
result[i] = 0;
|
||||
}
|
||||
|
||||
overflowValue = 0;
|
||||
nextOverflowValue = 0;
|
||||
|
||||
c = aWordArray.length;
|
||||
for (i=0; i<c; i++) {
|
||||
var value;
|
||||
var resultWord;
|
||||
|
||||
// value = this.value()[i];
|
||||
value = aWordArray[i];
|
||||
|
||||
if (numberOfBitsToShift > 0) {
|
||||
nextOverflowValue = (value >>> (32 - numberOfBitsToShift));
|
||||
value = value & (0xffffffff >>> numberOfBitsToShift);
|
||||
resultWord = (((value << numberOfBitsToShift) | overflowValue) >>> 0);
|
||||
} else {
|
||||
resultWord = value;
|
||||
}
|
||||
|
||||
result[i+numberOfWordsToShift] = resultWord;
|
||||
overflowValue = nextOverflowValue;
|
||||
}
|
||||
|
||||
if (overflowValue != 0) {
|
||||
result[aWordArray.length + numberOfWordsToShift] = overflowValue;
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
Clipperz.Crypto.ECC.BinaryField.Value._overwriteShiftLeft = function(aWordArray, aNumberOfBitsToShift) {
|
||||
var numberOfWordsToShift;
|
||||
var numberOfBitsToShift;
|
||||
var result;
|
||||
var overflowValue;
|
||||
var i,c;
|
||||
|
||||
numberOfWordsToShift = Math.floor(aNumberOfBitsToShift / 32);
|
||||
numberOfBitsToShift = aNumberOfBitsToShift % 32;
|
||||
|
||||
result = new Array(aWordArray.length + numberOfWordsToShift);
|
||||
|
||||
c = numberOfWordsToShift;
|
||||
for (i=0; i<c; i++) {
|
||||
result[i] = 0;
|
||||
}
|
||||
|
||||
overflowValue = 0;
|
||||
nextOverflowValue = 0;
|
||||
|
||||
c = aWordArray.length;
|
||||
for (i=0; i<c; i++) {
|
||||
var value;
|
||||
var resultWord;
|
||||
|
||||
// value = this.value()[i];
|
||||
value = aWordArray[i];
|
||||
|
||||
if (numberOfBitsToShift > 0) {
|
||||
var nextOverflowValue;
|
||||
|
||||
nextOverflowValue = (value >>> (32 - numberOfBitsToShift));
|
||||
value = value & (0xffffffff >>> numberOfBitsToShift);
|
||||
resultWord = (((value << numberOfBitsToShift) | overflowValue) >>> 0);
|
||||
} else {
|
||||
resultWord = value;
|
||||
}
|
||||
|
||||
result[i+numberOfWordsToShift] = resultWord;
|
||||
overflowValue = nextOverflowValue;
|
||||
}
|
||||
|
||||
if (overflowValue != 0) {
|
||||
result[aWordArray.length + numberOfWordsToShift] = overflowValue;
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
Clipperz.Crypto.ECC.BinaryField.Value._bitSize = function(aWordArray) {
|
||||
var result;
|
||||
var notNullElements;
|
||||
var mostValuableWord;
|
||||
var matchingBitsInMostImportantWord;
|
||||
var mask;
|
||||
var i,c;
|
||||
|
||||
notNullElements = aWordArray.length;
|
||||
|
||||
if ((aWordArray.length == 1) && (aWordArray[0] == 0)) {
|
||||
result = 0;
|
||||
} else {
|
||||
notNullElements --;
|
||||
while((notNullElements > 0) && (aWordArray[notNullElements] == 0)) {
|
||||
notNullElements --;
|
||||
}
|
||||
|
||||
result = notNullElements * 32;
|
||||
mostValuableWord = aWordArray[notNullElements];
|
||||
|
||||
matchingBits = 32;
|
||||
mask = 0x80000000;
|
||||
|
||||
while ((matchingBits > 0) && ((mostValuableWord & mask) == 0)) {
|
||||
matchingBits --;
|
||||
mask >>>= 1;
|
||||
}
|
||||
|
||||
result += matchingBits;
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
Clipperz.Crypto.ECC.BinaryField.Value._isBitSet = function(aWordArray, aBitPosition) {
|
||||
var result;
|
||||
var byteIndex;
|
||||
var bitIndexInSelectedByte;
|
||||
|
||||
byteIndex = Math.floor(aBitPosition / 32);
|
||||
bitIndexInSelectedByte = aBitPosition % 32;
|
||||
|
||||
if (byteIndex <= aWordArray.length) {
|
||||
result = ((aWordArray[byteIndex] & (1 << bitIndexInSelectedByte)) != 0);
|
||||
} else {
|
||||
result = false;
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
Clipperz.Crypto.ECC.BinaryField.Value._compare = function(a,b) {
|
||||
var result;
|
||||
var i,c;
|
||||
|
||||
result = MochiKit.Base.compare(a.length, b.length);
|
||||
|
||||
c = a.length;
|
||||
for (i=0; (i<c) && (result==0); i++) {
|
||||
result = MochiKit.Base.compare(a[c-i-1], b[c-i-1]);
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
|
||||
Clipperz.Crypto.ECC.BinaryField.Value['exception']= {
|
||||
'UnsupportedBase': new MochiKit.Base.NamedError("Clipperz.Crypto.ECC.BinaryField.Value.exception.UnsupportedBase"),
|
||||
'UnsupportedConstructorValueType': new MochiKit.Base.NamedError("Clipperz.Crypto.ECC.BinaryField.Value.exception.UnsupportedConstructorValueType")
|
||||
};
|
||||
229
frontend/delta/js/Clipperz/Crypto/ECC/StandardCurves.js
Normal file
229
frontend/delta/js/Clipperz/Crypto/ECC/StandardCurves.js
Normal file
@@ -0,0 +1,229 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
//try { if (typeof(Clipperz.Crypto.ECC.BinaryField.Curve) == 'undefined') { throw ""; }} catch (e) {
|
||||
// throw "Clipperz.Crypto.ECC depends on Clipperz.Crypto.ECC.BinaryField.Curve!";
|
||||
//}
|
||||
//try { if (typeof(Clipperz.Crypto.ECC.Koblitz.Curve) == 'undefined') { throw ""; }} catch (e) {
|
||||
// throw "Clipperz.Crypto.ECC depends on Clipperz.Crypto.ECC.Koblitz.Curve!";
|
||||
//}
|
||||
|
||||
Clipperz.Crypto.ECC.StandardCurves = {};
|
||||
|
||||
MochiKit.Base.update(Clipperz.Crypto.ECC.StandardCurves, {
|
||||
|
||||
//==============================================================================
|
||||
|
||||
'_K571': null,
|
||||
'K571': function() { // f(z) = z^571 + z^10 + z^5 + z^2 + 1
|
||||
if ((Clipperz.Crypto.ECC.StandardCurves._K571 == null) && (typeof(Clipperz.Crypto.ECC.Koblitz.Curve) != 'undefined')) {
|
||||
Clipperz.Crypto.ECC.StandardCurves._K571 = new Clipperz.Crypto.ECC.Koblitz.Curve({
|
||||
modulus: new Clipperz.Crypto.ECC.Koblitz.Value('08000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000425', 16),
|
||||
a: new Clipperz.Crypto.ECC.Koblitz.Value('0', 16),
|
||||
b: new Clipperz.Crypto.ECC.Koblitz.Value('1', 16),
|
||||
G: new Clipperz.Crypto.ECC.Koblitz.Point({
|
||||
x: new Clipperz.Crypto.ECC.Koblitz.Value('026eb7a8 59923fbc 82189631 f8103fe4 ac9ca297 0012d5d4 60248048 01841ca4 43709584 93b205e6 47da304d b4ceb08c bbd1ba39 494776fb 988b4717 4dca88c7 e2945283 a01c8972', 16),
|
||||
y: new Clipperz.Crypto.ECC.Koblitz.Value('0349dc80 7f4fbf37 4f4aeade 3bca9531 4dd58cec 9f307a54 ffc61efc 006d8a2c 9d4979c0 ac44aea7 4fbebbb9 f772aedc b620b01a 7ba7af1b 320430c8 591984f6 01cd4c14 3ef1c7a3', 16)
|
||||
}),
|
||||
r: new Clipperz.Crypto.ECC.Koblitz.Value('02000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 131850e1 f19a63e4 b391a8db 917f4138 b630d84b e5d63938 1e91deb4 5cfe778f 637c1001', 16),
|
||||
h: new Clipperz.Crypto.ECC.Koblitz.Value('4', 16),
|
||||
primeFactor: new Clipperz.Crypto.ECC.Koblitz.Value('02000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 131850e1 f19a63e4 b391a8db 917f4138 b630d84b e5d63938 1e91deb4 5cfe778f 637c1001', 16)
|
||||
});
|
||||
}
|
||||
|
||||
return Clipperz.Crypto.ECC.StandardCurves._K571;
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'_K283': null,
|
||||
'K283': function() { // f(z) = z^283 + z^12 + z^7 + z^5 + 1
|
||||
if ((Clipperz.Crypto.ECC.StandardCurves._K283 == null) && (typeof(Clipperz.Crypto.ECC.Koblitz.Curve) != 'undefined')) {
|
||||
Clipperz.Crypto.ECC.StandardCurves._K283 = new Clipperz.Crypto.ECC.Koblitz.Curve({
|
||||
modulus: new Clipperz.Crypto.ECC.Koblitz.Value('08000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 000010a1', 16),
|
||||
a: new Clipperz.Crypto.ECC.Koblitz.Value('0', 16),
|
||||
b: new Clipperz.Crypto.ECC.Koblitz.Value('1', 16),
|
||||
G: new Clipperz.Crypto.ECC.Koblitz.Point({
|
||||
x: new Clipperz.Crypto.ECC.Koblitz.Value('0503213f 78ca4488 3f1a3b81 62f188e5 53cd265f 23c1567a 16876913 b0c2ac24 58492836', 16),
|
||||
y: new Clipperz.Crypto.ECC.Koblitz.Value('01ccda38 0f1c9e31 8d90f95d 07e5426f e87e45c0 e8184698 e4596236 4e341161 77dd2259', 16)
|
||||
}),
|
||||
r: new Clipperz.Crypto.ECC.Koblitz.Value('01ffffff ffffffff ffffffff ffffffff ffffe9ae 2ed07577 265dff7f 94451e06 1e163c61', 16),
|
||||
h: new Clipperz.Crypto.ECC.Koblitz.Value('4', 16),
|
||||
primeFactor: new Clipperz.Crypto.ECC.Koblitz.Value('01ffffff ffffffff ffffffff ffffffff ffffe9ae 2ed07577 265dff7f 94451e06 1e163c61', 16)
|
||||
});
|
||||
}
|
||||
|
||||
return Clipperz.Crypto.ECC.StandardCurves._K283;
|
||||
},
|
||||
|
||||
//==============================================================================
|
||||
|
||||
'_B571': null,
|
||||
'B571': function() { // f(z) = z^571 + z^10 + z^5 + z^2 + 1
|
||||
if ((Clipperz.Crypto.ECC.StandardCurves._B571 == null) && (typeof(Clipperz.Crypto.ECC.BinaryField.Curve) != 'undefined')) {
|
||||
Clipperz.Crypto.ECC.StandardCurves._B571 = new Clipperz.Crypto.ECC.BinaryField.Curve({
|
||||
modulus: new Clipperz.Crypto.ECC.BinaryField.Value('08000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000425', 16),
|
||||
a: new Clipperz.Crypto.ECC.BinaryField.Value('1', 16),
|
||||
b: new Clipperz.Crypto.ECC.BinaryField.Value('02f40e7e 2221f295 de297117 b7f3d62f 5c6a97ff cb8ceff1 cd6ba8ce 4a9a18ad 84ffabbd 8efa5933 2be7ad67 56a66e29 4afd185a 78ff12aa 520e4de7 39baca0c 7ffeff7f 2955727a', 16),
|
||||
G: new Clipperz.Crypto.ECC.BinaryField.Point({
|
||||
x: new Clipperz.Crypto.ECC.BinaryField.Value('0303001d 34b85629 6c16c0d4 0d3cd775 0a93d1d2 955fa80a a5f40fc8 db7b2abd bde53950 f4c0d293 cdd711a3 5b67fb14 99ae6003 8614f139 4abfa3b4 c850d927 e1e7769c 8eec2d19', 16),
|
||||
y: new Clipperz.Crypto.ECC.BinaryField.Value('037bf273 42da639b 6dccfffe b73d69d7 8c6c27a6 009cbbca 1980f853 3921e8a6 84423e43 bab08a57 6291af8f 461bb2a8 b3531d2f 0485c19b 16e2f151 6e23dd3c 1a4827af 1b8ac15b', 16)
|
||||
}),
|
||||
r: new Clipperz.Crypto.ECC.BinaryField.Value('03ffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff e661ce18 ff559873 08059b18 6823851e c7dd9ca1 161de93d 5174d66e 8382e9bb 2fe84e47', 16),
|
||||
h: new Clipperz.Crypto.ECC.BinaryField.Value('2', 16)
|
||||
|
||||
// S: new Clipperz.Crypto.ECC.BinaryField.Value('2aa058f73a0e33ab486b0f610410c53a7f132310', 10),
|
||||
// n: new Clipperz.Crypto.ECC.BinaryField.Value('03ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe661ce18ff55987308059b186823851ec7dd9ca1161de93d5174d66e8382e9bb2fe84e47', 16)
|
||||
});
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Guide to Elliptic Curve Cryptography
|
||||
// Darrel Hankerson, Alfred Menezes, Scott Vanstone
|
||||
// - Pag: 56, Alorithm 2.45 (with a typo!!!)
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// http://www.milw0rm.com/papers/136
|
||||
//
|
||||
// -------------------------------------------------------------------------
|
||||
// Polynomial Reduction Algorithm Modulo f571
|
||||
// -------------------------------------------------------------------------
|
||||
//
|
||||
// Input: Polynomial p(x) of degree 1140 or less, stored as
|
||||
// an array of 2T machinewords.
|
||||
// Output: p(x) mod f571(x)
|
||||
//
|
||||
// FOR i = T-1, ..., 0 DO
|
||||
// SET X := P[i+T]
|
||||
// P[i] := P[i] ^ (X<<5) ^ (X<<7) ^ (X<<10) ^ (X<<15)
|
||||
// P[i+1] := P[i+1] ^ (X>>17) ^ (X>>22) ^ (X>>25) ^ (X>>27)
|
||||
//
|
||||
// SET X := P[T-1] >> 27
|
||||
// P[0] := P[0] ^ X ^ (X<<2) ^ (X<<5) ^ (X<<10)
|
||||
// P[T-1] := P[T-1] & 0x07ffffff
|
||||
//
|
||||
// RETURN P[T-1],...,P[0]
|
||||
//
|
||||
// -------------------------------------------------------------------------
|
||||
//
|
||||
Clipperz.Crypto.ECC.StandardCurves._B571.finiteField().slowModule = Clipperz.Crypto.ECC.StandardCurves._B571.finiteField().module;
|
||||
Clipperz.Crypto.ECC.StandardCurves._B571.finiteField().module = function(aValue) {
|
||||
var result;
|
||||
|
||||
if (aValue.bitSize() > 1140) {
|
||||
Clipperz.logWarning("ECC.StandarCurves.B571.finiteField().module: falling back to default implementation");
|
||||
result = Clipperz.Crypto.ECC.StandardCurves._B571.finiteField().slowModule(aValue);
|
||||
} else {
|
||||
var C, T;
|
||||
var i;
|
||||
|
||||
C = aValue._value.slice(0);
|
||||
for (i=35; i>=18; i--) {
|
||||
T = C[i];
|
||||
C[i-18] = (((C[i-18] ^ (T<<5) ^ (T<<7) ^ (T<<10) ^ (T<<15)) & 0xffffffff) >>> 0);
|
||||
C[i-17] = ((C[i-17] ^ (T>>>27) ^ (T>>>25) ^ (T>>>22) ^ (T>>>17)) >>> 0);
|
||||
}
|
||||
T = (C[17] >>> 27);
|
||||
C[0] = ((C[0] ^ T ^ ((T<<2) ^ (T<<5) ^ (T<<10)) & 0xffffffff) >>> 0);
|
||||
C[17] = (C[17] & 0x07ffffff);
|
||||
|
||||
for(i=18; i<=35; i++) {
|
||||
C[i] = 0;
|
||||
}
|
||||
|
||||
result = new Clipperz.Crypto.ECC.BinaryField.Value(C);
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
}
|
||||
|
||||
return Clipperz.Crypto.ECC.StandardCurves._B571;
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'_B283': null,
|
||||
'B283': function() { // f(z) = z^283 + z^12 + z^7 + z^5 + 1
|
||||
if ((Clipperz.Crypto.ECC.StandardCurves._B283 == null) && (typeof(Clipperz.Crypto.ECC.BinaryField.Curve) != 'undefined')) {
|
||||
Clipperz.Crypto.ECC.StandardCurves._B283 = new Clipperz.Crypto.ECC.BinaryField.Curve({
|
||||
modulus: new Clipperz.Crypto.ECC.BinaryField.Value('08000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 000010a1', 16),
|
||||
a: new Clipperz.Crypto.ECC.BinaryField.Value('1', 16),
|
||||
b: new Clipperz.Crypto.ECC.BinaryField.Value('027b680a c8b8596d a5a4af8a 19a0303f ca97fd76 45309fa2 a581485a f6263e31 3b79a2f5', 16),
|
||||
G: new Clipperz.Crypto.ECC.BinaryField.Point({
|
||||
x: new Clipperz.Crypto.ECC.BinaryField.Value('05f93925 8db7dd90 e1934f8c 70b0dfec 2eed25b8 557eac9c 80e2e198 f8cdbecd 86b12053', 16),
|
||||
y: new Clipperz.Crypto.ECC.BinaryField.Value('03676854 fe24141c b98fe6d4 b20d02b4 516ff702 350eddb0 826779c8 13f0df45 be8112f4', 16)
|
||||
}),
|
||||
r: new Clipperz.Crypto.ECC.BinaryField.Value('03ffffff ffffffff ffffffff ffffffff ffffef90 399660fc 938a9016 5b042a7c efadb307', 16),
|
||||
h: new Clipperz.Crypto.ECC.BinaryField.Value('2', 16)
|
||||
});
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Guide to Elliptic Curve Cryptography
|
||||
// Darrel Hankerson, Alfred Menezes, Scott Vanstone
|
||||
// - Pag: 56, Alorithm 2.43
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
Clipperz.Crypto.ECC.StandardCurves._B283.finiteField().slowModule = Clipperz.Crypto.ECC.StandardCurves._B283.finiteField().module;
|
||||
Clipperz.Crypto.ECC.StandardCurves._B283.finiteField().module = function(aValue) {
|
||||
var result;
|
||||
|
||||
if (aValue.bitSize() > 564) {
|
||||
Clipperz.logWarning("ECC.StandarCurves.B283.finiteField().module: falling back to default implementation");
|
||||
result = Clipperz.Crypto.ECC.StandardCurves._B283.finiteField().slowModule(aValue);
|
||||
} else {
|
||||
var C, T;
|
||||
var i;
|
||||
|
||||
C = aValue._value.slice(0);
|
||||
for (i=17; i>=9; i--) {
|
||||
T = C[i];
|
||||
C[i-9] = (((C[i-9] ^ (T<<5) ^ (T<<10) ^ (T<<12) ^ (T<<17)) & 0xffffffff) >>> 0);
|
||||
C[i-8] = ((C[i-8] ^ (T>>>27) ^ (T>>>22) ^ (T>>>20) ^ (T>>>15)) >>> 0);
|
||||
}
|
||||
T = (C[8] >>> 27);
|
||||
C[0] = ((C[0] ^ T ^ ((T<<5) ^ (T<<7) ^ (T<<12)) & 0xffffffff) >>> 0);
|
||||
C[8] = (C[8] & 0x07ffffff);
|
||||
|
||||
for(i=9; i<=17; i++) {
|
||||
C[i] = 0;
|
||||
}
|
||||
|
||||
result = new Clipperz.Crypto.ECC.BinaryField.Value(C);
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
}
|
||||
|
||||
return Clipperz.Crypto.ECC.StandardCurves._B283;
|
||||
},
|
||||
|
||||
//==============================================================================
|
||||
__syntaxFix__: "syntax fix"
|
||||
});
|
||||
|
||||
|
||||
|
||||
841
frontend/delta/js/Clipperz/Crypto/PRNG.js
Normal file
841
frontend/delta/js/Clipperz/Crypto/PRNG.js
Normal file
@@ -0,0 +1,841 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
try { if (typeof(Clipperz.ByteArray) == 'undefined') { throw ""; }} catch (e) {
|
||||
throw "Clipperz.Crypto.PRNG depends on Clipperz.ByteArray!";
|
||||
}
|
||||
|
||||
try { if (typeof(Clipperz.Crypto.SHA) == 'undefined') { throw ""; }} catch (e) {
|
||||
throw "Clipperz.Crypto.PRNG depends on Clipperz.Crypto.SHA!";
|
||||
}
|
||||
|
||||
try { if (typeof(Clipperz.Crypto.AES) == 'undefined') { throw ""; }} catch (e) {
|
||||
throw "Clipperz.Crypto.PRNG depends on Clipperz.Crypto.AES!";
|
||||
}
|
||||
|
||||
if (typeof(Clipperz.Crypto.PRNG) == 'undefined') { Clipperz.Crypto.PRNG = {}; }
|
||||
|
||||
//#############################################################################
|
||||
|
||||
Clipperz.Crypto.PRNG.EntropyAccumulator = function(args) {
|
||||
args = args || {};
|
||||
// MochiKit.Base.bindMethods(this);
|
||||
|
||||
this._stack = new Clipperz.ByteArray();
|
||||
this._maxStackLengthBeforeHashing = args.maxStackLengthBeforeHashing || 256;
|
||||
return this;
|
||||
}
|
||||
|
||||
Clipperz.Crypto.PRNG.EntropyAccumulator.prototype = MochiKit.Base.update(null, {
|
||||
|
||||
'toString': function() {
|
||||
return "Clipperz.Crypto.PRNG.EntropyAccumulator";
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'stack': function() {
|
||||
return this._stack;
|
||||
},
|
||||
|
||||
'setStack': function(aValue) {
|
||||
this._stack = aValue;
|
||||
},
|
||||
|
||||
'resetStack': function() {
|
||||
this.stack().reset();
|
||||
},
|
||||
|
||||
'maxStackLengthBeforeHashing': function() {
|
||||
return this._maxStackLengthBeforeHashing;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'addRandomByte': function(aValue) {
|
||||
this.stack().appendByte(aValue);
|
||||
|
||||
if (this.stack().length() > this.maxStackLengthBeforeHashing()) {
|
||||
this.setStack(Clipperz.Crypto.SHA.sha_d256(this.stack()));
|
||||
}
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
__syntaxFix__: "syntax fix"
|
||||
});
|
||||
|
||||
//#############################################################################
|
||||
|
||||
Clipperz.Crypto.PRNG.RandomnessSource = function(args) {
|
||||
args = args || {};
|
||||
MochiKit.Base.bindMethods(this);
|
||||
|
||||
this._generator = args.generator || null;
|
||||
this._sourceId = args.sourceId || null;
|
||||
this._boostMode = args.boostMode || false;
|
||||
|
||||
this._nextPoolIndex = 0;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
Clipperz.Crypto.PRNG.RandomnessSource.prototype = MochiKit.Base.update(null, {
|
||||
|
||||
'generator': function() {
|
||||
return this._generator;
|
||||
},
|
||||
|
||||
'setGenerator': function(aValue) {
|
||||
this._generator = aValue;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'boostMode': function() {
|
||||
return this._boostMode;
|
||||
},
|
||||
|
||||
'setBoostMode': function(aValue) {
|
||||
this._boostMode = aValue;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'sourceId': function() {
|
||||
return this._sourceId;
|
||||
},
|
||||
|
||||
'setSourceId': function(aValue) {
|
||||
this._sourceId = aValue;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'nextPoolIndex': function() {
|
||||
return this._nextPoolIndex;
|
||||
},
|
||||
|
||||
'incrementNextPoolIndex': function() {
|
||||
this._nextPoolIndex = ((this._nextPoolIndex + 1) % this.generator().numberOfEntropyAccumulators());
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'updateGeneratorWithValue': function(aRandomValue) {
|
||||
if (this.generator() != null) {
|
||||
this.generator().addRandomByte(this.sourceId(), this.nextPoolIndex(), aRandomValue);
|
||||
this.incrementNextPoolIndex();
|
||||
}
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
__syntaxFix__: "syntax fix"
|
||||
});
|
||||
|
||||
//#############################################################################
|
||||
|
||||
Clipperz.Crypto.PRNG.TimeRandomnessSource = function(args) {
|
||||
args = args || {};
|
||||
// MochiKit.Base.bindMethods(this);
|
||||
|
||||
this._intervalTime = args.intervalTime || 1000;
|
||||
|
||||
Clipperz.Crypto.PRNG.RandomnessSource.call(this, args);
|
||||
|
||||
this.collectEntropy();
|
||||
return this;
|
||||
}
|
||||
|
||||
Clipperz.Crypto.PRNG.TimeRandomnessSource.prototype = MochiKit.Base.update(new Clipperz.Crypto.PRNG.RandomnessSource, {
|
||||
|
||||
'intervalTime': function() {
|
||||
return this._intervalTime;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'collectEntropy': function() {
|
||||
var now;
|
||||
var entropyByte;
|
||||
var intervalTime;
|
||||
now = new Date();
|
||||
entropyByte = (now.getTime() & 0xff);
|
||||
|
||||
intervalTime = this.intervalTime();
|
||||
if (this.boostMode() == true) {
|
||||
intervalTime = intervalTime / 9;
|
||||
}
|
||||
|
||||
this.updateGeneratorWithValue(entropyByte);
|
||||
setTimeout(this.collectEntropy, intervalTime);
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'numberOfRandomBits': function() {
|
||||
return 5;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'pollingFrequency': function() {
|
||||
return 10;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
__syntaxFix__: "syntax fix"
|
||||
});
|
||||
|
||||
//*****************************************************************************
|
||||
|
||||
Clipperz.Crypto.PRNG.MouseRandomnessSource = function(args) {
|
||||
args = args || {};
|
||||
|
||||
Clipperz.Crypto.PRNG.RandomnessSource.call(this, args);
|
||||
|
||||
this._numberOfBitsToCollectAtEachEvent = 4;
|
||||
this._randomBitsCollector = 0;
|
||||
this._numberOfRandomBitsCollected = 0;
|
||||
|
||||
MochiKit.Signal.connect(document, 'onmousemove', this, 'collectEntropy');
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
Clipperz.Crypto.PRNG.MouseRandomnessSource.prototype = MochiKit.Base.update(new Clipperz.Crypto.PRNG.RandomnessSource, {
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'numberOfBitsToCollectAtEachEvent': function() {
|
||||
return this._numberOfBitsToCollectAtEachEvent;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'randomBitsCollector': function() {
|
||||
return this._randomBitsCollector;
|
||||
},
|
||||
|
||||
'setRandomBitsCollector': function(aValue) {
|
||||
this._randomBitsCollector = aValue;
|
||||
},
|
||||
|
||||
'appendRandomBitsToRandomBitsCollector': function(aValue) {
|
||||
var collectedBits;
|
||||
var numberOfRandomBitsCollected;
|
||||
|
||||
numberOfRandomBitsCollected = this.numberOfRandomBitsCollected();
|
||||
collectetBits = this.randomBitsCollector() | (aValue << numberOfRandomBitsCollected);
|
||||
this.setRandomBitsCollector(collectetBits);
|
||||
numberOfRandomBitsCollected += this.numberOfBitsToCollectAtEachEvent();
|
||||
|
||||
if (numberOfRandomBitsCollected == 8) {
|
||||
this.updateGeneratorWithValue(collectetBits);
|
||||
numberOfRandomBitsCollected = 0;
|
||||
this.setRandomBitsCollector(0);
|
||||
}
|
||||
|
||||
this.setNumberOfRandomBitsCollected(numberOfRandomBitsCollected)
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'numberOfRandomBitsCollected': function() {
|
||||
return this._numberOfRandomBitsCollected;
|
||||
},
|
||||
|
||||
'setNumberOfRandomBitsCollected': function(aValue) {
|
||||
this._numberOfRandomBitsCollected = aValue;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'collectEntropy': function(anEvent) {
|
||||
var mouseLocation;
|
||||
var randomBit;
|
||||
var mask;
|
||||
|
||||
mask = 0xffffffff >>> (32 - this.numberOfBitsToCollectAtEachEvent());
|
||||
|
||||
mouseLocation = anEvent.mouse().client;
|
||||
randomBit = ((mouseLocation.x ^ mouseLocation.y) & mask);
|
||||
this.appendRandomBitsToRandomBitsCollector(randomBit)
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'numberOfRandomBits': function() {
|
||||
return 1;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'pollingFrequency': function() {
|
||||
return 10;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
__syntaxFix__: "syntax fix"
|
||||
});
|
||||
|
||||
//*****************************************************************************
|
||||
|
||||
Clipperz.Crypto.PRNG.KeyboardRandomnessSource = function(args) {
|
||||
args = args || {};
|
||||
Clipperz.Crypto.PRNG.RandomnessSource.call(this, args);
|
||||
|
||||
this._randomBitsCollector = 0;
|
||||
this._numberOfRandomBitsCollected = 0;
|
||||
|
||||
MochiKit.Signal.connect(document, 'onkeypress', this, 'collectEntropy');
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
Clipperz.Crypto.PRNG.KeyboardRandomnessSource.prototype = MochiKit.Base.update(new Clipperz.Crypto.PRNG.RandomnessSource, {
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'randomBitsCollector': function() {
|
||||
return this._randomBitsCollector;
|
||||
},
|
||||
|
||||
'setRandomBitsCollector': function(aValue) {
|
||||
this._randomBitsCollector = aValue;
|
||||
},
|
||||
|
||||
'appendRandomBitToRandomBitsCollector': function(aValue) {
|
||||
var collectedBits;
|
||||
var numberOfRandomBitsCollected;
|
||||
|
||||
numberOfRandomBitsCollected = this.numberOfRandomBitsCollected();
|
||||
collectetBits = this.randomBitsCollector() | (aValue << numberOfRandomBitsCollected);
|
||||
this.setRandomBitsCollector(collectetBits);
|
||||
numberOfRandomBitsCollected ++;
|
||||
|
||||
if (numberOfRandomBitsCollected == 8) {
|
||||
this.updateGeneratorWithValue(collectetBits);
|
||||
numberOfRandomBitsCollected = 0;
|
||||
this.setRandomBitsCollector(0);
|
||||
}
|
||||
|
||||
this.setNumberOfRandomBitsCollected(numberOfRandomBitsCollected)
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'numberOfRandomBitsCollected': function() {
|
||||
return this._numberOfRandomBitsCollected;
|
||||
},
|
||||
|
||||
'setNumberOfRandomBitsCollected': function(aValue) {
|
||||
this._numberOfRandomBitsCollected = aValue;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'collectEntropy': function(anEvent) {
|
||||
/*
|
||||
var mouseLocation;
|
||||
var randomBit;
|
||||
|
||||
mouseLocation = anEvent.mouse().client;
|
||||
|
||||
randomBit = ((mouseLocation.x ^ mouseLocation.y) & 0x1);
|
||||
this.appendRandomBitToRandomBitsCollector(randomBit);
|
||||
*/
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'numberOfRandomBits': function() {
|
||||
return 1;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'pollingFrequency': function() {
|
||||
return 10;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
__syntaxFix__: "syntax fix"
|
||||
});
|
||||
|
||||
//#############################################################################
|
||||
|
||||
Clipperz.Crypto.PRNG.Fortuna = function(args) {
|
||||
var i,c;
|
||||
|
||||
args = args || {};
|
||||
|
||||
this._key = args.seed || null;
|
||||
if (this._key == null) {
|
||||
this._counter = 0;
|
||||
this._key = new Clipperz.ByteArray();
|
||||
} else {
|
||||
this._counter = 1;
|
||||
}
|
||||
|
||||
this._aesKey = null;
|
||||
|
||||
this._firstPoolReseedLevel = args.firstPoolReseedLevel || 32 || 64;
|
||||
this._numberOfEntropyAccumulators = args.numberOfEntropyAccumulators || 32;
|
||||
|
||||
this._accumulators = [];
|
||||
c = this.numberOfEntropyAccumulators();
|
||||
for (i=0; i<c; i++) {
|
||||
this._accumulators.push(new Clipperz.Crypto.PRNG.EntropyAccumulator());
|
||||
}
|
||||
|
||||
this._randomnessSources = [];
|
||||
this._reseedCounter = 0;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
Clipperz.Crypto.PRNG.Fortuna.prototype = MochiKit.Base.update(null, {
|
||||
|
||||
'toString': function() {
|
||||
return "Clipperz.Crypto.PRNG.Fortuna";
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'key': function() {
|
||||
return this._key;
|
||||
},
|
||||
|
||||
'setKey': function(aValue) {
|
||||
this._key = aValue;
|
||||
this._aesKey = null;
|
||||
},
|
||||
|
||||
'aesKey': function() {
|
||||
if (this._aesKey == null) {
|
||||
this._aesKey = new Clipperz.Crypto.AES.Key({key:this.key()});
|
||||
}
|
||||
|
||||
return this._aesKey;
|
||||
},
|
||||
|
||||
'accumulators': function() {
|
||||
return this._accumulators;
|
||||
},
|
||||
|
||||
'firstPoolReseedLevel': function() {
|
||||
return this._firstPoolReseedLevel;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'reseedCounter': function() {
|
||||
return this._reseedCounter;
|
||||
},
|
||||
|
||||
'incrementReseedCounter': function() {
|
||||
this._reseedCounter = this._reseedCounter +1;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'reseed': function() {
|
||||
var newKeySeed;
|
||||
var reseedCounter;
|
||||
var reseedCounterMask;
|
||||
var i, c;
|
||||
|
||||
newKeySeed = this.key();
|
||||
this.incrementReseedCounter();
|
||||
reseedCounter = this.reseedCounter();
|
||||
|
||||
c = this.numberOfEntropyAccumulators();
|
||||
reseedCounterMask = 0xffffffff >>> (32 - c);
|
||||
for (i=0; i<c; i++) {
|
||||
if ((i == 0) || ((reseedCounter & (reseedCounterMask >>> (c - i))) == 0)) {
|
||||
newKeySeed.appendBlock(this.accumulators()[i].stack());
|
||||
this.accumulators()[i].resetStack();
|
||||
}
|
||||
}
|
||||
|
||||
if (reseedCounter == 1) {
|
||||
c = this.randomnessSources().length;
|
||||
for (i=0; i<c; i++) {
|
||||
this.randomnessSources()[i].setBoostMode(false);
|
||||
}
|
||||
}
|
||||
|
||||
this.setKey(Clipperz.Crypto.SHA.sha_d256(newKeySeed));
|
||||
if (reseedCounter == 1) {
|
||||
Clipperz.log("### PRNG.readyToGenerateRandomBytes");
|
||||
MochiKit.Signal.signal(this, 'readyToGenerateRandomBytes');
|
||||
}
|
||||
MochiKit.Signal.signal(this, 'reseeded');
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'isReadyToGenerateRandomValues': function() {
|
||||
return this.reseedCounter() != 0;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'entropyLevel': function() {
|
||||
return this.accumulators()[0].stack().length() + (this.reseedCounter() * this.firstPoolReseedLevel());
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'counter': function() {
|
||||
return this._counter;
|
||||
},
|
||||
|
||||
'incrementCounter': function() {
|
||||
this._counter += 1;
|
||||
},
|
||||
|
||||
'counterBlock': function() {
|
||||
var result;
|
||||
|
||||
result = new Clipperz.ByteArray().appendWords(this.counter(), 0, 0, 0);
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'getRandomBlock': function() {
|
||||
var result;
|
||||
|
||||
result = new Clipperz.ByteArray(Clipperz.Crypto.AES.encryptBlock(this.aesKey(), this.counterBlock().arrayValues()));
|
||||
this.incrementCounter();
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'getRandomBytes': function(aSize) {
|
||||
var result;
|
||||
|
||||
if (this.isReadyToGenerateRandomValues()) {
|
||||
var i,c;
|
||||
var newKey;
|
||||
|
||||
result = new Clipperz.ByteArray();
|
||||
|
||||
c = Math.ceil(aSize / (128 / 8));
|
||||
for (i=0; i<c; i++) {
|
||||
result.appendBlock(this.getRandomBlock());
|
||||
}
|
||||
|
||||
if (result.length() != aSize) {
|
||||
result = result.split(0, aSize);
|
||||
}
|
||||
|
||||
newKey = this.getRandomBlock().appendBlock(this.getRandomBlock());
|
||||
this.setKey(newKey);
|
||||
} else {
|
||||
Clipperz.logWarning("Fortuna generator has not enough entropy, yet!");
|
||||
throw Clipperz.Crypto.PRNG.exception.NotEnoughEntropy;
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'addRandomByte': function(aSourceId, aPoolId, aRandomValue) {
|
||||
var selectedAccumulator;
|
||||
|
||||
selectedAccumulator = this.accumulators()[aPoolId];
|
||||
selectedAccumulator.addRandomByte(aRandomValue);
|
||||
|
||||
if (aPoolId == 0) {
|
||||
MochiKit.Signal.signal(this, 'addedRandomByte')
|
||||
if (selectedAccumulator.stack().length() > this.firstPoolReseedLevel()) {
|
||||
this.reseed();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'numberOfEntropyAccumulators': function() {
|
||||
return this._numberOfEntropyAccumulators;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'randomnessSources': function() {
|
||||
return this._randomnessSources;
|
||||
},
|
||||
|
||||
'addRandomnessSource': function(aRandomnessSource) {
|
||||
aRandomnessSource.setGenerator(this);
|
||||
aRandomnessSource.setSourceId(this.randomnessSources().length);
|
||||
this.randomnessSources().push(aRandomnessSource);
|
||||
|
||||
if (this.isReadyToGenerateRandomValues() == false) {
|
||||
aRandomnessSource.setBoostMode(true);
|
||||
}
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'deferredEntropyCollection': function(aValue) {
|
||||
var result;
|
||||
|
||||
|
||||
if (this.isReadyToGenerateRandomValues()) {
|
||||
result = aValue;
|
||||
} else {
|
||||
var deferredResult;
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("PRNG.deferredEntropyCollection");
|
||||
deferredResult.addCallback(MochiKit.Base.partial(MochiKit.Async.succeed, aValue));
|
||||
MochiKit.Signal.connect(this,
|
||||
'readyToGenerateRandomBytes',
|
||||
deferredResult,
|
||||
'callback');
|
||||
|
||||
result = deferredResult;
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'fastEntropyAccumulationForTestingPurpose': function() {
|
||||
while (! this.isReadyToGenerateRandomValues()) {
|
||||
this.addRandomByte(Math.floor(Math.random() * 32), Math.floor(Math.random() * 32), Math.floor(Math.random() * 256));
|
||||
}
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'dump': function(appendToDoc) {
|
||||
var tbl;
|
||||
var i,c;
|
||||
|
||||
tbl = document.createElement("table");
|
||||
tbl.border = 0;
|
||||
with (tbl.style) {
|
||||
border = "1px solid lightgrey";
|
||||
fontFamily = 'Helvetica, Arial, sans-serif';
|
||||
fontSize = '8pt';
|
||||
//borderCollapse = "collapse";
|
||||
}
|
||||
var hdr = tbl.createTHead();
|
||||
var hdrtr = hdr.insertRow(0);
|
||||
// document.createElement("tr");
|
||||
{
|
||||
var ntd;
|
||||
|
||||
ntd = hdrtr.insertCell(0);
|
||||
ntd.style.borderBottom = "1px solid lightgrey";
|
||||
ntd.style.borderRight = "1px solid lightgrey";
|
||||
ntd.appendChild(document.createTextNode("#"));
|
||||
|
||||
ntd = hdrtr.insertCell(1);
|
||||
ntd.style.borderBottom = "1px solid lightgrey";
|
||||
ntd.style.borderRight = "1px solid lightgrey";
|
||||
ntd.appendChild(document.createTextNode("s"));
|
||||
|
||||
ntd = hdrtr.insertCell(2);
|
||||
ntd.colSpan = this.firstPoolReseedLevel();
|
||||
ntd.style.borderBottom = "1px solid lightgrey";
|
||||
ntd.style.borderRight = "1px solid lightgrey";
|
||||
ntd.appendChild(document.createTextNode("base values"));
|
||||
|
||||
ntd = hdrtr.insertCell(3);
|
||||
ntd.colSpan = 20;
|
||||
ntd.style.borderBottom = "1px solid lightgrey";
|
||||
ntd.appendChild(document.createTextNode("extra values"));
|
||||
|
||||
}
|
||||
|
||||
c = this.accumulators().length;
|
||||
for (i=0; i<c ; i++) {
|
||||
var currentAccumulator;
|
||||
var bdytr;
|
||||
var bdytd;
|
||||
var ii, cc;
|
||||
|
||||
currentAccumulator = this.accumulators()[i]
|
||||
|
||||
bdytr = tbl.insertRow(true);
|
||||
|
||||
bdytd = bdytr.insertCell(0);
|
||||
bdytd.style.borderRight = "1px solid lightgrey";
|
||||
bdytd.style.color = "lightgrey";
|
||||
bdytd.appendChild(document.createTextNode("" + i));
|
||||
|
||||
bdytd = bdytr.insertCell(1);
|
||||
bdytd.style.borderRight = "1px solid lightgrey";
|
||||
bdytd.style.color = "gray";
|
||||
bdytd.appendChild(document.createTextNode("" + currentAccumulator.stack().length()));
|
||||
|
||||
|
||||
cc = Math.max(currentAccumulator.stack().length(), this.firstPoolReseedLevel());
|
||||
for (ii=0; ii<cc; ii++) {
|
||||
var cellText;
|
||||
|
||||
bdytd = bdytr.insertCell(ii + 2);
|
||||
|
||||
if (ii < currentAccumulator.stack().length()) {
|
||||
cellText = Clipperz.ByteArray.byteToHex(currentAccumulator.stack().byteAtIndex(ii));
|
||||
} else {
|
||||
cellText = "_";
|
||||
}
|
||||
|
||||
if (ii == (this.firstPoolReseedLevel() - 1)) {
|
||||
bdytd.style.borderRight = "1px solid lightgrey";
|
||||
}
|
||||
|
||||
bdytd.appendChild(document.createTextNode(cellText));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (appendToDoc) {
|
||||
var ne = document.createElement("div");
|
||||
ne.id = "entropyGeneratorStatus";
|
||||
with (ne.style) {
|
||||
fontFamily = "Courier New, monospace";
|
||||
fontSize = "12px";
|
||||
lineHeight = "16px";
|
||||
borderTop = "1px solid black";
|
||||
padding = "10px";
|
||||
}
|
||||
if (document.getElementById(ne.id)) {
|
||||
MochiKit.DOM.swapDOM(ne.id, ne);
|
||||
} else {
|
||||
document.body.appendChild(ne);
|
||||
}
|
||||
ne.appendChild(tbl);
|
||||
}
|
||||
|
||||
return tbl;
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
__syntaxFix__: "syntax fix"
|
||||
});
|
||||
|
||||
//#############################################################################
|
||||
|
||||
Clipperz.Crypto.PRNG.Random = function(args) {
|
||||
args = args || {};
|
||||
// MochiKit.Base.bindMethods(this);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
Clipperz.Crypto.PRNG.Random.prototype = MochiKit.Base.update(null, {
|
||||
|
||||
'toString': function() {
|
||||
return "Clipperz.Crypto.PRNG.Random";
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'getRandomBytes': function(aSize) {
|
||||
//Clipperz.Profile.start("Clipperz.Crypto.PRNG.Random.getRandomBytes");
|
||||
var result;
|
||||
var i,c;
|
||||
|
||||
result = new Clipperz.ByteArray()
|
||||
c = aSize || 1;
|
||||
for (i=0; i<c; i++) {
|
||||
result.appendByte((Math.random()*255) & 0xff);
|
||||
}
|
||||
|
||||
//Clipperz.Profile.stop("Clipperz.Crypto.PRNG.Random.getRandomBytes");
|
||||
return result;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
__syntaxFix__: "syntax fix"
|
||||
});
|
||||
|
||||
//#############################################################################
|
||||
|
||||
_clipperz_crypt_prng_defaultPRNG = null;
|
||||
|
||||
Clipperz.Crypto.PRNG.defaultRandomGenerator = function() {
|
||||
if (_clipperz_crypt_prng_defaultPRNG == null) {
|
||||
_clipperz_crypt_prng_defaultPRNG = new Clipperz.Crypto.PRNG.Fortuna();
|
||||
|
||||
//.............................................................
|
||||
//
|
||||
// TimeRandomnessSource
|
||||
//
|
||||
//.............................................................
|
||||
{
|
||||
var newRandomnessSource;
|
||||
|
||||
newRandomnessSource = new Clipperz.Crypto.PRNG.TimeRandomnessSource({intervalTime:111});
|
||||
_clipperz_crypt_prng_defaultPRNG.addRandomnessSource(newRandomnessSource);
|
||||
}
|
||||
|
||||
//.............................................................
|
||||
//
|
||||
// MouseRandomnessSource
|
||||
//
|
||||
//.............................................................
|
||||
{
|
||||
var newRandomnessSource;
|
||||
|
||||
newRandomnessSource = new Clipperz.Crypto.PRNG.MouseRandomnessSource();
|
||||
_clipperz_crypt_prng_defaultPRNG.addRandomnessSource(newRandomnessSource);
|
||||
}
|
||||
|
||||
//.............................................................
|
||||
//
|
||||
// KeyboardRandomnessSource
|
||||
//
|
||||
//.............................................................
|
||||
{
|
||||
var newRandomnessSource;
|
||||
|
||||
newRandomnessSource = new Clipperz.Crypto.PRNG.KeyboardRandomnessSource();
|
||||
_clipperz_crypt_prng_defaultPRNG.addRandomnessSource(newRandomnessSource);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return _clipperz_crypt_prng_defaultPRNG;
|
||||
};
|
||||
|
||||
//#############################################################################
|
||||
|
||||
Clipperz.Crypto.PRNG.exception = {
|
||||
NotEnoughEntropy: new MochiKit.Base.NamedError("Clipperz.Crypto.PRNG.exception.NotEnoughEntropy")
|
||||
};
|
||||
|
||||
|
||||
MochiKit.DOM.addLoadEvent(Clipperz.Crypto.PRNG.defaultRandomGenerator);
|
||||
146
frontend/delta/js/Clipperz/Crypto/RSA.js
Normal file
146
frontend/delta/js/Clipperz/Crypto/RSA.js
Normal file
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
try { if (typeof(Clipperz.Crypto.BigInt) == 'undefined') { throw ""; }} catch (e) {
|
||||
throw "Clipperz.Crypto.RSA depends on Clipperz.Crypto.BigInt!";
|
||||
}
|
||||
|
||||
if (typeof(Clipperz.Crypto.RSA) == 'undefined') { Clipperz.Crypto.RSA = {}; }
|
||||
|
||||
Clipperz.Crypto.RSA.VERSION = "0.1";
|
||||
Clipperz.Crypto.RSA.NAME = "Clipperz.RSA";
|
||||
|
||||
//#############################################################################
|
||||
|
||||
MochiKit.Base.update(Clipperz.Crypto.RSA, {
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'publicKeyWithValues': function (e, d, n) {
|
||||
var result;
|
||||
|
||||
result = {};
|
||||
|
||||
if (e.isBigInt) {
|
||||
result.e = e;
|
||||
} else {
|
||||
result.e = new Clipperz.Crypto.BigInt(e, 16);
|
||||
}
|
||||
|
||||
if (d.isBigInt) {
|
||||
result.d = d;
|
||||
} else {
|
||||
result.d = new Clipperz.Crypto.BigInt(d, 16);
|
||||
}
|
||||
|
||||
if (n.isBigInt) {
|
||||
result.n = n;
|
||||
} else {
|
||||
result.n = new Clipperz.Crypto.BigInt(n, 16);
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
'privateKeyWithValues': function(e, d, n) {
|
||||
return Clipperz.Crypto.RSA.publicKeyWithValues(e, d, n);
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'encryptUsingPublicKey': function (aKey, aMessage) {
|
||||
var messageValue;
|
||||
var result;
|
||||
|
||||
messageValue = new Clipperz.Crypto.BigInt(aMessage, 16);
|
||||
result = messageValue.powerModule(aKey.e, aKey.n);
|
||||
|
||||
return result.asString(16);
|
||||
},
|
||||
|
||||
//.............................................................................
|
||||
|
||||
'decryptUsingPublicKey': function (aKey, aMessage) {
|
||||
return Clipperz.Crypto.RSA.encryptUsingPublicKey(aKey, aMessage);
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'encryptUsingPrivateKey': function (aKey, aMessage) {
|
||||
var messageValue;
|
||||
var result;
|
||||
|
||||
messageValue = new Clipperz.Crypto.BigInt(aMessage, 16);
|
||||
result = messageValue.powerModule(aKey.d, aKey.n);
|
||||
|
||||
return result.asString(16);
|
||||
},
|
||||
|
||||
//.............................................................................
|
||||
|
||||
'decryptUsingPrivateKey': function (aKey, aMessage) {
|
||||
return Clipperz.Crypto.RSA.encryptUsingPrivateKey(aKey, aMessage);
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'generatePublicKey': function(aNumberOfBits) {
|
||||
var result;
|
||||
var e;
|
||||
var d;
|
||||
var n;
|
||||
|
||||
e = new Clipperz.Crypto.BigInt("10001", 16);
|
||||
|
||||
{
|
||||
var p, q;
|
||||
var phi;
|
||||
|
||||
do {
|
||||
p = Clipperz.Crypto.BigInt.randomPrime(aNumberOfBits);
|
||||
} while (p.module(e).equals(1));
|
||||
|
||||
do {
|
||||
q = Clipperz.Crypto.BigInt.randomPrime(aNumberOfBits);
|
||||
} while ((q.equals(p)) || (q.module(e).equals(1)));
|
||||
|
||||
n = p.multiply(q);
|
||||
phi = (p.subtract(1).multiply(q.subtract(1)));
|
||||
d = e.powerModule(-1, phi);
|
||||
}
|
||||
|
||||
result = Clipperz.Crypto.RSA.publicKeyWithValues(e, d, n);
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
__syntaxFix__: "syntax fix"
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
});
|
||||
|
||||
//#############################################################################
|
||||
|
||||
296
frontend/delta/js/Clipperz/Crypto/SHA.js
Normal file
296
frontend/delta/js/Clipperz/Crypto/SHA.js
Normal file
@@ -0,0 +1,296 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
try { if (typeof(Clipperz.ByteArray) == 'undefined') { throw ""; }} catch (e) {
|
||||
throw "Clipperz.Crypto.PRNG depends on Clipperz.ByteArray!";
|
||||
}
|
||||
|
||||
if (typeof(Clipperz.Crypto) == 'undefined') { Clipperz.Crypto = {}; }
|
||||
if (typeof(Clipperz.Crypto.SHA) == 'undefined') { Clipperz.Crypto.SHA = {}; }
|
||||
|
||||
Clipperz.Crypto.SHA.VERSION = "0.3";
|
||||
Clipperz.Crypto.SHA.NAME = "Clipperz.Crypto.SHA";
|
||||
|
||||
MochiKit.Base.update(Clipperz.Crypto.SHA, {
|
||||
|
||||
'__repr__': function () {
|
||||
return "[" + this.NAME + " " + this.VERSION + "]";
|
||||
},
|
||||
|
||||
'toString': function () {
|
||||
return this.__repr__();
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'rotateRight': function(aValue, aNumberOfBits) {
|
||||
//Clipperz.Profile.start("Clipperz.Crypto.SHA.rotateRight");
|
||||
var result;
|
||||
|
||||
result = (aValue >>> aNumberOfBits) | (aValue << (32 - aNumberOfBits));
|
||||
|
||||
//Clipperz.Profile.stop("Clipperz.Crypto.SHA.rotateRight");
|
||||
return result;
|
||||
},
|
||||
|
||||
'shiftRight': function(aValue, aNumberOfBits) {
|
||||
//Clipperz.Profile.start("Clipperz.Crypto.SHA.shiftRight");
|
||||
var result;
|
||||
|
||||
result = aValue >>> aNumberOfBits;
|
||||
|
||||
//Clipperz.Profile.stop("Clipperz.Crypto.SHA.shiftRight");
|
||||
return result;
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'safeAdd': function() {
|
||||
//Clipperz.Profile.start("Clipperz.Crypto.SHA.safeAdd");
|
||||
var result;
|
||||
var i, c;
|
||||
|
||||
result = arguments[0];
|
||||
c = arguments.length;
|
||||
for (i=1; i<c; i++) {
|
||||
var lowerBytesSum;
|
||||
|
||||
lowerBytesSum = (result & 0xffff) + (arguments[i] & 0xffff);
|
||||
result = (((result >> 16) + (arguments[i] >> 16) + (lowerBytesSum >> 16)) << 16) | (lowerBytesSum & 0xffff);
|
||||
}
|
||||
|
||||
//Clipperz.Profile.stop("Clipperz.Crypto.SHA.safeAdd");
|
||||
return result;
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'sha256_array': function(aValue) {
|
||||
//Clipperz.Profile.start("Clipperz.Crypto.SHA.sha256_array");
|
||||
var result;
|
||||
var message;
|
||||
var h0, h1, h2, h3, h4, h5, h6, h7;
|
||||
var k;
|
||||
var messageLength;
|
||||
var messageLengthInBits;
|
||||
var _i, _c;
|
||||
var charBits;
|
||||
var rotateRight;
|
||||
var shiftRight;
|
||||
var safeAdd;
|
||||
var bytesPerBlock;
|
||||
var currentMessageIndex;
|
||||
|
||||
bytesPerBlock = 512/8;
|
||||
rotateRight = Clipperz.Crypto.SHA.rotateRight;
|
||||
shiftRight = Clipperz.Crypto.SHA.shiftRight;
|
||||
safeAdd = Clipperz.Crypto.SHA.safeAdd;
|
||||
|
||||
charBits = 8;
|
||||
|
||||
h0 = 0x6a09e667;
|
||||
h1 = 0xbb67ae85;
|
||||
h2 = 0x3c6ef372;
|
||||
h3 = 0xa54ff53a;
|
||||
h4 = 0x510e527f;
|
||||
h5 = 0x9b05688c;
|
||||
h6 = 0x1f83d9ab;
|
||||
h7 = 0x5be0cd19;
|
||||
|
||||
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];
|
||||
|
||||
message = aValue;
|
||||
messageLength = message.length;
|
||||
|
||||
//Pre-processing:
|
||||
message.push(0x80); // append a single "1" bit to message
|
||||
|
||||
_c = (512 - (((messageLength + 1) * charBits) % 512) - 64) / charBits;
|
||||
if (_c < 0) {
|
||||
_c = _c + (512 / charBits);
|
||||
}
|
||||
|
||||
for (_i=0; _i<_c; _i++) {
|
||||
message.push(0x00); // append "0" bits until message length ≡ 448 ≡ -64 (mod 512)
|
||||
}
|
||||
|
||||
messageLengthInBits = messageLength * charBits;
|
||||
message.push(0x00); // the 4 most high byte are alway 0 as message length is represented with a 32bit value;
|
||||
message.push(0x00);
|
||||
message.push(0x00);
|
||||
message.push(0x00);
|
||||
message.push((messageLengthInBits >> 24) & 0xff);
|
||||
message.push((messageLengthInBits >> 16) & 0xff);
|
||||
message.push((messageLengthInBits >> 8) & 0xff);
|
||||
message.push( messageLengthInBits & 0xff);
|
||||
|
||||
currentMessageIndex = 0;
|
||||
while(currentMessageIndex < message.length) {
|
||||
var w;
|
||||
var a, b, c, d, e, f, g, h;
|
||||
|
||||
w = Array(64);
|
||||
|
||||
_c = 16;
|
||||
for (_i=0; _i<_c; _i++) {
|
||||
var _j;
|
||||
|
||||
_j = currentMessageIndex + _i*4;
|
||||
w[_i] = (message[_j] << 24) | (message[_j + 1] << 16) | (message[_j + 2] << 8) | (message[_j + 3] << 0);
|
||||
}
|
||||
|
||||
_c = 64;
|
||||
for (_i=16; _i<_c; _i++) {
|
||||
var s0, s1;
|
||||
|
||||
s0 = (rotateRight(w[_i-15], 7)) ^ (rotateRight(w[_i-15], 18)) ^ (shiftRight(w[_i-15], 3));
|
||||
s1 = (rotateRight(w[_i-2], 17)) ^ (rotateRight(w[_i-2], 19)) ^ (shiftRight(w[_i-2], 10));
|
||||
w[_i] = safeAdd(w[_i-16], s0, w[_i-7], s1);
|
||||
}
|
||||
|
||||
a=h0; b=h1; c=h2; d=h3; e=h4; f=h5; g=h6; h=h7;
|
||||
|
||||
_c = 64;
|
||||
for (_i=0; _i<_c; _i++) {
|
||||
var s0, s1, ch, maj, t1, t2;
|
||||
|
||||
s0 = (rotateRight(a, 2)) ^ (rotateRight(a, 13)) ^ (rotateRight(a, 22));
|
||||
maj = (a & b) ^ (a & c) ^ (b & c);
|
||||
t2 = safeAdd(s0, maj);
|
||||
s1 = (rotateRight(e, 6)) ^ (rotateRight(e, 11)) ^ (rotateRight(e, 25));
|
||||
ch = (e & f) ^ ((~e) & g);
|
||||
t1 = safeAdd(h, s1, ch, k[_i], w[_i]);
|
||||
|
||||
h = g;
|
||||
g = f;
|
||||
f = e;
|
||||
e = safeAdd(d, t1);
|
||||
d = c;
|
||||
c = b;
|
||||
b = a;
|
||||
a = safeAdd(t1, t2);
|
||||
}
|
||||
|
||||
h0 = safeAdd(h0, a);
|
||||
h1 = safeAdd(h1, b);
|
||||
h2 = safeAdd(h2, c);
|
||||
h3 = safeAdd(h3, d);
|
||||
h4 = safeAdd(h4, e);
|
||||
h5 = safeAdd(h5, f);
|
||||
h6 = safeAdd(h6, g);
|
||||
h7 = safeAdd(h7, h);
|
||||
|
||||
currentMessageIndex += bytesPerBlock;
|
||||
}
|
||||
|
||||
result = new Array(256/8);
|
||||
result[0] = (h0 >> 24) & 0xff;
|
||||
result[1] = (h0 >> 16) & 0xff;
|
||||
result[2] = (h0 >> 8) & 0xff;
|
||||
result[3] = h0 & 0xff;
|
||||
|
||||
result[4] = (h1 >> 24) & 0xff;
|
||||
result[5] = (h1 >> 16) & 0xff;
|
||||
result[6] = (h1 >> 8) & 0xff;
|
||||
result[7] = h1 & 0xff;
|
||||
|
||||
result[8] = (h2 >> 24) & 0xff;
|
||||
result[9] = (h2 >> 16) & 0xff;
|
||||
result[10] = (h2 >> 8) & 0xff;
|
||||
result[11] = h2 & 0xff;
|
||||
|
||||
result[12] = (h3 >> 24) & 0xff;
|
||||
result[13] = (h3 >> 16) & 0xff;
|
||||
result[14] = (h3 >> 8) & 0xff;
|
||||
result[15] = h3 & 0xff;
|
||||
|
||||
result[16] = (h4 >> 24) & 0xff;
|
||||
result[17] = (h4 >> 16) & 0xff;
|
||||
result[18] = (h4 >> 8) & 0xff;
|
||||
result[19] = h4 & 0xff;
|
||||
|
||||
result[20] = (h5 >> 24) & 0xff;
|
||||
result[21] = (h5 >> 16) & 0xff;
|
||||
result[22] = (h5 >> 8) & 0xff;
|
||||
result[23] = h5 & 0xff;
|
||||
|
||||
result[24] = (h6 >> 24) & 0xff;
|
||||
result[25] = (h6 >> 16) & 0xff;
|
||||
result[26] = (h6 >> 8) & 0xff;
|
||||
result[27] = h6 & 0xff;
|
||||
|
||||
result[28] = (h7 >> 24) & 0xff;
|
||||
result[29] = (h7 >> 16) & 0xff;
|
||||
result[30] = (h7 >> 8) & 0xff;
|
||||
result[31] = h7 & 0xff;
|
||||
|
||||
//Clipperz.Profile.stop("Clipperz.Crypto.SHA.sha256_array");
|
||||
return result;
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'sha256': function(aValue) {
|
||||
//Clipperz.Profile.start("Clipperz.Crypto.SHA.sha256");
|
||||
var result;
|
||||
var resultArray;
|
||||
var valueArray;
|
||||
|
||||
valueArray = aValue.arrayValues();
|
||||
resultArray = Clipperz.Crypto.SHA.sha256_array(valueArray);
|
||||
|
||||
result = new Clipperz.ByteArray(resultArray);
|
||||
|
||||
//Clipperz.Profile.stop("Clipperz.Crypto.SHA.sha256");
|
||||
return result;
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'sha_d256': function(aValue) {
|
||||
//Clipperz.Profile.start("Clipperz.Crypto.SHA.sha_d256");
|
||||
var result;
|
||||
var resultArray;
|
||||
var valueArray;
|
||||
|
||||
valueArray = aValue.arrayValues();
|
||||
resultArray = Clipperz.Crypto.SHA.sha256_array(valueArray);
|
||||
resultArray = Clipperz.Crypto.SHA.sha256_array(resultArray);
|
||||
|
||||
result = new Clipperz.ByteArray(resultArray);
|
||||
|
||||
//Clipperz.Profile.stop("Clipperz.Crypto.SHA.sha256");
|
||||
return result;
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
__syntaxFix__: "syntax fix"
|
||||
|
||||
});
|
||||
316
frontend/delta/js/Clipperz/Crypto/SRP.js
Normal file
316
frontend/delta/js/Clipperz/Crypto/SRP.js
Normal file
@@ -0,0 +1,316 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
try { if (typeof(Clipperz.ByteArray) == 'undefined') { throw ""; }} catch (e) {
|
||||
throw "Clipperz.Crypto.PRNG depends on Clipperz.ByteArray!";
|
||||
}
|
||||
|
||||
try { if (typeof(Clipperz.Crypto.BigInt) == 'undefined') { throw ""; }} catch (e) {
|
||||
throw "Clipperz.Crypto.SRP depends on Clipperz.Crypto.BigInt!";
|
||||
}
|
||||
|
||||
try { if (typeof(Clipperz.Crypto.PRNG) == 'undefined') { throw ""; }} catch (e) {
|
||||
throw "Clipperz.Crypto.SRP depends on Clipperz.Crypto.PRNG!";
|
||||
}
|
||||
|
||||
if (typeof(Clipperz.Crypto.SRP) == 'undefined') { Clipperz.Crypto.SRP = {}; }
|
||||
|
||||
Clipperz.Crypto.SRP.VERSION = "0.1";
|
||||
Clipperz.Crypto.SRP.NAME = "Clipperz.Crypto.SRP";
|
||||
|
||||
//#############################################################################
|
||||
|
||||
MochiKit.Base.update(Clipperz.Crypto.SRP, {
|
||||
|
||||
'_n': null,
|
||||
'_g': null,
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'n': function() {
|
||||
if (Clipperz.Crypto.SRP._n == null) {
|
||||
Clipperz.Crypto.SRP._n = new Clipperz.Crypto.BigInt("115b8b692e0e045692cf280b436735c77a5a9e8a9e7ed56c965f87db5b2a2ece3", 16);
|
||||
}
|
||||
|
||||
return Clipperz.Crypto.SRP._n;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'g': function() {
|
||||
if (Clipperz.Crypto.SRP._g == null) {
|
||||
Clipperz.Crypto.SRP._g = new Clipperz.Crypto.BigInt(2); // eventually 5 (as suggested on the Diffi-Helmann documentation)
|
||||
}
|
||||
|
||||
return Clipperz.Crypto.SRP._g;
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'exception': {
|
||||
'InvalidValue': new MochiKit.Base.NamedError("Clipperz.Crypto.SRP.exception.InvalidValue")
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
__syntaxFix__: "syntax fix"
|
||||
|
||||
});
|
||||
|
||||
//#############################################################################
|
||||
//
|
||||
// S R P C o n n e c t i o n version 1.0
|
||||
//
|
||||
//=============================================================================
|
||||
Clipperz.Crypto.SRP.Connection = function (args) {
|
||||
args = args || {};
|
||||
|
||||
this._C = args.C;
|
||||
this._P = args.P;
|
||||
this.hash = args.hash;
|
||||
|
||||
this._a = null;
|
||||
this._A = null;
|
||||
|
||||
this._s = null;
|
||||
this._B = null;
|
||||
|
||||
this._x = null;
|
||||
|
||||
this._u = null;
|
||||
this._K = null;
|
||||
this._M1 = null;
|
||||
this._M2 = null;
|
||||
|
||||
this._sessionKey = null;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
Clipperz.Crypto.SRP.Connection.prototype = MochiKit.Base.update(null, {
|
||||
|
||||
'toString': function () {
|
||||
return "Clipperz.Crypto.SRP.Connection (username: " + this.username() + "). Status: " + this.statusDescription();
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'C': function () {
|
||||
return this._C;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'P': function () {
|
||||
return this._P;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'a': function () {
|
||||
if (this._a == null) {
|
||||
this._a = new Clipperz.Crypto.BigInt(Clipperz.Crypto.PRNG.defaultRandomGenerator().getRandomBytes(32).toHexString().substring(2), 16);
|
||||
// this._a = new Clipperz.Crypto.BigInt("37532428169486597638072888476611365392249575518156687476805936694442691012367", 10);
|
||||
}
|
||||
|
||||
return this._a;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'A': function () {
|
||||
if (this._A == null) {
|
||||
// Warning: this value should be strictly greater than zero: how should we perform this check?
|
||||
this._A = Clipperz.Crypto.SRP.g().powerModule(this.a(), Clipperz.Crypto.SRP.n());
|
||||
|
||||
if (this._A.equals(0)) {
|
||||
Clipperz.logError("Clipperz.Crypto.SRP.Connection: trying to set 'A' to 0.");
|
||||
throw Clipperz.Crypto.SRP.exception.InvalidValue;
|
||||
}
|
||||
}
|
||||
|
||||
return this._A;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
's': function () {
|
||||
return this._s;
|
||||
},
|
||||
|
||||
'set_s': function(aValue) {
|
||||
this._s = aValue;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'B': function () {
|
||||
return this._B;
|
||||
},
|
||||
|
||||
'set_B': function(aValue) {
|
||||
// Warning: this value should be strictly greater than zero: how should we perform this check?
|
||||
if (! aValue.equals(0)) {
|
||||
this._B = aValue;
|
||||
} else {
|
||||
Clipperz.logError("Clipperz.Crypto.SRP.Connection: trying to set 'B' to 0.");
|
||||
throw Clipperz.Crypto.SRP.exception.InvalidValue;
|
||||
}
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'x': function () {
|
||||
if (this._x == null) {
|
||||
this._x = new Clipperz.Crypto.BigInt(this.stringHash(this.s().asString(16, 64) + this.P()), 16);
|
||||
}
|
||||
|
||||
return this._x;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'u': function () {
|
||||
if (this._u == null) {
|
||||
this._u = new Clipperz.Crypto.BigInt(this.stringHash(this.B().asString()), 16);
|
||||
}
|
||||
|
||||
return this._u;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'S': function () {
|
||||
if (this._S == null) {
|
||||
var bigint;
|
||||
var srp;
|
||||
|
||||
bigint = Clipperz.Crypto.BigInt;
|
||||
srp = Clipperz.Crypto.SRP;
|
||||
|
||||
this._S = bigint.powerModule(
|
||||
bigint.subtract(this.B(), bigint.powerModule(srp.g(), this.x(), srp.n())),
|
||||
bigint.add(this.a(), bigint.multiply(this.u(), this.x())),
|
||||
srp.n()
|
||||
)
|
||||
}
|
||||
|
||||
return this._S;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'K': function () {
|
||||
if (this._K == null) {
|
||||
this._K = this.stringHash(this.S().asString());
|
||||
}
|
||||
|
||||
return this._K;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'M1': function () {
|
||||
if (this._M1 == null) {
|
||||
this._M1 = this.stringHash(this.A().asString(10) + this.B().asString(10) + this.K());
|
||||
}
|
||||
|
||||
return this._M1;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'M2': function () {
|
||||
if (this._M2 == null) {
|
||||
this._M2 = this.stringHash(this.A().asString(10) + this.M1() + this.K());
|
||||
}
|
||||
|
||||
return this._M2;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'serverSideCredentialsWithSalt': function(aSalt) {
|
||||
var result;
|
||||
var s, x, v;
|
||||
|
||||
s = aSalt;
|
||||
x = this.stringHash(s + this.P());
|
||||
v = Clipperz.Crypto.SRP.g().powerModule(new Clipperz.Crypto.BigInt(x, 16), Clipperz.Crypto.SRP.n());
|
||||
|
||||
result = {};
|
||||
result['C'] = this.C();
|
||||
result['s'] = s;
|
||||
result['v'] = v.asString(16);
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
'serverSideCredentials': function() {
|
||||
var result;
|
||||
var s;
|
||||
|
||||
s = Clipperz.Crypto.PRNG.defaultRandomGenerator().getRandomBytes(32).toHexString().substring(2);
|
||||
|
||||
result = this.serverSideCredentialsWithSalt(s);
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
/*
|
||||
'computeServerSide_S': function(b) {
|
||||
var result;
|
||||
var v;
|
||||
var bigint;
|
||||
var srp;
|
||||
|
||||
bigint = Clipperz.Crypto.BigInt;
|
||||
srp = Clipperz.Crypto.SRP;
|
||||
|
||||
v = new Clipperz.Crypto.BigInt(srpConnection.serverSideCredentialsWithSalt(this.s().asString(16, 64)).v, 16);
|
||||
// _S = (this.A().multiply(this.v().modPow(this.u(), this.n()))).modPow(this.b(), this.n());
|
||||
result = bigint.powerModule(
|
||||
bigint.multiply(
|
||||
this.A(),
|
||||
bigint.powerModule(v, this.u(), srp.n())
|
||||
), new Clipperz.Crypto.BigInt(b, 10), srp.n()
|
||||
);
|
||||
|
||||
return result;
|
||||
},
|
||||
*/
|
||||
//=========================================================================
|
||||
|
||||
'stringHash': function(aValue) {
|
||||
var result;
|
||||
|
||||
result = this.hash(new Clipperz.ByteArray(aValue)).toHexString().substring(2);
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
__syntaxFix__: "syntax fix"
|
||||
|
||||
});
|
||||
|
||||
//#############################################################################
|
||||
134
frontend/delta/js/Clipperz/DOM.js
Normal file
134
frontend/delta/js/Clipperz/DOM.js
Normal file
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
|
||||
if (typeof(Clipperz.DOM) == 'undefined') { Clipperz.DOM = {}; }
|
||||
|
||||
Clipperz.DOM.VERSION = "0.1";
|
||||
Clipperz.DOM.NAME = "Clipperz.DOM";
|
||||
|
||||
MochiKit.Base.update(Clipperz.DOM, {
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'__repr__': function () {
|
||||
return "[" + this.NAME + " " + this.VERSION + "]";
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'toString': function () {
|
||||
return this.__repr__();
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'selectOptionMatchingValue': function (aSelectElement, aValue, shouldUseCaseInsensitiveTest) {
|
||||
var selectedOptionIndex;
|
||||
var i, c;
|
||||
|
||||
selectedOptionIndex = -1;
|
||||
|
||||
c = aSelectElement.options.length;
|
||||
for (i=0; (i<c) && (selectedOptionIndex == -1); i++) {
|
||||
if (shouldUseCaseInsensitiveTest == true) {
|
||||
if (aSelectElement.options[i].value.toLowerCase() == aValue.toLowerCase()) {
|
||||
selectedOptionIndex = i;
|
||||
}
|
||||
} else {
|
||||
if (aSelectElement.options[i].value == aValue) {
|
||||
selectedOptionIndex = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (selectedOptionIndex != -1) {
|
||||
aSelectElement.selectedIndex = selectedOptionIndex;
|
||||
}
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'setFormContents': function(aNode, someValues) {
|
||||
var node;
|
||||
var values;
|
||||
var i, c;
|
||||
|
||||
values = {};
|
||||
c = someValues[0].length;
|
||||
for (i=0; i<c; i++) {
|
||||
values[someValues[0][i]] = someValues[1][i];
|
||||
}
|
||||
|
||||
// var m = MochiKit.Base;
|
||||
// var self = MochiKit.DOM;
|
||||
if (typeof(aNode) == "undefined" || aNode === null) {
|
||||
node = MochiKit.DOM._document.body;
|
||||
} else {
|
||||
node = MochiKit.DOM.getElement(aNode);
|
||||
}
|
||||
|
||||
MochiKit.Base.nodeWalk(node, function(aNode) {
|
||||
var result;
|
||||
var name;
|
||||
|
||||
result = null;
|
||||
name = aNode.name;
|
||||
if (MochiKit.Base.isNotEmpty(name) && (typeof(values[name]) != 'undefined')) {
|
||||
var tagName;
|
||||
|
||||
tagName = aNode.tagName.toUpperCase();
|
||||
if (tagName === "INPUT" && (aNode.type == "radio" || aNode.type == "checkbox")) {
|
||||
aNode.checked = values[name];
|
||||
} else if (tagName === "SELECT") {
|
||||
if (aNode.type == "select-one") {
|
||||
Clipperz.DOM.selectOptionMatchingValue(aNode, values[name]);
|
||||
} else { // aNode.type == "select-multiple"
|
||||
Clipperz.logWarning("### unhandled Select.type = 'select-multiple' condition");
|
||||
}
|
||||
} else if (tagName === "FORM" || tagName === "P" || tagName === "SPAN" || tagName === "DIV") {
|
||||
result = aNode.childNodes;
|
||||
} else {
|
||||
aNode.value = values[name]
|
||||
}
|
||||
} else {
|
||||
result = aNode.childNodes;
|
||||
}
|
||||
|
||||
return result;
|
||||
});
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'get': MochiKit.DOM.getElement,
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'Helper': Clipperz.YUI.DomHelper,
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
__syntaxFix__: "syntax fix"
|
||||
|
||||
});
|
||||
|
||||
297
frontend/delta/js/Clipperz/Date.js
Normal file
297
frontend/delta/js/Clipperz/Date.js
Normal file
@@ -0,0 +1,297 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
|
||||
if (typeof(Clipperz.Date) == 'undefined') { Clipperz.Date = {}; }
|
||||
|
||||
Clipperz.Date.VERSION = "0.1";
|
||||
Clipperz.Date.NAME = "Clipperz.Date";
|
||||
|
||||
MochiKit.Base.update(Clipperz.Date, {
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'__repr__': function () {
|
||||
return "[" + this.NAME + " " + this.VERSION + "]";
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'toString': function () {
|
||||
return this.__repr__();
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'daysInMonth': [31,28,31,30,31,30,31,31,30,31,30,31],
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'englishOrdinalDaySuffixForDate': function(aDate) {
|
||||
var result;
|
||||
|
||||
switch (aDate.getDate()) {
|
||||
case 1:
|
||||
case 21:
|
||||
case 31:
|
||||
result = "st";
|
||||
break;
|
||||
case 2:
|
||||
case 22:
|
||||
result = "nd";
|
||||
break;
|
||||
case 3:
|
||||
case 23:
|
||||
result = "rd";
|
||||
break;
|
||||
default:
|
||||
result = "th";
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'isLeapYear': function(aDate) {
|
||||
var year;
|
||||
var result;
|
||||
|
||||
year = aDate.getFullYear();
|
||||
result = ((year & 0x03) == 0 && (year % 100 || (year % 400 == 0 && year)));
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'getDaysInMonth': function(aDate) {
|
||||
var result;
|
||||
|
||||
if (aDate.getMonth() == 1) {
|
||||
Clipperz.Date.isLeapYear(aDate)
|
||||
result += Clipperz.Date.isLeapYear(aDate) ? 29 : 28;
|
||||
} else {
|
||||
result = Clipperz.Date.daysInMonth[aDate.getMonth()];
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'getTimezone': function(aDate) {
|
||||
var result;
|
||||
|
||||
result = aDate.toString();
|
||||
result = result.replace(/([A-Z]{3}) [0-9]{4}/, '$1');
|
||||
result = result.replace(/^.*?\(([A-Z])[a-z]+ ([A-Z])[a-z]+ ([A-Z])[a-z]+\)$/, "$1$2$3");
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
'getGMTOffset': function(aDate) {
|
||||
return (aDate.getTimezoneOffset() > 0 ? "-" : "+") + MochiKit.Format.numberFormatter('00')(Math.floor(this.getTimezoneOffset() / 60))
|
||||
+ MochiKit.Format.numberFormatter('00')(this.getTimezoneOffset() % 60);
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'dayOfYear': function(aDate) {
|
||||
var result;
|
||||
var i,c;
|
||||
|
||||
result = 0;
|
||||
c = aDate.getMonth();
|
||||
for (i=0; i<c; i++) {
|
||||
if (i == 1) {
|
||||
result += Clipperz.Date.isLeapYear(aDate) ? 29 : 28;
|
||||
} else {
|
||||
result += Clipperz.Date.daysInMonth[i];
|
||||
}
|
||||
}
|
||||
return num + this.getDate() - 1;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'getPHPLikeFormatCode': function(aCharacter) {
|
||||
var result;
|
||||
|
||||
switch (aCharacter) {
|
||||
case "d":
|
||||
result = " + MochiKit.Format.numberFormatter('00')(aDate.getDate())";
|
||||
break;
|
||||
case "D":
|
||||
result = " + aLocale['shortDays'][aDate.getDay()]";
|
||||
break;
|
||||
case "j":
|
||||
result = " + aDate.getDate()";
|
||||
break;
|
||||
case "l":
|
||||
result = " + aLocale['days'][aDate.getDay()]";
|
||||
break;
|
||||
case "S":
|
||||
result = " + Clipperz.Date.englishOrdinalDaySuffixForDate(aDate)";
|
||||
break;
|
||||
case "w":
|
||||
result = " + aDate.getDay()";
|
||||
break;
|
||||
case "z":
|
||||
result = " + aDate.getDayOfYear()";
|
||||
break;
|
||||
case "W":
|
||||
result = " + aDate.getWeekOfYear()";
|
||||
break;
|
||||
case "F":
|
||||
result = " + aLocale['months'][aDate.getMonth()]";
|
||||
break;
|
||||
case "m":
|
||||
result = " + MochiKit.Format.numberFormatter('00')(aDate.getMonth() + 1)";
|
||||
break;
|
||||
case "M":
|
||||
result = " + aLocale['shortMonths'][aDate.getMonth()]";
|
||||
break;
|
||||
case "n":
|
||||
result = " + (aDate.getMonth() + 1)";
|
||||
break;
|
||||
case "t":
|
||||
result = " + Clipperz.Date.getDaysInMonth(aDate)";
|
||||
break;
|
||||
case "L":
|
||||
result = " + (Clipperz.Date.isLeapYear(aDate) ? 1 : 0)";
|
||||
break;
|
||||
case "Y":
|
||||
result = " + aDate.getFullYear()";
|
||||
break;
|
||||
case "y":
|
||||
result = " + ('' + aDate.getFullYear()).substring(2, 4)";
|
||||
break;
|
||||
case "a":
|
||||
result = " + (aDate.getHours() < 12 ? aLocale['amDesignation'] : aLocale['pmDesignation'])";
|
||||
break;
|
||||
case "A":
|
||||
result = " + (aDate.getHours() < 12 ? aLocale['amDesignation'].toUpperCase() : aLocale['pmDesignation'].toUpperCase())";
|
||||
break;
|
||||
case "g":
|
||||
result = " + ((aDate.getHours() %12) ? aDate.getHours() % 12 : 12)";
|
||||
break;
|
||||
case "G":
|
||||
result = " + aDate.getHours()";
|
||||
break;
|
||||
case "h":
|
||||
result = " + MochiKit.Format.numberFormatter('00')((aDate.getHours() %12) ? aDate.getHours() % 12 : 12)";
|
||||
break;
|
||||
case "H":
|
||||
result = " + MochiKit.Format.numberFormatter('00')(aDate.getHours())";
|
||||
break;
|
||||
case "i":
|
||||
result = " + MochiKit.Format.numberFormatter('00')(aDate.getMinutes())";
|
||||
break;
|
||||
case "s":
|
||||
result = " + MochiKit.Format.numberFormatter('00')(aDate.getSeconds())";
|
||||
break;
|
||||
case "O":
|
||||
result = " + aDate.getGMTOffset()";
|
||||
break;
|
||||
case "T":
|
||||
result = " + Clipperz.Date.getTimezone(aDate)";
|
||||
break;
|
||||
case "Z":
|
||||
result = " + ( + aDate.getTimezoneOffset() * -60)";
|
||||
break;
|
||||
default:
|
||||
result = " + '" + aCharacter + "'";
|
||||
break;
|
||||
};
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'formatDateWithPHPLikeTemplateAndLocale': function(aDate, aFormat, aLocale) {
|
||||
var result;
|
||||
var formatterCode;
|
||||
var formatter;
|
||||
var i,c;
|
||||
|
||||
formatterCode = "Clipperz.Date.__scratchFormatter = function(aDate, aLocale){return ''";
|
||||
|
||||
c = aFormat.length;
|
||||
i = 0;
|
||||
|
||||
while (i<c) {
|
||||
var character;
|
||||
|
||||
character = aFormat.charAt(i);
|
||||
if (character == "\\") {
|
||||
i++;
|
||||
character = aFormat.charAt(i);
|
||||
formatterCode += " + '" + character + "'"
|
||||
} else {
|
||||
formatterCode += Clipperz.Date.getPHPLikeFormatCode(character);
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
formatterCode += ";}";
|
||||
eval(formatterCode);
|
||||
|
||||
result = Clipperz.Date.__scratchFormatter.call(this, aDate, aLocale);
|
||||
delete Clipperz.Date.__scratchFormatter;
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'parseDateWithPHPLikeTemplateAndLocale': function(aString, aFormat, aLocale) {
|
||||
return new Date();
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'formatDateWithUTCFormatAndLocale': function(aDate, aLocale) {
|
||||
// return Clipperz.Date.formatWithJavaLikeTemplateAndLocale(aDate, "EEE, dd MMMM yyyy HH:mm:ss zzz", aLocale);
|
||||
return aDate.toString();
|
||||
},
|
||||
|
||||
'parseDateWithUTCFormatAndLocale': function(aValue, aLocale) {
|
||||
return new Date(Date.parse(aValue));
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'exception': {
|
||||
// 'AbstractMethod': new MochiKit.Base.NamedError("Clipperz.Base.exception.AbstractMethod"),
|
||||
// 'UnknownType': new MochiKit.Base.NamedError("Clipperz.Base.exception.UnknownType")
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
__syntaxFix__: "syntax fix"
|
||||
|
||||
});
|
||||
|
||||
191
frontend/delta/js/Clipperz/KeePassExportProcessor.js
Normal file
191
frontend/delta/js/Clipperz/KeePassExportProcessor.js
Normal file
@@ -0,0 +1,191 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
|
||||
|
||||
|
||||
Clipperz.KeePassExportProcessor = function(args) {
|
||||
args = args || {};
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
||||
Clipperz.KeePassExportProcessor.prototype = MochiKit.Base.update(null, {
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'deferredParse_core': function(aContext) {
|
||||
var deferredResult;
|
||||
|
||||
if (aContext.line == "") {
|
||||
deferredResult = MochiKit.Async.succeed(aContext.result);
|
||||
} else {
|
||||
var record;
|
||||
|
||||
record = this.parseRecord(aContext);
|
||||
if (record != null) {
|
||||
aContext.result.push(record);
|
||||
}
|
||||
|
||||
aContext.line = aContext.line.replace(/^\n*/g, "").replace(/\n$/g, "");
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("KeePassExportProcessor.deferredParse_core");
|
||||
deferredResult.addCallbackPass(MochiKit.Signal.signal, this, 'importProcessorProgressUpdate', {status:'processing', size:aContext.size, progress:(aContext.size - aContext.line.length)});
|
||||
deferredResult.addCallback(MochiKit.Async.wait, 0.2);
|
||||
deferredResult.addMethod(this, 'deferredParse_core');
|
||||
deferredResult.callback(aContext);
|
||||
}
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//.........................................................................
|
||||
|
||||
'deferredParse': function(aValue) {
|
||||
var deferredResult;
|
||||
var lines;
|
||||
var context;
|
||||
|
||||
lines = aValue.replace(/\r?\n/g, "\n");
|
||||
context = {
|
||||
line: lines,
|
||||
size: lines.length,
|
||||
result: []
|
||||
}
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("KeePassExportProcessor.deferredResult");
|
||||
deferredResult.addMethod(this, 'deferredParse_core');
|
||||
deferredResult.callback(context);
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'parseRecord': function(aContext) {
|
||||
var result;
|
||||
var recordLabelRegexp;
|
||||
var fieldLabelRegexp;
|
||||
var fieldValueRegexp;
|
||||
var fullLineRegexp;
|
||||
/*
|
||||
[Record name]
|
||||
Group Tree:
|
||||
UserName:
|
||||
URL:
|
||||
Password:
|
||||
Notes: test
|
||||
UUID: 525f62430079bae48b79ed2961924b05
|
||||
Icon: 0
|
||||
Creation Time: 2007-06-26 17:56:03
|
||||
Last Access: 2007-10-25 16:23:51
|
||||
Last Modification: 2007-10-25 16:23:51
|
||||
Expires: 2999-12-28 23:59:59
|
||||
|
||||
[Record name] ==> Title
|
||||
Group: General ==> Group
|
||||
Group Tree: ==> Group Tree
|
||||
UserName: ==> UserName
|
||||
URL: ==> URL
|
||||
Password: ==> Password
|
||||
Notes: test ==> Notes
|
||||
UUID: 525f62430079bae48b79ed2961924b05 ==> UUID
|
||||
Icon: 0 ==> Icon
|
||||
Creation Time: 2007-06-26 17:56:03 ==> Creation Time
|
||||
Last Access: 2007-10-25 16:23:51 ==> Last Access
|
||||
Last Modification: 2007-10-25 16:23:51 ==> Last Modification
|
||||
Expires: 2999-12-28 23:59:59 ==> Expires
|
||||
Attachment Description: ==> Attachment Description
|
||||
Attachment: ==> Attachment
|
||||
*/
|
||||
// recordLabelRegexp = new RegExp("(^\\[(.*)\\]\\n|^Title:\s*(.*)\\n)");
|
||||
recordLabelRegexp = new RegExp("^\\[(.*)\\]\\n|^Title:\s*(.*)\\n");
|
||||
fieldLabelRegexp = new RegExp("^\s?(Group|Group Tree|Username|UserName|User Name|Url|URL|Password|Notes|Comment|UUID|Icon|Creation Time|Last Access|Last Modification|Expires|Attachment Description|Attachment|Valid until): ");
|
||||
fieldValueRegexp = new RegExp("(.*)(\\n|$)");
|
||||
fullLineRegexp = new RegExp("^(.*\\n)");
|
||||
|
||||
if (recordLabelRegexp.test(aContext.line) == true) {
|
||||
var line;
|
||||
|
||||
line = aContext.line;
|
||||
|
||||
result = {};
|
||||
result['Title'] = line.match(recordLabelRegexp)[1];
|
||||
line = line.replace(/^.*\n/, "");
|
||||
while (fieldLabelRegexp.test(line) == true) {
|
||||
var fieldName;
|
||||
var fieldValue;
|
||||
|
||||
fieldName = RegExp.$1;
|
||||
line = RegExp.rightContext;
|
||||
|
||||
fieldValue = line.match(fieldValueRegexp)[1];
|
||||
line = RegExp.rightContext;
|
||||
|
||||
if (fieldName == 'Notes') {
|
||||
var isMultiline;
|
||||
|
||||
isMultiline = false;
|
||||
|
||||
if ((line != "") && (fieldLabelRegexp.test(line) == false) && (recordLabelRegexp.test(line) == false)) {
|
||||
fieldValue += '\n';
|
||||
}
|
||||
|
||||
while ((line != "") && (fieldLabelRegexp.test(line) == false) && (recordLabelRegexp.test(line) == false)) {
|
||||
var newLineValue;
|
||||
|
||||
newLineValue = line.match(fullLineRegexp)[1];
|
||||
if (newLineValue != "\n") {
|
||||
isMultiline = true;
|
||||
}
|
||||
fieldValue += newLineValue;
|
||||
line = RegExp.rightContext;
|
||||
}
|
||||
|
||||
if (isMultiline) {
|
||||
fieldValue = fieldValue.replace(/\n$/g, "");
|
||||
} else {
|
||||
fieldValue = fieldValue.replace(/\n\n$/g, "");
|
||||
}
|
||||
|
||||
line = line.replace(/^\n/, '');
|
||||
}
|
||||
|
||||
result[fieldName] = fieldValue;
|
||||
}
|
||||
} else {
|
||||
result = null;
|
||||
}
|
||||
|
||||
aContext.line = line;
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
__syntaxFix__: "syntax fix"
|
||||
});
|
||||
|
||||
|
||||
166
frontend/delta/js/Clipperz/KeyValueObjectStore.js
Normal file
166
frontend/delta/js/Clipperz/KeyValueObjectStore.js
Normal file
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
|
||||
|
||||
//#############################################################################
|
||||
|
||||
Clipperz.KeyValueObjectStore = function(args) {
|
||||
args = args || {};
|
||||
|
||||
// this._name = args['name'] || "unnamed KeyValueObjectStore";
|
||||
this._values = args['values'] || {};
|
||||
// this._referenceObjectStore = null;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
Clipperz.KeyValueObjectStore.prototype = MochiKit.Base.update(null, {
|
||||
|
||||
'values': function() {
|
||||
return this._values;
|
||||
},
|
||||
|
||||
'initWithValues': function (someValues) {
|
||||
this._values = Clipperz.Base.deepClone(someValues) || {};
|
||||
return this;
|
||||
},
|
||||
|
||||
'setValues': function (someValues) {
|
||||
this._values = someValues;
|
||||
return this;
|
||||
},
|
||||
|
||||
// 'initWithObjectStore': function (anObjectStore) {
|
||||
// this._referenceObjectStore = anObjectStore;
|
||||
// },
|
||||
|
||||
'removeAllData': function () {
|
||||
this._values = {};
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'getValue': function(aKeyPath) {
|
||||
var result;
|
||||
var keys;
|
||||
var i,c;
|
||||
|
||||
result = this.values();
|
||||
|
||||
keys = (aKeyPath + '').split('.');
|
||||
c = keys.length;
|
||||
i = 0;
|
||||
|
||||
while ((i<c) && (result != null)) {
|
||||
if (typeof result[keys[i]] != 'undefined') {
|
||||
result = result[keys[i]];
|
||||
} else {
|
||||
result = null;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'setValue': function(aKeyPath, aValue) {
|
||||
var targetObject;
|
||||
var keys;
|
||||
var i,c;
|
||||
|
||||
targetObject = this.values();
|
||||
keys = (aKeyPath + '').split('.');
|
||||
c = keys.length - 1;
|
||||
for (i=0; i<c; i++) {
|
||||
if (typeof targetObject[keys[i]] == 'undefined') {
|
||||
targetObject[keys[i]] = {}
|
||||
}
|
||||
|
||||
targetObject = targetObject[keys[i]];
|
||||
}
|
||||
|
||||
targetObject[keys[c]] = aValue;
|
||||
|
||||
return aValue;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'removeValue': function (aKeyPath) {
|
||||
// this.setValue(aKeyPath, null);
|
||||
|
||||
var targetObject;
|
||||
var keys;
|
||||
var i,c;
|
||||
|
||||
targetObject = this.values();
|
||||
keys = ('' + aKeyPath).split('.');
|
||||
c = keys.length - 1;
|
||||
for (i=0; i<c; i++) {
|
||||
if (typeof targetObject[keys[i]] == 'undefined') {
|
||||
targetObject[keys[i]] = {}
|
||||
}
|
||||
|
||||
targetObject = targetObject[keys[i]];
|
||||
}
|
||||
|
||||
delete targetObject[keys[c]];
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'deferredGetOrSet': function(aKeyPath, aGetterFunction) {
|
||||
var deferredResult;
|
||||
|
||||
if (this.getValue(aKeyPath) != null) {
|
||||
deferredResult = MochiKit.Async.succeed(this.getValue(aKeyPath));
|
||||
} else {
|
||||
deferredResult = new Clipperz.Async.Deferred("KeyValueObjectStore.deferredGetOrSet [" + aKeyPath + "]", {trace:false});
|
||||
|
||||
deferredResult.addCallback(aGetterFunction);
|
||||
deferredResult.addMethod(this, 'setValue', aKeyPath);
|
||||
deferredResult.callback();
|
||||
}
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'isEmpty': function () {
|
||||
return (MochiKit.Base.keys(this.values()).length == 0)
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
'dumpData': function () {
|
||||
return Clipperz.Base.serializeJSON(this.values());
|
||||
},
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
__syntaxFix__: "syntax fix"
|
||||
});
|
||||
32
frontend/delta/js/Clipperz/Logging.js
Normal file
32
frontend/delta/js/Clipperz/Logging.js
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
Clipperz.Base.module('Clipperz');
|
||||
|
||||
Clipperz.log = function () {
|
||||
console.log.apply(console, arguments);
|
||||
}
|
||||
|
||||
Clipperz.logError = Clipperz.log;
|
||||
Clipperz.logWarning = Clipperz.log;
|
||||
Clipperz.logDebug = Clipperz.log;
|
||||
191
frontend/delta/js/Clipperz/PM/BookmarkletProcessor.js
Normal file
191
frontend/delta/js/Clipperz/PM/BookmarkletProcessor.js
Normal file
@@ -0,0 +1,191 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
|
||||
if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
|
||||
|
||||
Clipperz.PM.BookmarkletProcessor = function(aConfiguration) {
|
||||
this._configuration = aConfiguration;
|
||||
|
||||
this._editableFields = null;
|
||||
this._favicon = null;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
Clipperz.PM.BookmarkletProcessor.prototype = MochiKit.Base.update(null, {
|
||||
|
||||
'toString': function() {
|
||||
return "Clipperz.PM.BookmarkletProcessor";
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'configuration': function() {
|
||||
return this._configuration;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'pageTitle': function() {
|
||||
return this.configuration().page.title;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'fields': function() {
|
||||
return this.configuration().form.inputs;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'editableFields': function() {
|
||||
if (this._editableFields == null) {
|
||||
this._editableFields = MochiKit.Base.filter(function(aField) {
|
||||
var result;
|
||||
var type;
|
||||
|
||||
type = aField['type'].toLowerCase();
|
||||
result = ((type != 'hidden') && (type != 'submit') && (type != 'checkbox') && (type != 'radio') && (type != 'select'));
|
||||
|
||||
return result;
|
||||
}, this.fields())
|
||||
}
|
||||
|
||||
return this._editableFields;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'hostname': function() {
|
||||
if (this._hostname == null) {
|
||||
var actionUrl;
|
||||
|
||||
actionUrl = this.configuration()['form']['attributes']['action'];
|
||||
this._hostname = actionUrl.replace(/ ^ h t t p s ? : \ / \ / ( [ ^ \ / ] * ) \ / . * /, '$1');
|
||||
}
|
||||
|
||||
return this._hostname;
|
||||
},
|
||||
|
||||
'favicon': function() {
|
||||
if (this._favicon == null) {
|
||||
this._favicon = "http://" + this.hostname() + "/favicon.ico";
|
||||
}
|
||||
|
||||
return this._favicon;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
__syntaxFix__: "syntax fix"
|
||||
});
|
||||
|
||||
//#############################################################################
|
||||
/ *
|
||||
Clipperz.PM.BookmarkletProcessor.createRecordFromBookmarkletConfiguration = function(anUser, aConfiguration) {
|
||||
var processor;
|
||||
var record;
|
||||
var recordVersion;
|
||||
var directLogin;
|
||||
var bindings;
|
||||
var i,c;
|
||||
|
||||
processor = new Clipperz.PM.BookmarkletProcessor(aConfiguration);
|
||||
|
||||
record = new Clipperz.PM.DataModel.Record({
|
||||
'label': processor.pageTitle(),
|
||||
'notes': "",
|
||||
'user': anUser
|
||||
});
|
||||
recordVersion = new Clipperz.PM.DataModel.Record.Version(record, {})
|
||||
record.setCurrentVersion(recordVersion);
|
||||
|
||||
bindings = {};
|
||||
|
||||
c = processor.editableFields().length;
|
||||
for (i=0; i<c; i++) {
|
||||
var formField;
|
||||
var recordField;
|
||||
|
||||
formField = processor.editableFields()[i];
|
||||
recordField = new Clipperz.PM.DataModel.RecordField({
|
||||
'label': formField['name'],
|
||||
'value': formField['value'],
|
||||
'type': Clipperz.PM.Strings.inputTypeToRecordFieldType[formField['type']],
|
||||
'hidden': false,
|
||||
'recordVersion': recordVersion
|
||||
});
|
||||
recordVersion.addField(recordField);
|
||||
|
||||
bindings[formField['name']] = recordField.key();
|
||||
}
|
||||
|
||||
directLogin = new Clipperz.PM.DataModel.DirectLogin({
|
||||
'record': record,
|
||||
'label': processor.pageTitle(),
|
||||
'favicon': processor.favicon(),
|
||||
'formData': processor.configuration()['form'],
|
||||
'bindingData': bindings,
|
||||
'bookmarkletVersion': '0.2'
|
||||
});
|
||||
record.addDirectLogin(directLogin);
|
||||
|
||||
anUser.addRecord(record);
|
||||
|
||||
return record;
|
||||
};
|
||||
* /
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
Clipperz.PM.BookmarkletProcessor.sanitizeBookmarkletConfiguration = function(aConfiguration) {
|
||||
var result;
|
||||
|
||||
// throw "XSS Bookmarklet attempt";
|
||||
|
||||
result = aConfiguration;
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
Clipperz.PM.BookmarkletProcessor.checkBookmarkletConfiguration = function(aConfiguration) {
|
||||
var result;
|
||||
|
||||
try {
|
||||
result = Clipperz.Base.evalJSON(aConfiguration);
|
||||
result = Clipperz.PM.BookmarkletProcessor.sanitizeBookmarkletConfiguration(result);
|
||||
|
||||
if (result['version'] != '0.2.3') {
|
||||
throw "WrongBookmarkletVersion";
|
||||
}
|
||||
} catch (exception) {
|
||||
throw exception;
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
*/
|
||||
636
frontend/delta/js/Clipperz/PM/Connection.js
Normal file
636
frontend/delta/js/Clipperz/PM/Connection.js
Normal file
@@ -0,0 +1,636 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
|
||||
if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Abstract C O N N E C T I O N class
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
Clipperz.PM.Connection = function (args) {
|
||||
args = args || {};
|
||||
|
||||
this._proxy = args.proxy || Clipperz.PM.Proxy.defaultProxy;
|
||||
this._getCredentialsFunction = args.getCredentialsFunction;
|
||||
|
||||
this._clipperz_pm_crypto_version = null;
|
||||
this._connectionId = null;
|
||||
this._sharedSecret = null;
|
||||
this._serverLockValue = null;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
Clipperz.PM.Connection.prototype = MochiKit.Base.update(null, {
|
||||
|
||||
'toString': function() {
|
||||
return "Connection [" + this.version() + "]";
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'version': function() {
|
||||
throw Clipperz.Base.exception.AbstractMethod;
|
||||
},
|
||||
|
||||
'clipperz_pm_crypto_version': function() {
|
||||
if (this._clipperz_pm_crypto_version == null) {
|
||||
var connectionVersions;
|
||||
var versions;
|
||||
var version;
|
||||
var i, c;
|
||||
|
||||
version = null;
|
||||
connectionVersions = Clipperz.PM.Connection.communicationProtocol.versions;
|
||||
versions = MochiKit.Base.keys(connectionVersions);
|
||||
c = versions.length;
|
||||
for (i=0; i<c; i++) {
|
||||
if (! (versions[i] == 'current')) {
|
||||
if (this instanceof connectionVersions[versions[i]]) {
|
||||
version = versions[i];
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
this._clipperz_pm_crypto_version = version;
|
||||
}
|
||||
|
||||
return this._clipperz_pm_crypto_version;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'defaultErrorHandler': function(anErrorString, anException) {
|
||||
// Clipperz.logError("### Connection.defaultErrorHandler: " + anErrorString, anException);
|
||||
Clipperz.logError("### Connection.defaultErrorHandler: " + anErrorString + " (" + anException + ")");
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'getCredentialsFunction': function () {
|
||||
return this._getCredentialsFunction;
|
||||
},
|
||||
|
||||
'normalizedCredentials': function(someValues) {
|
||||
throw Clipperz.Base.exception.AbstractMethod;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'proxy': function () {
|
||||
return this._proxy;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'register': function () {
|
||||
throw Clipperz.Base.exception.AbstractMethod;
|
||||
},
|
||||
|
||||
'login': function() {
|
||||
throw Clipperz.Base.exception.AbstractMethod;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'message': function(someArguments, aCallback) {
|
||||
throw Clipperz.Base.exception.AbstractMethod;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'serverSideUserCredentials': function() {
|
||||
throw Clipperz.Base.exception.AbstractMethod;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'sharedSecret': function () {
|
||||
return this._sharedSecret;
|
||||
},
|
||||
|
||||
'setSharedSecret': function (aValue) {
|
||||
this._sharedSecret = aValue;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'connectionId': function() {
|
||||
return this._connectionId;
|
||||
},
|
||||
|
||||
'setConnectionId': function(aValue) {
|
||||
this._connectionId = aValue;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'serverLockValue': function () {
|
||||
return this._serverLockValue;
|
||||
},
|
||||
|
||||
'setServerLockValue': function (aValue) {
|
||||
this._serverLockValue = aValue;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
/*
|
||||
// TODO: ?????
|
||||
'oneTimePassword': function() {
|
||||
return this._oneTimePassword;
|
||||
},
|
||||
|
||||
'setOneTimePassword': function(aValue) {
|
||||
this._oneTimePassword = aValue;
|
||||
},
|
||||
*/
|
||||
//=========================================================================
|
||||
|
||||
'reset': function() {
|
||||
this.setSharedSecret(null);
|
||||
this.setConnectionId(null);
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
__syntaxFix__: "syntax fix"
|
||||
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
if (typeof(Clipperz.PM.Connection.SRP) == 'undefined') { Clipperz.PM.Connection.SRP = {}; }
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// S R P [ 1 . 0 ] C O N N E C T I O N class
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
Clipperz.PM.Connection.SRP['1.0'] = function (args) {
|
||||
Clipperz.PM.Connection.call(this, args);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
Clipperz.PM.Connection.SRP['1.0'].prototype = MochiKit.Base.update(new Clipperz.PM.Connection(), {
|
||||
|
||||
'version': function() {
|
||||
return '1.0';
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'register': function (someUserData) {
|
||||
var deferredResult;
|
||||
var cryptoVersion;
|
||||
var srpConnection;
|
||||
|
||||
cryptoVersion = this.clipperz_pm_crypto_version();
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("Connection.registerWithVersion", {trace:false});
|
||||
deferredResult.collectResults({
|
||||
'credentials': [
|
||||
this.getCredentialsFunction(),
|
||||
MochiKit.Base.method(this, 'normalizedCredentials'),
|
||||
MochiKit.Base.bind(function(someCredentials) {
|
||||
var srpConnection;
|
||||
var result;
|
||||
|
||||
srpConnection = new Clipperz.Crypto.SRP.Connection({ C:someCredentials['username'], P:someCredentials['password'], hash:this.hash() });
|
||||
result = srpConnection.serverSideCredentials();
|
||||
result['version'] = Clipperz.PM.Connection.communicationProtocol.currentVersion;
|
||||
|
||||
return result;
|
||||
}, this)
|
||||
],
|
||||
'user': MochiKit.Base.partial(MochiKit.Async.succeed, someUserData),
|
||||
'version': MochiKit.Base.partial(MochiKit.Async.succeed, Clipperz.PM.Connection.communicationProtocol.currentVersion),
|
||||
'message': MochiKit.Base.partial(MochiKit.Async.succeed, 'completeRegistration')
|
||||
});
|
||||
// deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'advanceProgress');
|
||||
deferredResult.addMethod(this.proxy(), 'registration');
|
||||
// deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'advanceProgress');
|
||||
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'updateCredentials': function (aUsername, aPassphrase, someUserData) {
|
||||
var deferredResult;
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("Connection.updateCredentials", {trace:false});
|
||||
deferredResult.collectResults({
|
||||
'credentials': [
|
||||
MochiKit.Base.method(this, 'normalizedCredentials', {username:aUsername, password:aPassphrase}),
|
||||
MochiKit.Base.bind(function(someCredentials) {
|
||||
var srpConnection;
|
||||
var result;
|
||||
|
||||
srpConnection = new Clipperz.Crypto.SRP.Connection({ C:someCredentials['username'], P:someCredentials['password'], hash:this.hash() });
|
||||
result = srpConnection.serverSideCredentials();
|
||||
result['version'] = Clipperz.PM.Connection.communicationProtocol.currentVersion;
|
||||
|
||||
return result;
|
||||
}, this)
|
||||
],
|
||||
'user': MochiKit.Base.partial(MochiKit.Async.succeed, someUserData)
|
||||
});
|
||||
// deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'advanceProgress');
|
||||
deferredResult.addMethod(this, 'message', 'upgradeUserCredentials');
|
||||
// deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'advanceProgress');
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'redeemOneTimePassword': function (someParameters) {
|
||||
/*
|
||||
//=========================================================================
|
||||
// LOGIN WITH PASSPHRASE, extracted from the TRUNK version (LoginPanel.js)
|
||||
deferredResult.addCallback(function(anUsername, aOneTimePassword) {
|
||||
var args;
|
||||
|
||||
args = {
|
||||
'message': 'oneTimePassword',
|
||||
'version': Clipperz.PM.Crypto.communicationProtocol.currentVersion,
|
||||
'parameters': {
|
||||
'oneTimePasswordKey': Clipperz.PM.DataModel.OneTimePassword.computeKeyWithUsernameAndPassword(anUsername, aOneTimePassword),
|
||||
'oneTimePasswordKeyChecksum': Clipperz.PM.DataModel.OneTimePassword.computeKeyChecksumWithUsernameAndPassword(anUsername, aOneTimePassword)
|
||||
}
|
||||
}
|
||||
|
||||
return args;
|
||||
}, anUsername, oneTimePassword);
|
||||
deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', 'OTP_login_loadingOTP');
|
||||
deferredResult.addCallback(MochiKit.Base.method(Clipperz.PM.Proxy.defaultProxy, 'handshake'));
|
||||
deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', 'OTP_login_extractingPassphrase');
|
||||
deferredResult.addCallback(function(aResult) {
|
||||
return Clipperz.PM.Crypto.deferredDecrypt(oneTimePassword, aResult['data'], aResult['version']);
|
||||
});
|
||||
deferredResult.addCallback(function(aResult) {
|
||||
return (new Clipperz.ByteArray().appendBase64String(aResult['passphrase'])).asString();
|
||||
});
|
||||
deferredResult.addMethod(this, 'doLoginWithUsernameAndPassphrase', anUsername),
|
||||
*/
|
||||
var args;
|
||||
var normalizedOTP;
|
||||
|
||||
normalizedOTP = Clipperz.PM.DataModel.OneTimePassword.normalizedOneTimePassword(someParameters['password']);
|
||||
|
||||
args = {
|
||||
'message': 'oneTimePassword',
|
||||
'version': Clipperz.PM.Connection.communicationProtocol.currentVersion,
|
||||
'parameters': {
|
||||
'oneTimePasswordKey': Clipperz.PM.DataModel.OneTimePassword.computeKeyWithUsernameAndPassword(someParameters['username'], normalizedOTP),
|
||||
'oneTimePasswordKeyChecksum': Clipperz.PM.DataModel.OneTimePassword.computeKeyChecksumWithUsernameAndPassword(someParameters['username'], normalizedOTP)
|
||||
}
|
||||
}
|
||||
|
||||
return Clipperz.Async.callbacks("Connction.redeemOTP", [
|
||||
MochiKit.Base.method(this.proxy(), 'handshake', args),
|
||||
function(aResult) {
|
||||
return Clipperz.PM.Crypto.deferredDecrypt({
|
||||
value: aResult['data'],
|
||||
key: normalizedOTP,
|
||||
version:aResult['version']
|
||||
});
|
||||
},
|
||||
function(aResult) {
|
||||
return (new Clipperz.ByteArray().appendBase64String(aResult['passphrase'])).asString();
|
||||
}
|
||||
], {trace:false})
|
||||
},
|
||||
|
||||
'login': function(isReconnecting) {
|
||||
var deferredResult;
|
||||
var cryptoVersion;
|
||||
var srpConnection;
|
||||
|
||||
cryptoVersion = this.clipperz_pm_crypto_version();
|
||||
deferredResult = new Clipperz.Async.Deferred("Connection.login", {trace:false});
|
||||
deferredResult.addCallback(this.getCredentialsFunction());
|
||||
deferredResult.addMethod(this, 'normalizedCredentials');
|
||||
// deferredResult.addCallbackPass(MochiKit.Signal.signal, this, 'updatedProgressState', 'connection_sendingCredentials');
|
||||
// deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'advanceProgress');
|
||||
deferredResult.addCallback(MochiKit.Base.bind(function(someCredentials) {
|
||||
srpConnection = new Clipperz.Crypto.SRP.Connection({ C:someCredentials['username'], P:someCredentials['password'], hash:this.hash() });
|
||||
}, this));
|
||||
deferredResult.addCallback(function() {
|
||||
var result;
|
||||
|
||||
result = {
|
||||
message: 'connect',
|
||||
version: cryptoVersion,
|
||||
parameters: {
|
||||
C: srpConnection.C(),
|
||||
A: srpConnection.A().asString(16)
|
||||
// reconnecting: this.connectionId()
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: ?????
|
||||
// if (isReconnecting == true) {
|
||||
// args.parameters['reconnecting'] = aConnection.connectionId();
|
||||
// }
|
||||
|
||||
return result;
|
||||
});
|
||||
deferredResult.addMethod(this.proxy(), 'handshake');
|
||||
// deferredResult.addCallbackPass(MochiKit.Signal.signal, this, 'updatedProgressState', 'connection_credentialVerification');
|
||||
// deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'advanceProgress');
|
||||
deferredResult.addCallback(function(someParameters) {
|
||||
var result;
|
||||
|
||||
srpConnection.set_s(new Clipperz.Crypto.BigInt(someParameters['s'], 16));
|
||||
srpConnection.set_B(new Clipperz.Crypto.BigInt(someParameters['B'], 16));
|
||||
|
||||
// TODO: ?????
|
||||
// if (typeof(someParameters['oneTimePassword']) != 'undefined') {
|
||||
// this.setOneTimePassword(someParameters['oneTimePassword']);
|
||||
// }
|
||||
|
||||
result = {
|
||||
message: 'credentialCheck',
|
||||
version: cryptoVersion,
|
||||
parameters: {
|
||||
M1: srpConnection.M1()
|
||||
}
|
||||
};
|
||||
|
||||
return result;
|
||||
});
|
||||
deferredResult.addMethod(this.proxy(), 'handshake');
|
||||
deferredResult.addCallback(function(someParameters) {
|
||||
var result;
|
||||
|
||||
if (someParameters['M2'] == srpConnection.M2()) {
|
||||
result = MochiKit.Async.succeed(someParameters);
|
||||
} else {
|
||||
result = MochiKit.Async.fail(Clipperz.PM.Connection.exception.WrongChecksum);
|
||||
}
|
||||
|
||||
return result;
|
||||
});
|
||||
deferredResult.addCallback(MochiKit.Base.bind(function(someParameters) {
|
||||
this.setConnectionId(someParameters['connectionId']);
|
||||
this.setSharedSecret(srpConnection.K());
|
||||
// TODO: ?????
|
||||
// if (this.oneTimePassword() != null) {
|
||||
/// ?? result = this.user().oneTimePasswordManager().archiveOneTimePassword(this.oneTimePassword()));
|
||||
// }
|
||||
|
||||
if ((isReconnecting == true) && (this.serverLockValue() != someParameters['lock'])) {
|
||||
throw Clipperz.PM.Connection.exception.StaleData;
|
||||
} else {
|
||||
this.setServerLockValue(someParameters['lock']);
|
||||
}
|
||||
|
||||
return someParameters;
|
||||
}, this));
|
||||
// deferredResult.addCallbackPass(MochiKit.Signal.signal, this, 'updatedProgressState', 'connection_loggedIn');
|
||||
// deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'advanceProgress');
|
||||
// deferredResult.addCallback(MochiKit.Async.succeed, {result:"done"});
|
||||
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'logout': function() {
|
||||
return Clipperz.Async.callbacks("Connection.logout", [
|
||||
MochiKit.Base.method(this, 'setSharedSecret'),
|
||||
MochiKit.Base.method(this.proxy(), 'logout', {})
|
||||
], {trace:false});
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'ping': function () {
|
||||
// TODO: ping the server in order to have a valid session
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'message': function(aMessageName, someParameters) {
|
||||
var args;
|
||||
var parameters;
|
||||
|
||||
parameters = someParameters || {};
|
||||
if (typeof(parameters['user']) != 'undefined') {
|
||||
parameters['user']['lock'] = this.serverLockValue();
|
||||
}
|
||||
|
||||
args = {
|
||||
message: aMessageName,
|
||||
srpSharedSecret: this.sharedSecret(),
|
||||
// parameters: (someParameters || {})
|
||||
parameters: parameters
|
||||
}
|
||||
|
||||
return this.sendMessage(args);
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'sendMessage': function(someArguments) {
|
||||
var deferredResult;
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("Connection.sendMessage", {trace:false});
|
||||
deferredResult.addMethod(this.proxy(), 'message', someArguments);
|
||||
deferredResult.addCallback(MochiKit.Base.bind(function(res) {
|
||||
if (typeof(res['lock']) != 'undefined') {
|
||||
this.setServerLockValue(res['lock']);
|
||||
}
|
||||
return res;
|
||||
}, this));
|
||||
|
||||
deferredResult.addErrback(MochiKit.Base.method(this, 'messageExceptionHandler'), someArguments);
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'messageExceptionHandler': function(anOriginalMessageArguments, anError) {
|
||||
var result;
|
||||
|
||||
Clipperz.log(">>> Connection.messageExceptionHandler: " + anError.message, anError);
|
||||
if (anError instanceof MochiKit.Async.CancelledError) {
|
||||
result = anError;
|
||||
} else {
|
||||
if ((anError.message == 'Trying to communicate without an active connection') ||
|
||||
(anError.message == 'No tollManager available for current session')
|
||||
) {
|
||||
result = this.reestablishConnection(anOriginalMessageArguments);
|
||||
} else if (anError.message == 'Session with stale data') {
|
||||
MochiKit.Signal.signal(this, 'EXCEPTION');
|
||||
} else {
|
||||
result = anError;
|
||||
}
|
||||
}
|
||||
Clipperz.log("<<< Connection.messageExceptionHandler")
|
||||
|
||||
return result;;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'reestablishConnection': function(anOriginalMessageArguments) {
|
||||
var deferredResult;
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("Connection.reestablishConnection");
|
||||
deferredResult.addMethod(this, 'reset');
|
||||
deferredResult.addMethod(this, 'login', true);
|
||||
deferredResult.addCallback(MochiKit.Base.bind(function(aMessage) {
|
||||
aMessage['srpSharedSecret'] = this.sharedSecret();
|
||||
return aMessage;
|
||||
}, this), anOriginalMessageArguments);
|
||||
deferredResult.addMethod(this, 'sendMessage');
|
||||
deferredResult.addErrback(MochiKit.Signal.signal, this, 'EXCEPTION', null);
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'serverSideUserCredentials': function(aUsername, aPassword) {
|
||||
var result;
|
||||
var newSrpConnection;
|
||||
var normalizedAttributes;
|
||||
|
||||
normalizedAttributes = this.normalizedCredentials({username:aUsername, password:aPassword});
|
||||
newSrpConnection = new Clipperz.Crypto.SRP.Connection({ C:normalizedAttributes['username'], P:normalizedAttributes['password'], hash:this.hash() });
|
||||
result = newSrpConnection.serverSideCredentials();
|
||||
result['version'] = this.clipperz_pm_crypto_version();
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'normalizedCredentials': function(someValues) {
|
||||
var result;
|
||||
|
||||
result = {}
|
||||
result['username'] = this.hash()(new Clipperz.ByteArray(someValues['username'])).toHexString().substring(2);
|
||||
result['password'] = this.hash()(new Clipperz.ByteArray(someValues['password'] + someValues['username'])).toHexString().substring(2);
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'hash': function() {
|
||||
return Clipperz.PM.Crypto.encryptingFunctions.versions['0.1'].hash;
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
__syntaxFix__: "syntax fix"
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// S R P [ 1 . 1 ] C O N N E C T I O N class
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
Clipperz.PM.Connection.SRP['1.1'] = function (args) {
|
||||
Clipperz.PM.Connection.SRP['1.0'].call(this, args);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
Clipperz.PM.Connection.SRP['1.1'].prototype = MochiKit.Base.update(new Clipperz.PM.Connection.SRP['1.0'](), {
|
||||
|
||||
'version': function() {
|
||||
return '1.1';
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'normalizedCredentials': function(someValues) {
|
||||
var result;
|
||||
|
||||
result = {}
|
||||
result['username'] = this.hash()(new Clipperz.ByteArray(someValues['username'] + someValues['password'])).toHexString().substring(2);
|
||||
result['password'] = this.hash()(new Clipperz.ByteArray(someValues['password'] + someValues['username'])).toHexString().substring(2);
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'hash': function() {
|
||||
return Clipperz.PM.Crypto.encryptingFunctions.versions['0.2'].hash;
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
__syntaxFix__: "syntax fix"
|
||||
|
||||
});
|
||||
|
||||
Clipperz.PM.Connection.exception = {
|
||||
WrongChecksum: new MochiKit.Base.NamedError("Clipperz.ByteArray.exception.InvalidValue"),
|
||||
StaleData: new MochiKit.Base.NamedError("Stale data"),
|
||||
UnexpectedRequest: new MochiKit.Base.NamedError("Clipperz.ByteArray.exception.UnexpectedRequest")
|
||||
};
|
||||
|
||||
|
||||
Clipperz.PM.Connection.communicationProtocol = {
|
||||
'currentVersion': '0.2',
|
||||
'versions': {
|
||||
'0.1': Clipperz.PM.Connection.SRP['1.0'], //Clipperz.Crypto.SRP.versions['1.0'].Connection,
|
||||
'0.2': Clipperz.PM.Connection.SRP['1.1'] //Clipperz.Crypto.SRP.versions['1.1'].Connection
|
||||
},
|
||||
'fallbackVersions': {
|
||||
// 'current': '0.1',
|
||||
'0.2': '0.1',
|
||||
'0.1': null
|
||||
}
|
||||
};
|
||||
|
||||
MochiKit.Base.update(Clipperz.PM.Connection.communicationProtocol.versions, {
|
||||
'current': Clipperz.PM.Connection.communicationProtocol.versions[Clipperz.PM.Connection.communicationProtocol.currentVersion]
|
||||
});
|
||||
|
||||
MochiKit.Base.update(Clipperz.PM.Connection.communicationProtocol.fallbackVersions, {
|
||||
'current': Clipperz.PM.Connection.communicationProtocol.fallbackVersions[Clipperz.PM.Connection.communicationProtocol.currentVersion]
|
||||
});
|
||||
|
||||
|
||||
|
||||
546
frontend/delta/js/Clipperz/PM/Crypto.js
Normal file
546
frontend/delta/js/Clipperz/PM/Crypto.js
Normal file
@@ -0,0 +1,546 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
|
||||
if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
|
||||
if (typeof(Clipperz.PM.Crypto) == 'undefined') { Clipperz.PM.Crypto = {}; }
|
||||
|
||||
Clipperz.PM.Crypto.VERSION = "0.2";
|
||||
Clipperz.PM.Crypto.NAME = "Clipperz.PM.Crypto";
|
||||
|
||||
Clipperz.PM.Crypto.encryptingFunctions = {};
|
||||
|
||||
MochiKit.Base.update(Clipperz.PM.Crypto, {
|
||||
|
||||
'__repr__': function () {
|
||||
return "[" + this.NAME + " " + this.VERSION + "]";
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'toString': function () {
|
||||
return this.__repr__();
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
'communicationProtocol': {
|
||||
'currentVersion': '0.2',
|
||||
'versions': {
|
||||
'0.1': Clipperz.PM.Connection.SRP['1.0'], //Clipperz.Crypto.SRP.versions['1.0'].Connection,
|
||||
'0.2': Clipperz.PM.Connection.SRP['1.1'] //Clipperz.Crypto.SRP.versions['1.1'].Connection
|
||||
},
|
||||
'fallbackVersions': {
|
||||
'current': '0.1',
|
||||
'0.2': '0.1',
|
||||
'0.1': null
|
||||
}
|
||||
},
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'encryptingFunctions': {
|
||||
'currentVersion': '0.4',
|
||||
'versions': {
|
||||
|
||||
//#####################################################################
|
||||
|
||||
'0.1': {
|
||||
'encrypt': function(aKey, aValue) {
|
||||
return Clipperz.Crypto.Base.encryptUsingSecretKey(aKey, Clipperz.Base.serializeJSON(aValue));
|
||||
},
|
||||
|
||||
'deferredEncrypt': function(aKey, aValue) {
|
||||
var deferredResult;
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("Crypto[0.1].deferredEncrypt");
|
||||
deferredResult.addCallback(Clipperz.PM.Crypto.encryptingFunctions.versions['0.1'].encrypt, aKey, aValue);
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
'decrypt': function(aKey, aValue) {
|
||||
var result;
|
||||
|
||||
if (aValue != null) {
|
||||
result = Clipperz.Base.evalJSON(Clipperz.Crypto.Base.decryptUsingSecretKey(aKey, aValue));
|
||||
} else {
|
||||
result = null;
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
'deferredDecrypt': function(aKey, aValue) {
|
||||
var deferredResult;
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("Crypto.[0.1].deferredDecrypt");
|
||||
deferredResult.addCallback(Clipperz.PM.Crypto.encryptingFunctions.versions['0.1'].decrypt, aKey, aValue);
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
'hash': function(aValue) {
|
||||
var result;
|
||||
var strngResult;
|
||||
|
||||
stringResult = Clipperz.Crypto.Base.computeHashValue(aValue.asString()); // !!!!!!!
|
||||
result = new Clipperz.ByteArray("0x" + stringResult);
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
'deriveKey': function(aStringValue) {
|
||||
return Clipperz.Crypto.Base.computeHashValue(aStringValue);
|
||||
}
|
||||
},
|
||||
|
||||
//#####################################################################
|
||||
|
||||
'0.2': {
|
||||
'encrypt': function(aKey, aValue, aNonce) {
|
||||
var result;
|
||||
var key, value;
|
||||
var dataToEncrypt;
|
||||
var encryptedData;
|
||||
|
||||
key = Clipperz.Crypto.SHA.sha_d256(new Clipperz.ByteArray(aKey));
|
||||
value = new Clipperz.ByteArray(Clipperz.Base.serializeJSON(aValue));
|
||||
dataToEncrypt = Clipperz.Crypto.SHA.sha_d256(value).appendBlock(value);
|
||||
encryptedData = Clipperz.Crypto.AES.encrypt(key, dataToEncrypt, aNonce);
|
||||
result = encryptedData.toBase64String();
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
'deferredEncrypt': function(aKey, aValue, aNonce) {
|
||||
var deferredResult;
|
||||
var key, value;
|
||||
var dataToEncrypt;
|
||||
// var encryptedData;
|
||||
|
||||
key = Clipperz.Crypto.SHA.sha_d256(new Clipperz.ByteArray(aKey));
|
||||
value = new Clipperz.ByteArray(Clipperz.Base.serializeJSON(aValue));
|
||||
dataToEncrypt = Clipperz.Crypto.SHA.sha_d256(value).appendBlock(value);
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("Crypto[0.2].deferredEncrypt")
|
||||
deferredResult.addCallback(Clipperz.Crypto.AES.deferredEncrypt, key, dataToEncrypt, aNonce);
|
||||
deferredResult.addCallback(function(aResult) {
|
||||
return aResult.toBase64String();
|
||||
})
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
'decrypt': function(aKey, aValue) {
|
||||
var result;
|
||||
|
||||
if (aValue != null) {
|
||||
var key, value;
|
||||
var decryptedData;
|
||||
var decryptedValue;
|
||||
|
||||
key = Clipperz.Crypto.SHA.sha_d256(new Clipperz.ByteArray(aKey));
|
||||
value = new Clipperz.ByteArray().appendBase64String(aValue);
|
||||
|
||||
decryptedData = Clipperz.Crypto.AES.decrypt(key, value);
|
||||
decryptedValue = decryptedData.split((256/8));
|
||||
|
||||
try {
|
||||
result = Clipperz.Base.evalJSON(decryptedValue.asString());
|
||||
} catch (exception) {
|
||||
Clipperz.logError("Error while decrypting data [1]");
|
||||
throw Clipperz.Crypto.Base.exception.CorruptedMessage;
|
||||
}
|
||||
} else {
|
||||
result = null;
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
'deferredDecrypt': function(aKey, aValue) {
|
||||
var result;
|
||||
|
||||
if (aValue != null) {
|
||||
var deferredResult;
|
||||
var key, value;
|
||||
// var decryptedData;
|
||||
|
||||
key = Clipperz.Crypto.SHA.sha_d256(new Clipperz.ByteArray(aKey));
|
||||
value = new Clipperz.ByteArray().appendBase64String(aValue);
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("Crypto.[0.2].deferredDecrypt");
|
||||
deferredResult.addCallback(Clipperz.Crypto.AES.deferredDecrypt, key, value);
|
||||
deferredResult.addCallback(function(aResult) {
|
||||
var result;
|
||||
var decryptedData;
|
||||
|
||||
decryptedData = aResult.split((256/8));
|
||||
|
||||
try {
|
||||
result = Clipperz.Base.evalJSON(decryptedData.asString());
|
||||
} catch (exception) {
|
||||
Clipperz.logError("Error while decrypting data [2]");
|
||||
throw Clipperz.Crypto.Base.exception.CorruptedMessage;
|
||||
}
|
||||
|
||||
return result;
|
||||
})
|
||||
deferredResult.callback();
|
||||
|
||||
result = deferredResult;
|
||||
} else {
|
||||
result = MochiKit.Async.succeed(null);
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
'hash': Clipperz.Crypto.SHA.sha_d256,
|
||||
|
||||
'deriveKey': function(aStringValue) {
|
||||
var byteData;
|
||||
var result;
|
||||
|
||||
byteData = new Clipperz.ByteArray(aStringValue);
|
||||
result = Clipperz.Crypto.SHA.sha_d256(byteData);
|
||||
|
||||
return result;
|
||||
}
|
||||
},
|
||||
|
||||
//#####################################################################
|
||||
|
||||
'0.3': {
|
||||
'encrypt': function(aKey, aValue, aNonce) {
|
||||
var result;
|
||||
var key, value;
|
||||
var data;
|
||||
var dataToEncrypt;
|
||||
var encryptedData;
|
||||
|
||||
key = Clipperz.Crypto.SHA.sha_d256(new Clipperz.ByteArray(aKey));
|
||||
value = Clipperz.Base.serializeJSON(aValue);
|
||||
data = new Clipperz.ByteArray(value);
|
||||
encryptedData = Clipperz.Crypto.AES.encrypt(key, data, aNonce);
|
||||
result = encryptedData.toBase64String();
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
'deferredEncrypt': function(aKey, aValue, aNonce) {
|
||||
var deferredResult;
|
||||
var key, value;
|
||||
var data;
|
||||
var dataToEncrypt;
|
||||
var encryptedData;
|
||||
|
||||
key = Clipperz.Crypto.SHA.sha_d256(new Clipperz.ByteArray(aKey));
|
||||
value = Clipperz.Base.serializeJSON(aValue);
|
||||
data = new Clipperz.ByteArray(value);
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("Crypto[0.3].deferredEncrypt")
|
||||
deferredResult.addCallback(Clipperz.Crypto.AES.deferredEncrypt, key, data, aNonce);
|
||||
deferredResult.addCallback(function(aResult) {
|
||||
return aResult.toBase64String();
|
||||
})
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
'decrypt': function(aKey, aValue) {
|
||||
var result;
|
||||
|
||||
if (aValue != null) {
|
||||
var key, value;
|
||||
var decryptedData;
|
||||
|
||||
key = Clipperz.Crypto.SHA.sha_d256(new Clipperz.ByteArray(aKey));
|
||||
value = new Clipperz.ByteArray().appendBase64String(aValue);
|
||||
|
||||
decryptedData = Clipperz.Crypto.AES.decrypt(key, value);
|
||||
|
||||
value = decryptedData.asString();
|
||||
try {
|
||||
result = Clipperz.Base.evalJSON(value);
|
||||
} catch (exception) {
|
||||
Clipperz.logError("Error while decrypting data [3]");
|
||||
throw Clipperz.Crypto.Base.exception.CorruptedMessage;
|
||||
}
|
||||
} else {
|
||||
result = null;
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
'deferredDecrypt': function(aKey, aValue) {
|
||||
var deferredResult;
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("Crypto[0.3].deferredDecrypt", {trace: false});
|
||||
// now = new Date;
|
||||
|
||||
if (aValue != null) {
|
||||
var key, value;
|
||||
// var decryptedData;
|
||||
|
||||
key = Clipperz.Crypto.SHA.sha_d256(new Clipperz.ByteArray(aKey));
|
||||
value = new Clipperz.ByteArray().appendBase64String(aValue);
|
||||
|
||||
deferredResult.addCallback(Clipperz.Crypto.AES.deferredDecrypt, key, value);
|
||||
deferredResult.addCallback(MochiKit.Async.wait, 0.1);
|
||||
deferredResult.addCallback(function(aResult) {
|
||||
return aResult.asString();
|
||||
});
|
||||
deferredResult.addCallback(MochiKit.Async.wait, 0.1);
|
||||
deferredResult.addCallback(Clipperz.Base.evalJSON);
|
||||
deferredResult.addErrback(function(anError) {
|
||||
console.log("PIPPO_1", anError)
|
||||
Clipperz.logError("Error while decrypting data [4]");
|
||||
throw Clipperz.Crypto.Base.exception.CorruptedMessage;
|
||||
})
|
||||
} else {
|
||||
deferredResult.addCallback(function() {
|
||||
return null;
|
||||
});
|
||||
}
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
'hash': Clipperz.Crypto.SHA.sha_d256,
|
||||
|
||||
'deriveKey': function(aStringValue) {
|
||||
var byteData;
|
||||
var result;
|
||||
|
||||
byteData = new Clipperz.ByteArray(aStringValue);
|
||||
result = Clipperz.Crypto.SHA.sha_d256(byteData);
|
||||
|
||||
return result;
|
||||
}
|
||||
},
|
||||
|
||||
//#####################################################################
|
||||
|
||||
'0.4': {
|
||||
'encrypt': function(aKey, aValue, aNonce) {
|
||||
var result;
|
||||
var key, value;
|
||||
var data;
|
||||
var dataToEncrypt;
|
||||
var encryptedData;
|
||||
|
||||
key = Clipperz.Crypto.SHA.sha_d256(new Clipperz.ByteArray(aKey));
|
||||
value = Clipperz.Base.serializeJSON(aValue);
|
||||
data = new Clipperz.ByteArray(value);
|
||||
encryptedData = Clipperz.Crypto.AES_2.encrypt(key, data, aNonce);
|
||||
result = encryptedData.toBase64String();
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
'deferredEncrypt': function(aKey, aValue, aNonce) {
|
||||
var deferredResult;
|
||||
var key, value;
|
||||
var data;
|
||||
var dataToEncrypt;
|
||||
var encryptedData;
|
||||
|
||||
key = Clipperz.Crypto.SHA.sha_d256(new Clipperz.ByteArray(aKey));
|
||||
value = Clipperz.Base.serializeJSON(aValue);
|
||||
data = new Clipperz.ByteArray(value);
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("Crypto[0.4].deferredEncrypt")
|
||||
deferredResult.addCallback(Clipperz.Crypto.AES_2.deferredEncrypt, key, data, aNonce);
|
||||
deferredResult.addCallback(function(aResult) {
|
||||
return aResult.toBase64String();
|
||||
})
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
'decrypt': function(aKey, aValue) {
|
||||
var result;
|
||||
|
||||
if (aValue != null) {
|
||||
var key, value;
|
||||
var decryptedData;
|
||||
|
||||
key = Clipperz.Crypto.SHA.sha_d256(new Clipperz.ByteArray(aKey));
|
||||
value = new Clipperz.ByteArray().appendBase64String(aValue);
|
||||
|
||||
decryptedData = Clipperz.Crypto.AES_2.decrypt(key, value);
|
||||
|
||||
value = decryptedData.asString();
|
||||
try {
|
||||
result = Clipperz.Base.evalJSON(value);
|
||||
} catch (exception) {
|
||||
console.log("PIPPO_2", anError)
|
||||
Clipperz.logError("Error while decrypting data [4]");
|
||||
throw Clipperz.Crypto.Base.exception.CorruptedMessage;
|
||||
}
|
||||
} else {
|
||||
result = null;
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
'deferredDecrypt': function(aKey, aValue) {
|
||||
var deferredResult;
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("Crypto[0.4].deferredDecrypt", {trace: false});
|
||||
|
||||
if (aValue != null) {
|
||||
var key, value;
|
||||
|
||||
key = Clipperz.Crypto.SHA.sha_d256(new Clipperz.ByteArray(aKey));
|
||||
value = new Clipperz.ByteArray().appendBase64String(aValue);
|
||||
|
||||
deferredResult.addCallback(Clipperz.Crypto.AES_2.deferredDecrypt, key, value);
|
||||
deferredResult.addCallback(MochiKit.Async.wait, 0.1);
|
||||
deferredResult.addCallback(function(aResult) {
|
||||
return aResult.asString();
|
||||
});
|
||||
deferredResult.addCallback(MochiKit.Async.wait, 0.1);
|
||||
deferredResult.addCallback(Clipperz.Base.evalJSON);
|
||||
deferredResult.addErrback(function(anError) {
|
||||
Clipperz.logError("Error while decrypting data [4]");
|
||||
throw Clipperz.Crypto.Base.exception.CorruptedMessage;
|
||||
})
|
||||
} else {
|
||||
deferredResult.addCallback(function() {
|
||||
return null;
|
||||
});
|
||||
}
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
'hash': Clipperz.Crypto.SHA.sha_d256,
|
||||
|
||||
'deriveKey': function(aStringValue) {
|
||||
var byteData;
|
||||
var result;
|
||||
|
||||
byteData = new Clipperz.ByteArray(aStringValue);
|
||||
result = Clipperz.Crypto.SHA.sha_d256(byteData);
|
||||
|
||||
return result;
|
||||
}
|
||||
},
|
||||
|
||||
//#####################################################################
|
||||
__syntaxFix__: "syntax fix"
|
||||
}
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'encrypt': function(aKey, aValue, aVersion) {
|
||||
return Clipperz.PM.Crypto.encryptingFunctions.versions[aVersion].encrypt(aKey, aValue);
|
||||
},
|
||||
|
||||
'deferredEncrypt': function(someParameters) {
|
||||
return Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters['version']].deferredEncrypt(someParameters['key'], someParameters['value']);
|
||||
},
|
||||
|
||||
//.........................................................................
|
||||
|
||||
'decrypt': function(aKey, aValue, aVersion) {
|
||||
return Clipperz.PM.Crypto.encryptingFunctions.versions[aVersion].decrypt(aKey, aValue);
|
||||
},
|
||||
|
||||
'deferredDecrypt': function(someParameters) {
|
||||
return Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters['version']].deferredDecrypt(someParameters['key'], someParameters['value']);
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'hash': function(aValue) {
|
||||
return Clipperz.PM.Crypto.encryptingFunctions.versions[Clipperz.PM.Crypto.encryptingFunctions.currentVersion]['hash'](aValue);
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'randomKey': function() {
|
||||
return Clipperz.Crypto.PRNG.defaultRandomGenerator().getRandomBytes(32).toHexString().substring(2);
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'deriveKey': function(aValue) {
|
||||
return Clipperz.PM.Crypto.encryptingFunctions.versions[Clipperz.PM.Crypto.encryptingFunctions.currentVersion].deriveKey(aValue);
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'passwordEntropy': function(aValue) {
|
||||
var result;
|
||||
var bitPerChar;
|
||||
|
||||
bitPerChar = 4;
|
||||
if (/[a-z]/.test(aValue)) {
|
||||
bitPerChar ++;
|
||||
}
|
||||
if (/[A-Z]/.test(aValue)) {
|
||||
bitPerChar ++;
|
||||
}
|
||||
if (/[^a-zA-Z0-9]/.test(aValue)) {
|
||||
bitPerChar ++;
|
||||
}
|
||||
|
||||
result = aValue.length * bitPerChar;
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'nullValue': '####',
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
__syntaxFix__: "syntax fix"
|
||||
|
||||
});
|
||||
|
||||
//*****************************************************************************
|
||||
|
||||
//MochiKit.Base.update(Clipperz.PM.Connection.communicationProtocol.versions, {
|
||||
// 'current': Clipperz.PM.Connection.communicationProtocol.versions[Clipperz.PM.Connection.communicationProtocol.currentVersion]
|
||||
//});
|
||||
|
||||
MochiKit.Base.update(Clipperz.PM.Crypto.encryptingFunctions.versions, {
|
||||
'current': Clipperz.PM.Crypto.encryptingFunctions.versions[Clipperz.PM.Crypto.encryptingFunctions.currentVersion]
|
||||
});
|
||||
|
||||
//*****************************************************************************
|
||||
1086
frontend/delta/js/Clipperz/PM/DataModel/DirectLogin.js
Normal file
1086
frontend/delta/js/Clipperz/PM/DataModel/DirectLogin.js
Normal file
File diff suppressed because it is too large
Load Diff
120
frontend/delta/js/Clipperz/PM/DataModel/DirectLoginBinding.js
Normal file
120
frontend/delta/js/Clipperz/PM/DataModel/DirectLoginBinding.js
Normal file
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
|
||||
if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
|
||||
if (typeof(Clipperz.PM.DataModel) == 'undefined') { Clipperz.PM.DataModel = {}; }
|
||||
|
||||
|
||||
//#############################################################################
|
||||
|
||||
Clipperz.PM.DataModel.DirectLoginBinding = function(aDirectLogin, args) {
|
||||
args = args || {};
|
||||
|
||||
this._directLogin = aDirectLogin|| Clipperz.Base.exception.raise('MandatoryParameter');
|
||||
|
||||
this._key = args.key || Clipperz.Base.exception.raise('MandatoryParameter');
|
||||
this._fieldKey = args.field || /* this.directLogin().fieldWithName(args.fieldName).reference() || */ null;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
Clipperz.PM.DataModel.DirectLoginBinding.prototype = MochiKit.Base.update(null, {
|
||||
|
||||
'toString': function() {
|
||||
return "DirectLoginBinding (" + this.key() + ", " + this.fieldKey() + ")";
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'directLogin': function () {
|
||||
return this._directLogin;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'key': function() {
|
||||
return this._key;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'fieldKey': function() {
|
||||
return this._fieldKey;
|
||||
},
|
||||
|
||||
'setFieldKey': function(aValue) {
|
||||
this._fieldKey = aValue;
|
||||
|
||||
return this.directLogin().setValue('bindingData' + '.' + this.key(), aValue);
|
||||
},
|
||||
|
||||
// 'fieldName': function() {
|
||||
// return this._fieldName;
|
||||
// },
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'field': function() {
|
||||
var deferredResult;
|
||||
|
||||
if (this.fieldKey() != null) {
|
||||
deferredResult = Clipperz.Async.callbacks("DirectLoginBinding.field [1]", [
|
||||
MochiKit.Base.method(this.directLogin().record(), 'fields'),
|
||||
MochiKit.Base.itemgetter(this.fieldKey())
|
||||
], {trace:false});
|
||||
// } else if (this.fieldName() != null) {
|
||||
// WTF = TODO;
|
||||
// result = this.directLogin().record().fieldWithName(this.fieldName());
|
||||
//
|
||||
// this.setFieldKey(result.key());
|
||||
} else {
|
||||
deferredResult = MochiKit.Async.succeed(null);
|
||||
}
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
'setField': function (aField) {
|
||||
this.setFieldKey(aField.reference());
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
'fieldValue': function () {
|
||||
return Clipperz.Async.callbacks("DirectLoginBinding.fieldValue", [
|
||||
MochiKit.Base.method('field'),
|
||||
MochiKit.Base.methodcaller('value')
|
||||
], {trace:false});
|
||||
},
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'serializedData': function() {
|
||||
return this.fieldKey();
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
__syntaxFix__: "syntax fix"
|
||||
});
|
||||
|
||||
101
frontend/delta/js/Clipperz/PM/DataModel/DirectLoginFormValue.js
Normal file
101
frontend/delta/js/Clipperz/PM/DataModel/DirectLoginFormValue.js
Normal file
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
|
||||
if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
|
||||
if (typeof(Clipperz.PM.DataModel) == 'undefined') { Clipperz.PM.DataModel = {}; }
|
||||
|
||||
|
||||
//#############################################################################
|
||||
|
||||
Clipperz.PM.DataModel.DirectLoginFormValue = function(aDirectLogin, args) {
|
||||
args = args || {};
|
||||
|
||||
this._directLogin = aDirectLogin|| Clipperz.Base.exception.raise('MandatoryParameter');
|
||||
|
||||
this._key = args.key || Clipperz.Base.exception.raise('MandatoryParameter');
|
||||
this._fieldOptions = args.fieldOptions || Clipperz.Base.exception.raise('MandatoryParameter');
|
||||
this._value = args.value || null;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
Clipperz.PM.DataModel.DirectLoginFormValue.prototype = MochiKit.Base.update(null, {
|
||||
|
||||
'toString': function() {
|
||||
return "DirectLoginFormValue (" + this.key() + ", " + this.value() + ")";
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'directLogin': function () {
|
||||
return this._directLogin;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'key': function() {
|
||||
return this._key;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'fieldOptions': function() {
|
||||
return this._fieldOptions;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'type': function () {
|
||||
return this.fieldOptions()['type'];
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'value': function() {
|
||||
var result;
|
||||
|
||||
result = this._value;
|
||||
|
||||
// if ((result == null) && (this.type() == 'checkbox')) {
|
||||
// result = false;
|
||||
// };
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
'setValue': function (aValue) {
|
||||
this._value = aValue;
|
||||
return this.directLogin().setValue('formValues' + '.' + this.key(), aValue);
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
'serializedData': function() {
|
||||
return this.value();
|
||||
},
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
__syntaxFix__: "syntax fix"
|
||||
});
|
||||
|
||||
192
frontend/delta/js/Clipperz/PM/DataModel/DirectLoginInput.js
Normal file
192
frontend/delta/js/Clipperz/PM/DataModel/DirectLoginInput.js
Normal file
@@ -0,0 +1,192 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
|
||||
if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
|
||||
if (typeof(Clipperz.PM.DataModel) == 'undefined') { Clipperz.PM.DataModel = {}; }
|
||||
|
||||
//#############################################################################
|
||||
|
||||
Clipperz.PM.DataModel.DirectLoginInput = function(args) {
|
||||
this._args = args;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
Clipperz.PM.DataModel.DirectLoginInput.prototype = MochiKit.Base.update(null, {
|
||||
|
||||
'args': function() {
|
||||
return this._args;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'name': function() {
|
||||
return this.args()['name'];
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'type': function() {
|
||||
var result;
|
||||
|
||||
result = this.args()['type'];
|
||||
|
||||
if (result != null) {
|
||||
result = result.toLowerCase();
|
||||
}
|
||||
return result;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'options': function() {
|
||||
return this.args()['options'];
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'value': function() {
|
||||
return this.args()['value'];
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
'formConfiguration': function(someFormValues, someBindings, someFields) {
|
||||
var result;
|
||||
|
||||
if (this.shouldSetValue()) {
|
||||
switch (this.type()) {
|
||||
case 'select':
|
||||
var currentValue;
|
||||
var options;
|
||||
|
||||
// currentValue = this.directLogin()._configuration['formValues'][this.name()];
|
||||
currentValue = someFormValues[this.name()];
|
||||
options = this.args()['options'];
|
||||
|
||||
result = MochiKit.DOM.SELECT({name:this.name()},
|
||||
MochiKit.Base.map(function(anOption) {
|
||||
var options;
|
||||
|
||||
options = {value:anOption['value']};
|
||||
if (currentValue == anOption['value']) {
|
||||
options.selected = true;
|
||||
}
|
||||
|
||||
return MochiKit.DOM.OPTION(options, anOption['label'])
|
||||
}, options)
|
||||
)
|
||||
break;
|
||||
case 'checkbox':
|
||||
var options;
|
||||
|
||||
options = {type:'checkbox', name: this.name()};
|
||||
// if (this.directLogin()._configuration['formValues'][this.name()] == true) {
|
||||
if (someFormValues[this.name()] == true) {
|
||||
options['checked'] = true;
|
||||
};
|
||||
|
||||
result = MochiKit.DOM.INPUT(options, null);
|
||||
break;
|
||||
case 'radio':
|
||||
var currentName;
|
||||
var currentValue;
|
||||
var options;
|
||||
|
||||
currentName = this.name();
|
||||
// currentValue = this.directLogin()._configuration['formValues'][this.name()];
|
||||
currentValue = someFormValues[this.name()];
|
||||
options = this.args()['options'];
|
||||
|
||||
result = MochiKit.DOM.DIV(null,
|
||||
MochiKit.Base.map(function(anOption) {
|
||||
var options;
|
||||
var isChecked;
|
||||
var inputNode;
|
||||
var divNode;
|
||||
|
||||
options = {type:'radio', name:currentName, value:anOption['value']}
|
||||
isChecked = (currentValue == anOption['value']);
|
||||
if (isChecked) {
|
||||
options.checked = true;
|
||||
}
|
||||
|
||||
if (Clipperz_IEisBroken == true) {
|
||||
var checkedValue;
|
||||
|
||||
checkedValue = (isChecked ? " CHECKED" : "");
|
||||
inputNode = MochiKit.DOM.currentDocument().createElement("<INPUT TYPE='RADIO' NAME='" + currentName + "' VALUE='" + anOption['value'] + "'" + checkedValue + ">");
|
||||
} else {
|
||||
inputNode = MochiKit.DOM.INPUT(options, anOption['value']);
|
||||
}
|
||||
divNode = MochiKit.DOM.DIV(null, inputNode);
|
||||
|
||||
return divNode;
|
||||
}, options)
|
||||
);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
var binding;
|
||||
// binding = this.directLogin().bindings()[this.name()];
|
||||
binding = someBindings[this.name()];
|
||||
|
||||
result = MochiKit.DOM.INPUT({
|
||||
type:((this.type() != 'password') ? this.type() : 'text'),
|
||||
name:this.name(),
|
||||
// value:((binding != null)? binding.field().value() : this.value())
|
||||
value:((binding != null)? someFields[binding.fieldKey()]['value'] : this.value())
|
||||
// value:((binding != null)? someFields[binding.fieldKey()].value() : this.value())
|
||||
}, null);
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'needsFormValue': function() {
|
||||
var type;
|
||||
var result;
|
||||
|
||||
type = this.type();
|
||||
result = ((type == 'checkbox') || (type == 'radio') || (type == 'select'));
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
'needsBinding': function() {
|
||||
var type;
|
||||
var result;
|
||||
|
||||
type = this.type();
|
||||
result = ((type == 'text') || (type == 'password'));
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
__syntaxFix__: "syntax fix"
|
||||
});
|
||||
|
||||
542
frontend/delta/js/Clipperz/PM/DataModel/EncryptedRemoteObject.js
Normal file
542
frontend/delta/js/Clipperz/PM/DataModel/EncryptedRemoteObject.js
Normal file
@@ -0,0 +1,542 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
try { if (typeof(Clipperz.KeyValueObjectStore) == 'undefined') { throw ""; }} catch (e) {
|
||||
throw "Clipperz.PM.DataModel.EncryptedRemoteObject depends on Clipperz.KeyValueObjectStore!";
|
||||
}
|
||||
|
||||
if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
|
||||
if (typeof(Clipperz.PM.DataModel) == 'undefined') { Clipperz.PM.DataModel = {}; }
|
||||
|
||||
Clipperz.PM.DataModel.EncryptedRemoteObject = function(args) {
|
||||
args = args || {};
|
||||
|
||||
this._name = args.name || null;
|
||||
this._reference = args.reference || Clipperz.PM.Crypto.randomKey();
|
||||
this._isBrandNew = ((args.reference == null) && (args.remoteData == null));
|
||||
|
||||
if ((this._isBrandNew == false) && (args['retrieveKeyFunction'] == null)) {
|
||||
Clipperz.Base.exception.raise('MandatoryParameter');
|
||||
} else {
|
||||
this._retrieveKeyFunction = args['retrieveKeyFunction'];
|
||||
}
|
||||
|
||||
this._retrieveRemoteDataFunction = args.retrieveRemoteDataFunction || null;
|
||||
this._remoteData = args.remoteData || null;
|
||||
// this._remoteData = args.remoteData ? Clipperz.Base.deepClone(args.remoteData) : null;
|
||||
if ((!this._isBrandNew) && ((this._retrieveRemoteDataFunction == null) && (this._remoteData == null))) {
|
||||
Clipperz.Base.exception.raise('MandatoryParameter');
|
||||
}
|
||||
|
||||
|
||||
this._encryptedDataKeypath = args.encryptedDataKeypath || 'data'; //Clipperz.Base.exception.raise('MandatoryParameter');
|
||||
this._encryptedVersionKeypath = args.encryptedVersionKeypath || 'version'; //Clipperz.Base.exception.raise('MandatoryParameter');
|
||||
|
||||
|
||||
this._transientState = null;
|
||||
this._deferredLocks = {};
|
||||
|
||||
if (this._isBrandNew == true) {
|
||||
this._objectDataStore = new Clipperz.KeyValueObjectStore(/*{'name':'EncryptedRemoteObject.objectDataStore [1]'}*/);
|
||||
} else {
|
||||
this._objectDataStore = null;
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
//
|
||||
// Basic data workflow
|
||||
// =======================
|
||||
//
|
||||
// getRemoteData
|
||||
// unpackRemoteData
|
||||
// getDecryptData [encryptedDataKeypath, encryptedVersionKeypath]
|
||||
// unpackData
|
||||
//
|
||||
//
|
||||
// ?? packData
|
||||
// ?? encryptDataWithKey
|
||||
// ?? packRemoteData [encryptedDataKeypath (?), encryptedVersionKeypath (?)]
|
||||
//
|
||||
|
||||
Clipperz.PM.DataModel.EncryptedRemoteObject.prototype = MochiKit.Base.update(null, {
|
||||
|
||||
'toString': function () {
|
||||
return "Clipperz.PM.DataModel.EncryptedRemoteObject" + (this.name() != null ? " - " + this.name() : "");
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'name': function () {
|
||||
return this._name;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'reference': function () {
|
||||
return this._reference;
|
||||
},
|
||||
|
||||
'setReference': function (aValue) {
|
||||
this._reference = aValue;
|
||||
|
||||
return this._reference;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'transientState': function () {
|
||||
if (this._transientState == null) {
|
||||
this._transientState = new Clipperz.KeyValueObjectStore(/*{'name':'EncryptedRemoteObject.transientState [2]'}*/);
|
||||
}
|
||||
|
||||
return this._transientState;
|
||||
},
|
||||
|
||||
'resetTransientState': function (isCommitting) {
|
||||
if (this._transientState != null) {
|
||||
this._transientState.removeAllData();
|
||||
}
|
||||
|
||||
this._transientState = null;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'isBrandNew': function () {
|
||||
return this._isBrandNew;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'getKey': function () {
|
||||
var deferredResult;
|
||||
var deferredLock;
|
||||
|
||||
deferredLock = this.getDeferredLockForKey('key');
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("EncryptedRemoteObject.getKey", {trace:false});
|
||||
deferredResult.acquireLock(deferredLock);
|
||||
deferredResult.addMethod(
|
||||
this.decryptedDataStore(),
|
||||
'deferredGetOrSet',
|
||||
'decryptionKey',
|
||||
MochiKit.Base.partial(this.retrieveKeyFunction(), this.reference())
|
||||
);
|
||||
deferredResult.releaseLock(deferredLock);
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||
|
||||
'retrieveKeyFunction': function () {
|
||||
return this._retrieveKeyFunction;
|
||||
},
|
||||
|
||||
'setRetrieveKeyFunction': function (aFunction) {
|
||||
this._retrieveKeyFunction = aFunction;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'hasLoadedRemoteData': function () {
|
||||
return (this._remoteData != null);
|
||||
},
|
||||
|
||||
'getRemoteData': function () {
|
||||
var deferredResult;
|
||||
var deferredLock;
|
||||
|
||||
deferredLock = this.getDeferredLockForKey('remoteData');
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("EncryptedRemoteObjects.getRemoteData", {trace:false});
|
||||
deferredResult.acquireLock(deferredLock);
|
||||
deferredResult.addCallback(MochiKit.Base.bind(function () {
|
||||
var innerDeferredResult;
|
||||
|
||||
if (this._remoteData != null) {
|
||||
innerDeferredResult = MochiKit.Async.succeed(this._remoteData);
|
||||
} else {
|
||||
innerDeferredResult = Clipperz.Async.callbacks("EncryptedRemoteObjects.getRemoteData <inner deferred>", [
|
||||
MochiKit.Base.partial(this.retrieveRemoteDataFunction(), this.reference()),
|
||||
MochiKit.Base.method(this, 'unpackRemoteData'),
|
||||
MochiKit.Base.bind(function (someData) {
|
||||
this._remoteData = someData;
|
||||
return this._remoteData;
|
||||
}, this)
|
||||
], {trace:false});
|
||||
}
|
||||
|
||||
return innerDeferredResult;
|
||||
}, this))
|
||||
deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'advanceProgress');
|
||||
deferredResult.releaseLock(deferredLock);
|
||||
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'unpackRemoteData': function (someData) {
|
||||
return MochiKit.Async.succeed(someData);
|
||||
},
|
||||
|
||||
//.........................................................................
|
||||
|
||||
'packRemoteData': function (someData) {
|
||||
var result;
|
||||
|
||||
result = {
|
||||
'reference': this.reference(),
|
||||
'data': someData,
|
||||
'version': Clipperz.PM.Crypto.encryptingFunctions.currentVersion
|
||||
};
|
||||
|
||||
return MochiKit.Async.succeed(result);
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'retrieveRemoteDataFunction': function () {
|
||||
return this._retrieveRemoteDataFunction;
|
||||
},
|
||||
|
||||
'setRetrieveRemoteDataFunction': function (aFunction) {
|
||||
this._retrieveRemoteDataFunction = aFunction;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'decryptedDataStore': function () {
|
||||
if (this._decryptedDataStore == null) {
|
||||
this._decryptedDataStore = new Clipperz.KeyValueObjectStore(/*{'name':'EncryptedRemoteObject.decryptedDataStore [3]'}*/);
|
||||
};
|
||||
|
||||
return this._decryptedDataStore;
|
||||
},
|
||||
|
||||
//.........................................................................
|
||||
|
||||
'getDecryptedData': function () {
|
||||
var deferredResult;
|
||||
var deferredLock;
|
||||
|
||||
deferredLock = this.getDeferredLockForKey('decryptedData');
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("EncryptedRemoteObject.getDecryptedData", {trace:false});
|
||||
deferredResult.acquireLock(deferredLock);
|
||||
deferredResult.addMethod(this, 'decryptedDataStore');
|
||||
deferredResult.addCallback(MochiKit.Base.methodcaller('deferredGetOrSet', 'decryptedData', MochiKit.Base.bind(function () {
|
||||
var innerDeferredResult;
|
||||
|
||||
innerDeferredResult = new Clipperz.Async.Deferred("EncryptedRemoteObject.getDecryptedData <inner deferred>", {trace:false});
|
||||
|
||||
innerDeferredResult.addMethod(this, 'getRemoteData');
|
||||
innerDeferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'advanceProgress');
|
||||
innerDeferredResult.collectResults({
|
||||
'key': MochiKit.Base.method(this, 'getKey'),
|
||||
'value': MochiKit.Base.itemgetter(this._encryptedDataKeypath),
|
||||
'version': MochiKit.Base.itemgetter(this._encryptedVersionKeypath)
|
||||
});
|
||||
|
||||
innerDeferredResult.addCallback(Clipperz.PM.Crypto.deferredDecrypt);
|
||||
innerDeferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'advanceProgress');
|
||||
innerDeferredResult.addMethod(this, 'unpackData');
|
||||
innerDeferredResult.callback();
|
||||
|
||||
return innerDeferredResult;
|
||||
}, this)));
|
||||
deferredResult.releaseLock(deferredLock);
|
||||
deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'advanceProgress');
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'setValue': function(aKey, aValue) {
|
||||
var deferredResult;
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("EncryptedRemoteObject.setValue", {trace:false});
|
||||
deferredResult.addMethod(this, '_getObjectDataStore');
|
||||
deferredResult.addCallback(MochiKit.Base.methodcaller('setValue', aKey, aValue));
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//.........................................................................
|
||||
|
||||
'getValue': function (aKey) {
|
||||
return Clipperz.Async.callbacks("EncryptedRemoteObject.getValue", [
|
||||
MochiKit.Base.method(this, '_getObjectDataStore'),
|
||||
MochiKit.Base.methodcaller('getValue', aKey)
|
||||
], {trace:false});
|
||||
},
|
||||
|
||||
//.........................................................................
|
||||
|
||||
'removeValue': function (aKey) {
|
||||
return Clipperz.Async.callbacks("EncryptedRemoteObject.removeValue", [
|
||||
MochiKit.Base.method(this, '_getObjectDataStore'),
|
||||
MochiKit.Base.methodcaller('removeValue', aKey)
|
||||
], {trace:false});
|
||||
},
|
||||
|
||||
//.........................................................................
|
||||
|
||||
'values': function () {
|
||||
return Clipperz.Async.callbacks("EncryptedRemoteObject.values", [
|
||||
MochiKit.Base.method(this, '_getObjectDataStore'),
|
||||
MochiKit.Base.methodcaller('values')
|
||||
], {trace:false});
|
||||
},
|
||||
|
||||
'setValues': function (someValues) {
|
||||
return Clipperz.Async.callbacks("EncryptedRemoteObject.values", [
|
||||
MochiKit.Base.method(this, '_getObjectDataStore'),
|
||||
MochiKit.Base.methodcaller('setValues', someValues)
|
||||
], {trace:false});
|
||||
},
|
||||
|
||||
//.........................................................................
|
||||
|
||||
'_getObjectDataStore': function () {
|
||||
var deferredResult;
|
||||
var deferredLock;
|
||||
|
||||
deferredLock = this.getDeferredLockForKey('objectDataStore');
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("EncryptedRemoteObject._getObjectDataStore", {trace:false});
|
||||
deferredResult.acquireLock(deferredLock);
|
||||
deferredResult.addCallback(MochiKit.Base.bind(function () {
|
||||
var innerDeferredResult;
|
||||
|
||||
if (this._objectDataStore == null) {
|
||||
this._objectDataStore = new Clipperz.KeyValueObjectStore(/*{'name':'EncryptedRemoteObject.objectDataStore [4]'}*/);
|
||||
|
||||
innerDeferredResult = new Clipperz.Async.Deferred("EncryptedRemoteObject._getObjectDataStore <inner deferred>", {trace:false});
|
||||
innerDeferredResult.addMethod(this, 'getDecryptedData');
|
||||
innerDeferredResult.addMethod(this._objectDataStore, 'initWithValues');
|
||||
innerDeferredResult.callback();
|
||||
} else {
|
||||
innerDeferredResult = MochiKit.Async.succeed(this._objectDataStore);
|
||||
}
|
||||
|
||||
return innerDeferredResult;
|
||||
}, this));
|
||||
deferredResult.releaseLock(deferredLock);
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
'hasInitiatedObjectDataStore': function () {
|
||||
return (this._objectDataStore != null);
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'getDeferredLockForKey': function (aKey) {
|
||||
var result;
|
||||
|
||||
result = this._deferredLocks[aKey];
|
||||
|
||||
if (typeof(result) == 'undefined') {
|
||||
result = new MochiKit.Async.DeferredLock();
|
||||
this._deferredLocks[aKey] = result;
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'unpackData': function (someData) { // ++
|
||||
return someData;
|
||||
},
|
||||
|
||||
'packData': function (someData) { // ++
|
||||
return someData;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'hasPendingChanges': function () {
|
||||
var deferredResult;
|
||||
var tempObj = this;
|
||||
|
||||
if (this.isBrandNew()) {
|
||||
// deferredResult = MochiKit.Async.succeed(true);
|
||||
deferredResult = this.hasPendingChangesWhenBrandNew();
|
||||
} else if (this.hasInitiatedObjectDataStore()) {
|
||||
deferredResult = new Clipperz.Async.Deferred("EncryptedRemoteObject.hasPendingChanges", {trace:false});
|
||||
deferredResult.collectResults({
|
||||
'decryptedData': [
|
||||
MochiKit.Base.method(this, 'getDecryptedData'),
|
||||
Clipperz.Base.serializeJSON
|
||||
],
|
||||
'objectData': [
|
||||
MochiKit.Base.method(this, '_getObjectDataStore'),
|
||||
MochiKit.Base.methodcaller('values'),
|
||||
Clipperz.Base.serializeJSON
|
||||
]
|
||||
});
|
||||
deferredResult.addCallback(function (someValues) {
|
||||
return (someValues['decryptedData'] != someValues['objectData']);
|
||||
});
|
||||
deferredResult.callback();
|
||||
} else {
|
||||
deferredResult = MochiKit.Async.succeed(false);
|
||||
}
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
'hasPendingChangesWhenBrandNew': function () {
|
||||
return MochiKit.Async.succeed(true);
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'commitTransientState': function () {
|
||||
var deferredResult;
|
||||
|
||||
// if (this.transientState().getValue('__prepareRemoteData') == true) {
|
||||
if (this.transientState().getValue('packedRemoteData') != null) {
|
||||
deferredResult = Clipperz.Async.callbacks("EncryptedRemoteObject.commitTransientState - prepareRemoteData", [
|
||||
MochiKit.Base.bind(function (someData) {
|
||||
this._remoteData = this.transientState().getValue('packedRemoteData');
|
||||
}, this),
|
||||
|
||||
MochiKit.Base.method(this, '_getObjectDataStore'),
|
||||
MochiKit.Base.methodcaller('values'),
|
||||
Clipperz.Base.deepClone,
|
||||
MochiKit.Base.method(this.decryptedDataStore(), 'setValue', 'decryptedData'),
|
||||
|
||||
MochiKit.Base.method(this, 'resetTransientState', true)
|
||||
], {trace:false});
|
||||
|
||||
} else {
|
||||
deferredResult = Clipperz.Async.callbacks("EncryptedRemoteObject.commitTransientState - NO prepareRemoteData", [
|
||||
MochiKit.Base.method(this, 'resetTransientState', true)
|
||||
], {trace:false});
|
||||
}
|
||||
|
||||
this._isBrandNew = false;
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'revertChanges': function () {
|
||||
if (this.hasInitiatedObjectDataStore()) {
|
||||
this._objectDataStore.removeAllData();
|
||||
this._objectDataStore = null;
|
||||
}
|
||||
this.resetTransientState(false);
|
||||
|
||||
return MochiKit.Async.succeed();
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'deleteAllCleanTextData': function () {
|
||||
var deferredResult;
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("EncryptedRemoteObject.deleteAllCleanTextData", {trace:false});
|
||||
|
||||
deferredResult.addMethod(this, 'resetTransientState', false);
|
||||
|
||||
deferredResult.acquireLock(this.getDeferredLockForKey('decryptedData'));
|
||||
deferredResult.addCallback(MochiKit.Base.bind(function () {
|
||||
if (this._decryptedDataStore != null) {
|
||||
this._decryptedDataStore.removeAllData();
|
||||
}
|
||||
}, this));
|
||||
deferredResult.releaseLock(this.getDeferredLockForKey('decryptedData'));
|
||||
|
||||
deferredResult.acquireLock(this.getDeferredLockForKey('objectDataStore'));
|
||||
deferredResult.addCallback(MochiKit.Base.bind(function () {
|
||||
if (this._objectDataStore != null) {
|
||||
this._objectDataStore.removeAllData();
|
||||
this._objectDataStore = null;
|
||||
}
|
||||
}, this));
|
||||
deferredResult.releaseLock(this.getDeferredLockForKey('objectDataStore'));
|
||||
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//.........................................................................
|
||||
|
||||
'hasAnyCleanTextData': function () {
|
||||
var result;
|
||||
|
||||
result = false;
|
||||
|
||||
result = result || (! this.decryptedDataStore().isEmpty());
|
||||
result = result || (! this.transientState().isEmpty());
|
||||
if (this.hasInitiatedObjectDataStore()) {
|
||||
result = result || (! this._objectDataStore.isEmpty());
|
||||
}
|
||||
|
||||
return MochiKit.Async.succeed(result);
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'prepareRemoteDataWithKey': function (aKey) {
|
||||
return Clipperz.Async.callbacks("EncryptedRemoteObject.prepareRemoteDataWithKey", [
|
||||
// MochiKit.Base.method(this.transientState(), 'setValue', '__prepareRemoteData', true),
|
||||
MochiKit.Base.method(this, '_getObjectDataStore'),
|
||||
MochiKit.Base.methodcaller('values'),
|
||||
MochiKit.Base.method(this, 'packData'),
|
||||
function (someData) {
|
||||
return Clipperz.PM.Crypto.deferredEncrypt({
|
||||
'key': aKey,
|
||||
'value': someData,
|
||||
'version': Clipperz.PM.Crypto.encryptingFunctions.currentVersion
|
||||
})
|
||||
},
|
||||
MochiKit.Base.method(this, 'packRemoteData'),
|
||||
MochiKit.Base.method(this.transientState(), 'setValue', 'packedRemoteData'),
|
||||
function (someData) {
|
||||
MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'advanceProgress');
|
||||
return someData;
|
||||
}
|
||||
], {trace:false});
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
__syntaxFix__: "syntax fix"
|
||||
});
|
||||
350
frontend/delta/js/Clipperz/PM/DataModel/OneTimePassword.js
Normal file
350
frontend/delta/js/Clipperz/PM/DataModel/OneTimePassword.js
Normal file
@@ -0,0 +1,350 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
|
||||
if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
|
||||
if (typeof(Clipperz.PM.DataModel) == 'undefined') { Clipperz.PM.DataModel = {}; }
|
||||
|
||||
|
||||
//#############################################################################
|
||||
|
||||
Clipperz.PM.DataModel.OneTimePassword = function(args) {
|
||||
args = args || {};
|
||||
|
||||
// this._user = args['user'];
|
||||
this._reference = args['reference'] || Clipperz.PM.Crypto.randomKey();
|
||||
this._password = args['password'];
|
||||
this._passwordValue = Clipperz.PM.DataModel.OneTimePassword.normalizedOneTimePassword(args['password']);
|
||||
this._creationDate = args['created'] ? Clipperz.PM.Date.parseDateWithUTCFormat(args['created']) : new Date();
|
||||
this._usageDate = args['used'] ? Clipperz.PM.Date.parseDateWithUTCFormat(args['used']) : null;
|
||||
|
||||
this._status = args['status'] || 'ACTIVE'; // 'REQUESTED', 'USED', 'DISABLED'
|
||||
this._connectionInfo= null;
|
||||
|
||||
this._key = null;
|
||||
this._keyChecksum = null;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
Clipperz.PM.DataModel.OneTimePassword.prototype = MochiKit.Base.update(null, {
|
||||
|
||||
'toString': function() {
|
||||
return "Clipperz.PM.DataModel.OneTimePassword";
|
||||
},
|
||||
/*
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'user': function() {
|
||||
return this._user;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'password': function() {
|
||||
return this._password;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'passwordValue': function() {
|
||||
return this._passwordValue;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'creationDate': function() {
|
||||
return this._creationDate;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'reference': function() {
|
||||
return this._reference;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'key': function() {
|
||||
if (this._key == null) {
|
||||
this._key = Clipperz.PM.DataModel.OneTimePassword.computeKeyWithUsernameAndPassword(this.user().username(), this.passwordValue());
|
||||
}
|
||||
|
||||
return this._key;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'keyChecksum': function() {
|
||||
if (this._keyChecksum == null) {
|
||||
this._keyChecksum = Clipperz.PM.DataModel.OneTimePassword.computeKeyChecksumWithUsernameAndPassword(this.user().username(), this.passwordValue());
|
||||
}
|
||||
|
||||
return this._keyChecksum;
|
||||
},
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'status': function() {
|
||||
return this._status;
|
||||
},
|
||||
|
||||
'setStatus': function(aValue) {
|
||||
this._status = aValue;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
'serializedData': function() {
|
||||
var result;
|
||||
|
||||
result = {
|
||||
'password': this.password(),
|
||||
'created': this.creationDate() ? Clipperz.PM.Date.formatDateWithUTCFormat(this.creationDate()) : null,
|
||||
'used': this.usageDate() ? Clipperz.PM.Date.formatDateWithUTCFormat(this.usageDate()) : null,
|
||||
'status': this.status()
|
||||
};
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'packedPassphrase': function() {
|
||||
var result;
|
||||
var packedPassphrase;
|
||||
var encodedPassphrase;
|
||||
var prefixPadding;
|
||||
var suffixPadding;
|
||||
var getRandomBytes;
|
||||
|
||||
getRandomBytes = MochiKit.Base.method(Clipperz.Crypto.PRNG.defaultRandomGenerator(), 'getRandomBytes');
|
||||
|
||||
encodedPassphrase = new Clipperz.ByteArray(this.user().passphrase()).toBase64String();
|
||||
//Clipperz.logDebug("--- encodedPassphrase.length: " + encodedPassphrase.length);
|
||||
prefixPadding = getRandomBytes(getRandomBytes(1).byteAtIndex(0)).toBase64String();
|
||||
//Clipperz.logDebug("--- prefixPadding.length: " + prefixPadding.length);
|
||||
suffixPadding = getRandomBytes((500 - prefixPadding.length - encodedPassphrase.length) * 6 / 8).toBase64String();
|
||||
//Clipperz.logDebug("--- suffixPadding.length: " + suffixPadding.length);
|
||||
//Clipperz.logDebug("--- total.length: " + (prefixPadding.length + encodedPassphrase.length + suffixPadding.length));
|
||||
|
||||
packedPassphrase = {
|
||||
'prefix': prefixPadding,
|
||||
'passphrase': encodedPassphrase,
|
||||
'suffix': suffixPadding
|
||||
};
|
||||
|
||||
// result = Clipperz.Base.serializeJSON(packedPassphrase);
|
||||
result = packedPassphrase;
|
||||
//Clipperz.logDebug("===== OTP packedPassprase: [" + result.length + "]" + result);
|
||||
//Clipperz.logDebug("<<< OneTimePassword.packedPassphrase");
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'encryptedPackedPassphrase': function() {
|
||||
return Clipperz.PM.Crypto.deferredEncryptWithCurrentVersion(this.passwordValue(), this.packedPassphrase())
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'encryptedData': function() {
|
||||
var deferredResult;
|
||||
var result;
|
||||
|
||||
//Clipperz.logDebug(">>> OneTimePassword.encryptedData");
|
||||
//Clipperz.logDebug("--- OneTimePassword.encryptedData - id: " + this.reference());
|
||||
result = {
|
||||
'reference': this.reference(),
|
||||
'key': this.key(),
|
||||
'keyChecksum': this.keyChecksum(),
|
||||
'data': "",
|
||||
'version': Clipperz.PM.Crypto.encryptingFunctions.currentVersion
|
||||
}
|
||||
//Clipperz.logDebug("--- OneTimePassword.encryptedData - 2: " + Clipperz.Base.serializeJSON(result));
|
||||
deferredResult = new MochiKit.Async.Deferred();
|
||||
//Clipperz.logDebug("--- OneTimePassword.encryptedData - 3");
|
||||
//deferredResult.addBoth(function(res) {Clipperz.logDebug("OneTimePassword.encryptedData - 1: " + res); return res;});
|
||||
//# deferredResult.addCallback(Clipperz.PM.Crypto.deferredEncryptWithCurrentVersion, this.passwordValue(), this.packedPassphrase());
|
||||
deferredResult.addCallback(MochiKit.Base.method(this, 'encryptedPackedPassphrase'));
|
||||
//Clipperz.logDebug("--- OneTimePassword.encryptedData - 4");
|
||||
//deferredResult.addBoth(function(res) {Clipperz.logDebug("OneTimePassword.encryptedData - 2: [" + res.length + "]" + res); return res;});
|
||||
deferredResult.addCallback(function(aResult, res) {
|
||||
aResult['data'] = res;
|
||||
return aResult;
|
||||
}, result);
|
||||
//Clipperz.logDebug("--- OneTimePassword.encryptedData - 5");
|
||||
//deferredResult.addBoth(function(res) {Clipperz.logDebug("OneTimePassword.encryptedData - 3: " + Clipperz.Base.serializeJSON(res)); return res;});
|
||||
deferredResult.callback();
|
||||
//Clipperz.logDebug("--- OneTimePassword.encryptedData - 6");
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'saveChanges': function() {
|
||||
var deferredResult;
|
||||
var result;
|
||||
|
||||
//Clipperz.logDebug(">>> OneTimePassword.saveChanges");
|
||||
result = {};
|
||||
deferredResult = new MochiKit.Async.Deferred();
|
||||
|
||||
deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', 'saveOTP_encryptUserData');
|
||||
deferredResult.addCallback(MochiKit.Base.method(this.user(), 'encryptedData'));
|
||||
deferredResult.addCallback(function(aResult, res) {
|
||||
aResult['user'] = res;
|
||||
return aResult;
|
||||
}, result);
|
||||
|
||||
deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', 'saveOTP_encryptOTPData');
|
||||
deferredResult.addCallback(MochiKit.Base.method(this, 'encryptedData'));
|
||||
deferredResult.addCallback(function(aResult, res) {
|
||||
aResult['oneTimePassword'] = res;
|
||||
return aResult;
|
||||
}, result);
|
||||
|
||||
deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', 'saveOTP_sendingData');
|
||||
//deferredResult.addBoth(function(res) {Clipperz.logDebug("OneTimePassword.saveChanges - 1: " + Clipperz.Base.serializeJSON(res)); return res;});
|
||||
deferredResult.addCallback(MochiKit.Base.method(this.user().connection(), 'message'), 'addNewOneTimePassword');
|
||||
|
||||
deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', 'saveOTP_updatingInterface');
|
||||
//deferredResult.addBoth(function(res) {Clipperz.logDebug("OneTimePassword.saveChanges - 2: " + res); return res;});
|
||||
deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'notify', 'OTPUpdated');
|
||||
deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'oneTimePassword_saveChanges_done', null);
|
||||
//deferredResult.addBoth(function(res) {Clipperz.logDebug("OneTimePassword.saveChanges - 2: " + res); return res;});
|
||||
deferredResult.callback();
|
||||
//Clipperz.logDebug("<<< OneTimePassword.saveChanges");
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'usageDate': function() {
|
||||
return this._usageDate;
|
||||
},
|
||||
|
||||
'setUsageDate': function(aValue) {
|
||||
this._usageDate = aValue;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'connectionInfo': function() {
|
||||
return this._connectionInfo;
|
||||
},
|
||||
|
||||
'setConnectionInfo': function(aValue) {
|
||||
this._connectionInfo = aValue;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'isExpired': function() {
|
||||
return (this.usageDate() != null);
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'updateStatusWithValues': function(someValues) {
|
||||
var result;
|
||||
|
||||
result = false;
|
||||
|
||||
if (someValues['status'] != this.status()) {
|
||||
result = true;
|
||||
}
|
||||
|
||||
this.setStatus(someValues['status']);
|
||||
this.setUsageDate(Clipperz.PM.Date.parseDateWithUTCFormat(someValues['requestDate']));
|
||||
this.setConnectionInfo(someValues['connection']);
|
||||
|
||||
return result;
|
||||
},
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
__syntaxFix__: "syntax fix"
|
||||
});
|
||||
|
||||
//#############################################################################
|
||||
|
||||
Clipperz.PM.DataModel.OneTimePassword.computeKeyWithUsernameAndPassword = function(anUsername, aPassword) {
|
||||
return Clipperz.Crypto.SHA.sha_d256(new Clipperz.ByteArray(aPassword)).toHexString().substring(2);
|
||||
}
|
||||
|
||||
Clipperz.PM.DataModel.OneTimePassword.computeKeyChecksumWithUsernameAndPassword = function(anUsername, aPassword) {
|
||||
return Clipperz.Crypto.SHA.sha_d256(new Clipperz.ByteArray(anUsername + aPassword)).toHexString().substring(2);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
||||
Clipperz.PM.DataModel.OneTimePassword.isValidOneTimePasswordValue = function(aPassword) {
|
||||
var result;
|
||||
|
||||
// "yaxx k7ww - f8y6 tqz5 - 58b6 th44 - 9cwv q0fg"
|
||||
if (aPassword.replace(/[\s\-]/g, '').length == 32) {
|
||||
try {
|
||||
var passwordByteArray;
|
||||
|
||||
passwordByteArray = new Clipperz.ByteArray();
|
||||
passwordByteArray.appendBase32String(aPassword);
|
||||
|
||||
result = true;
|
||||
} catch(exception) {
|
||||
result = false;
|
||||
}
|
||||
} else {
|
||||
result = false;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
||||
Clipperz.PM.DataModel.OneTimePassword.normalizedOneTimePassword = function(aPassword) {
|
||||
var result;
|
||||
|
||||
if (aPassword.replace(/[\s\-]/g, '').length == 32) {
|
||||
try {
|
||||
var passwordByteArray;
|
||||
|
||||
passwordByteArray = new Clipperz.ByteArray();
|
||||
passwordByteArray.appendBase32String(aPassword);
|
||||
|
||||
result = passwordByteArray.toBase64String();
|
||||
} catch(exception) {
|
||||
result = aPassword;
|
||||
}
|
||||
} else {
|
||||
result = aPassword;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//#############################################################################
|
||||
186
frontend/delta/js/Clipperz/PM/DataModel/Record.Version.Field.js
Normal file
186
frontend/delta/js/Clipperz/PM/DataModel/Record.Version.Field.js
Normal file
@@ -0,0 +1,186 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
try { if (typeof(Clipperz.PM.DataModel.Record.Version) == 'undefined') { throw ""; }} catch (e) {
|
||||
throw "Clipperz.PM.DataModel.Record.Version.Field depends on Clipperz.PM.DataModel.Record.Version!";
|
||||
}
|
||||
|
||||
Clipperz.PM.DataModel.Record.Version.Field = function(args) {
|
||||
Clipperz.PM.DataModel.Record.Version.Field.superclass.constructor.apply(this, arguments);
|
||||
|
||||
this._recordVersion = args.recordVersion || Clipperz.Base.exception.raise('MandatoryParameter');
|
||||
this._reference = args.reference || Clipperz.PM.Crypto.randomKey();
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
Clipperz.Base.extend(Clipperz.PM.DataModel.Record.Version.Field, Object, {
|
||||
|
||||
'toString': function() {
|
||||
return "Record.Version.Field (" + this.reference() + ")";
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'recordVersion': function () {
|
||||
return this._recordVersion;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'reference': function () {
|
||||
return this._reference;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'getItem': function (aKey) {
|
||||
return Clipperz.Async.callbacks("Clipperz.PM.DataModel.Record.Version.Field.getItem", [
|
||||
MochiKit.Base.method(this, 'recordVersion'),
|
||||
MochiKit.Base.methodcaller('getValue', 'fields' + '.' + this.reference() + '.' + aKey)
|
||||
], {trace:false});
|
||||
},
|
||||
|
||||
'setItem': function (aKey, aValue) {
|
||||
return Clipperz.Async.callbacks("Clipperz.PM.DataModel.Record.Version.Field.getItem", [
|
||||
MochiKit.Base.method(this, 'recordVersion'),
|
||||
MochiKit.Base.methodcaller('setValue', 'fields' + '.' + this.reference() + '.' + aKey, aValue)
|
||||
], {trace:false});
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'label': function () {
|
||||
return this.getItem('label');
|
||||
},
|
||||
|
||||
'setLabel': function (aValue) {
|
||||
return this.setItem('label', aValue);
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'value': function () {
|
||||
return this.getItem('value');
|
||||
},
|
||||
|
||||
'setValue': function (aValue) {
|
||||
return this.setItem('value', aValue);
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'actionType': function () {
|
||||
return Clipperz.Async.callbacks("Clipperz.PM.DataModel.Record.Version.Field.actionType", [
|
||||
Clipperz.Async.collectResults("Clipperz.PM.DataModel.Record.Version.Field.actionType [collect results]", {
|
||||
'isHidden': MochiKit.Base.method(this, 'isHidden'),
|
||||
'value': MochiKit.Base.method(this, 'value')
|
||||
}, {trace:false}),
|
||||
function (someValues) {
|
||||
var result; // 'NONE', 'URL', 'EMAIL', 'PASSWORD'
|
||||
|
||||
result = 'NONE';
|
||||
|
||||
if (someValues['isHidden']) {
|
||||
result = 'PASSWORD';
|
||||
} else if (Clipperz.Base.isUrl(someValues['value'])) {
|
||||
result = 'URL'
|
||||
} else if (Clipperz.Base.isEmail(someValues['value'])) {
|
||||
result = 'EMAIL'
|
||||
};
|
||||
|
||||
return result;
|
||||
}
|
||||
], {trace:false});
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'isHidden': function () {
|
||||
return this.getItem('hidden');
|
||||
},
|
||||
|
||||
'setIsHidden': function (aValue) {
|
||||
return this.setItem('hidden', aValue);
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'isEmpty': function () {
|
||||
var deferredResult;
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("Clipperz.PM.DataModel.Record.Version.Field.isEmpty", {trace:false});
|
||||
|
||||
deferredResult.collectResults({
|
||||
'label': [
|
||||
MochiKit.Base.method(this, 'label'),
|
||||
MochiKit.Base.partial(MochiKit.Base.operator.eq, '')
|
||||
],
|
||||
'value': [
|
||||
MochiKit.Base.method(this, 'value'),
|
||||
MochiKit.Base.partial(MochiKit.Base.operator.eq, '')
|
||||
],
|
||||
'isHidden': [
|
||||
MochiKit.Base.method(this, 'isHidden'),
|
||||
MochiKit.Base.partial(MochiKit.Base.operator.eq, false)
|
||||
]
|
||||
});
|
||||
deferredResult.addCallback(MochiKit.Base.values);
|
||||
deferredResult.addCallback(function(someValues) {
|
||||
return MochiKit.Iter.every(someValues, MochiKit.Base.operator.identity);
|
||||
});
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'content': function () {
|
||||
var deferredResult;
|
||||
var fieldValues;
|
||||
|
||||
fieldValues = {};
|
||||
deferredResult = new Clipperz.Async.Deferred("Record.Version.Field.content", {trace:false});
|
||||
deferredResult.addMethod(this, 'reference');
|
||||
deferredResult.addCallback(function (aValue) { fieldValues['reference'] = aValue; });
|
||||
deferredResult.addMethod(this, 'label');
|
||||
deferredResult.addCallback(function (aValue) { fieldValues['label'] = aValue; });
|
||||
deferredResult.addMethod(this, 'value');
|
||||
deferredResult.addCallback(function (aValue) { fieldValues['value'] = aValue; });
|
||||
deferredResult.addMethod(this, 'actionType');
|
||||
deferredResult.addCallback(function (aValue) { fieldValues['actionType'] = aValue; });
|
||||
deferredResult.addMethod(this, 'isHidden');
|
||||
deferredResult.addCallback(function (aValue) { fieldValues['isHidden'] = aValue; });
|
||||
deferredResult.addCallback(function () { return fieldValues; });
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
__syntaxFix__: "syntax fix"
|
||||
});
|
||||
|
||||
|
||||
328
frontend/delta/js/Clipperz/PM/DataModel/Record.Version.js
Normal file
328
frontend/delta/js/Clipperz/PM/DataModel/Record.Version.js
Normal file
@@ -0,0 +1,328 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
try { if (typeof(Clipperz.PM.DataModel.Record) == 'undefined') { throw ""; }} catch (e) {
|
||||
throw "Clipperz.PM.DataModel.Record.Version depends on Clipperz.PM.DataModel.Record!";
|
||||
}
|
||||
|
||||
Clipperz.PM.DataModel.Record.Version = function(args) {
|
||||
Clipperz.PM.DataModel.Record.Version.superclass.constructor.apply(this, arguments);
|
||||
|
||||
this._getVersionFunction = args.getVersion || Clipperz.Base.exception.raise('MandatoryParameter');
|
||||
this._fields = null;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
Clipperz.Base.extend(Clipperz.PM.DataModel.Record.Version, Clipperz.PM.DataModel.EncryptedRemoteObject, {
|
||||
|
||||
'toString': function() {
|
||||
return "Record.Version (" + this.reference() + ")";
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'reference': function () {
|
||||
return this._reference;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
'hasPendingChanges': function () {
|
||||
var deferredResult;
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("Clipperz.PM.DataModel.Record.Version.hasPendingChanges", {trace:false});
|
||||
deferredResult.addCallback(MochiKit.Base.bind(Clipperz.PM.DataModel.Record.Version.superclass.hasPendingChanges, this));
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
|
||||
'hasPendingChangesWhenBrandNew': function () {
|
||||
var deferredResult;
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("Clipperz.PM.DataModel.Record.Version.hasPendingChangesWhenBrandNew", {trace:false});
|
||||
deferredResult.addMethod(this, 'fields');
|
||||
deferredResult.addCallback(MochiKit.Base.values);
|
||||
deferredResult.addCallback(MochiKit.Base.map, MochiKit.Base.methodcaller('isEmpty'))
|
||||
deferredResult.addCallback(Clipperz.Async.collectAll);
|
||||
deferredResult.addCallback(function(someValues) {
|
||||
return MochiKit.Iter.every(someValues, MochiKit.Base.operator.identity);
|
||||
});
|
||||
deferredResult.addCallback(MochiKit.Base.operator.lognot)
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'commitTransientState': function () {
|
||||
var deferredResult;
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("Clipperz.PM.DataModel.Record.Version.commitTransientState", {trace:false});
|
||||
deferredResult.addCallback(MochiKit.Base.bind(Clipperz.PM.DataModel.Record.Version.superclass.commitTransientState, this));
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'unpackData': function (someData) { // ++
|
||||
var result;
|
||||
|
||||
result = someData;
|
||||
if ((someData['fields'] != null) && (someData['fields'] instanceof Array)) {
|
||||
var fields;
|
||||
var i,c;
|
||||
|
||||
fields = someData['fields'];
|
||||
delete someData['fields'];
|
||||
|
||||
someData['fields'] = {};
|
||||
c = fields.length;
|
||||
for (i=0; i<c; i++) {
|
||||
someData['fields'][i] = fields[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'fields': function () {
|
||||
var deferredResult;
|
||||
var deferredLock;
|
||||
|
||||
deferredLock = this.getDeferredLockForKey('fields');
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("Record.Version.fields", {trace:false});
|
||||
deferredResult.acquireLock(deferredLock);
|
||||
deferredResult.addCallback(MochiKit.Base.bind(function () {
|
||||
var innerDeferredResult;
|
||||
|
||||
if (this._fields == null) {
|
||||
innerDeferredResult = new Clipperz.Async.Deferred("Record.Version.fields <inner deferred>", {trace:false});
|
||||
innerDeferredResult.addMethod(this, 'getValue', 'fields');
|
||||
innerDeferredResult.addCallback(MochiKit.Base.bind(function (someObjectData) {
|
||||
var reference;
|
||||
|
||||
this._fields = {};
|
||||
|
||||
for (reference in someObjectData) {
|
||||
var recordVersionField;
|
||||
|
||||
recordVersionField = new Clipperz.PM.DataModel.Record.Version.Field({
|
||||
'recordVersion': this,
|
||||
'reference': reference
|
||||
});
|
||||
|
||||
this._fields[reference] = recordVersionField;
|
||||
}
|
||||
|
||||
return this._fields;
|
||||
}, this));
|
||||
innerDeferredResult.callback();
|
||||
} else {
|
||||
innerDeferredResult = MochiKit.Async.succeed(this._fields);
|
||||
}
|
||||
|
||||
return innerDeferredResult;
|
||||
}, this));
|
||||
deferredResult.releaseLock(deferredLock);
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'getFieldsValues': function () {
|
||||
return this.getValue('fields');
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'addField': function (someParameters) {
|
||||
var newField;
|
||||
|
||||
newField = new Clipperz.PM.DataModel.Record.Version.Field({recordVersion:this});
|
||||
|
||||
return Clipperz.Async.callbacks("Record.Version.addField", [
|
||||
MochiKit.Base.method(this, 'fields'),
|
||||
|
||||
MochiKit.Base.method(this, '_getObjectDataStore'),
|
||||
MochiKit.Base.methodcaller('values'),
|
||||
Clipperz.Base.serializeJSON,
|
||||
|
||||
MochiKit.Base.bind(function () { this._fields[newField.reference()] = newField; }, this),
|
||||
MochiKit.Base.method(newField, 'setLabel', someParameters['label']),
|
||||
MochiKit.Base.method(newField, 'setValue', someParameters['value']),
|
||||
MochiKit.Base.method(newField, 'setIsHidden', someParameters['isHidden']),
|
||||
|
||||
MochiKit.Base.method(this, '_getObjectDataStore'),
|
||||
MochiKit.Base.methodcaller('values'),
|
||||
Clipperz.Base.serializeJSON,
|
||||
|
||||
MochiKit.Base.partial(MochiKit.Async.succeed, newField)
|
||||
], {trace:false});
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'removeField': function (aField) {
|
||||
return Clipperz.Async.callbacks("Record.Version.removeField", [
|
||||
MochiKit.Base.method(this, 'fields'),
|
||||
MochiKit.Base.bind(function () { delete this._fields[aField.reference()]; }, this),
|
||||
MochiKit.Base.method(this, 'removeValue', 'fields' + '.' + aField.reference())
|
||||
], {trace:false});
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
'sortFieldReference': function (someSortedFieldReferences) {
|
||||
|
||||
|
||||
|
||||
},
|
||||
*/
|
||||
//=========================================================================
|
||||
/*
|
||||
'directLogins': function () {
|
||||
return MochiKit.Base.values(this._directLogins);
|
||||
},
|
||||
|
||||
'addDirectLogin': function (aDirectLogin) {
|
||||
this._directLogins[aDirectLogin.reference()] = aDirectLogin;
|
||||
},
|
||||
*/
|
||||
|
||||
//=========================================================================
|
||||
/*
|
||||
'updateValues': function (anotherVersion) {
|
||||
return Clipperz.Async.callbacks("Record.Version.updateValue", [
|
||||
MochiKit.Base.partial(MochiKit.Async.succeed, this)
|
||||
], {trace:false});
|
||||
},
|
||||
*/
|
||||
//=========================================================================
|
||||
|
||||
'setRemoteData': function (aValue) {
|
||||
this._remoteData = aValue;
|
||||
|
||||
return aValue;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'getVersionFunction': function () {
|
||||
return this._getVersionFunction;
|
||||
},
|
||||
|
||||
'previousVersion': function () {
|
||||
return Clipperz.Async.callbacks("Record.Versions.previousVersion", [
|
||||
MochiKit.Base.method(this, 'previousVersionReference'),
|
||||
this.getVersionFunction()
|
||||
], {trace:false});
|
||||
},
|
||||
|
||||
'previousVersionReference': function () {
|
||||
return this.getValue('previousVersionReference');
|
||||
},
|
||||
|
||||
'previousVersionKey': function () {
|
||||
// TODO: this value i encrypted on its own. So it can not be saved in the main objectStore!!!
|
||||
return this.getValue('previousVersionKey');
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'setPreviousVersionReferenceAndKey': function (aVersionObjectAndKey) {
|
||||
// this._previousVersion = anotherVersion;
|
||||
return Clipperz.Async.callbacks("Record.Version.setPreviousVersion", [
|
||||
MochiKit.Base.method(this, 'setValue', 'previousVersionReference', aVersionObjectAndKey['reference']),
|
||||
MochiKit.Base.method(this, 'setValue', 'previousVersionKey', aVersionObjectAndKey['key'])
|
||||
], {trace:false});
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'revertChanges': function () {
|
||||
this.setReference(this.transientState()['originalReference']);
|
||||
Clipperz.PM.DataModel.Record.Version.superclass.revertChanges.apply(this, arguments);
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'prepareRemoteDataWithKey': function (aKey) {
|
||||
var deferredResult;
|
||||
var result;
|
||||
|
||||
result = {};
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("Record.Version.prepareRemoteDataWithKey", {trace:false});
|
||||
if (this.isBrandNew() == false) {
|
||||
this.transientState()['originalReference'] = this.reference();
|
||||
|
||||
deferredResult.collectResults({
|
||||
'key': MochiKit.Base.partial(MochiKit.Async.succeed, aKey),
|
||||
'value': MochiKit.Base.method(this, 'getKey'),
|
||||
'version': MochiKit.Base.partial(MochiKit.Async.succeed, Clipperz.PM.Crypto.encryptingFunctions.currentVersion)
|
||||
});
|
||||
deferredResult.addCallback(Clipperz.PM.Crypto.deferredEncrypt);
|
||||
deferredResult.addCallback(Clipperz.Async.setItem, result, 'previousVersionKey');
|
||||
} else {
|
||||
deferredResult.addCallback(Clipperz.Async.setItem, result, 'previousVersionKey', Clipperz.PM.Crypto.nullValue);
|
||||
}
|
||||
deferredResult.addCallback(MochiKit.Base.bind(Clipperz.PM.DataModel.Record.superclass.prepareRemoteDataWithKey, this, aKey));
|
||||
deferredResult.addCallback(MochiKit.Base.update, result);
|
||||
deferredResult.addMethod(this, 'setRemoteData');
|
||||
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
/*
|
||||
'deleteAllCleanTextData': function () {
|
||||
return Clipperz.PM.DataModel.Record.Version.superclass.deleteAllCleanTextData.apply(this, arguments);
|
||||
},
|
||||
|
||||
'hasAnyCleanTextData': function () {
|
||||
return Clipperz.PM.DataModel.Record.Version.superclass.hasAnyCleanTextData.apply(this, arguments);
|
||||
},
|
||||
*/
|
||||
//=========================================================================
|
||||
__syntaxFix__: "syntax fix"
|
||||
});
|
||||
|
||||
|
||||
891
frontend/delta/js/Clipperz/PM/DataModel/Record.js
Normal file
891
frontend/delta/js/Clipperz/PM/DataModel/Record.js
Normal file
@@ -0,0 +1,891 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
|
||||
if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
|
||||
if (typeof(Clipperz.PM.DataModel) == 'undefined') { Clipperz.PM.DataModel = {}; }
|
||||
|
||||
|
||||
Clipperz.PM.DataModel.Record = function(args) {
|
||||
Clipperz.PM.DataModel.Record.superclass.constructor.apply(this, arguments);
|
||||
|
||||
this._updateDate = (args.updateDate ? Clipperz.PM.Date.parse(args.updateDate) : Clipperz.Base.exception.raise('MandatoryParameter'));
|
||||
|
||||
this._retrieveIndexDataFunction = args.retrieveIndexDataFunction || Clipperz.Base.exception.raise('MandatoryParameter');
|
||||
this._updateIndexDataFunction = args.updateIndexDataFunction || Clipperz.Base.exception.raise('MandatoryParameter');
|
||||
|
||||
this._retrieveDirectLoginIndexDataFunction = args.retrieveDirectLoginIndexDataFunction || null;
|
||||
this._setDirectLoginIndexDataFunction = args.setDirectLoginIndexDataFunction || null;
|
||||
this._removeDirectLoginIndexDataFunction = args.removeDirectLoginIndexDataFunction || null;
|
||||
|
||||
this._createNewDirectLoginFunction = args.createNewDirectLoginFunction || null;
|
||||
|
||||
this._directLogins = {};
|
||||
|
||||
this._versions = {};
|
||||
|
||||
this._currentRecordVersion = null;
|
||||
if (this.isBrandNew()) {
|
||||
var newVersion;
|
||||
|
||||
this.setNotes('');
|
||||
newVersion = new Clipperz.PM.DataModel.Record.Version({
|
||||
'retrieveKeyFunction': MochiKit.Base.method(this, 'getVersionKey'),
|
||||
'getVersion': MochiKit.Base.method(this, 'getVersion')
|
||||
|
||||
});
|
||||
this._versions[newVersion.reference()] = newVersion;
|
||||
this._currentVersionReference = newVersion.reference();
|
||||
// this.setLabel('');
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
Clipperz.Base.extend(Clipperz.PM.DataModel.Record, Clipperz.PM.DataModel.EncryptedRemoteObject, {
|
||||
|
||||
'toString': function() {
|
||||
return "Record (" + this.reference() + ")";
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'reference': function () {
|
||||
return this._reference;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'getIndexData': function () {
|
||||
return this._retrieveIndexDataFunction(this.reference());
|
||||
},
|
||||
|
||||
//.........................................................................
|
||||
|
||||
'getIndexDataForKey': function (aKey) {
|
||||
return Clipperz.Async.callbacks("Record.getIndexDataForKey", [
|
||||
MochiKit.Base.method(this, 'getIndexData'),
|
||||
MochiKit.Base.itemgetter(aKey)
|
||||
], {trace:false});
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'setIndexDataForKey': function (aKey, aValue) {
|
||||
// return this._updateIndexDataFunction(this.reference(), aKey, aValue);
|
||||
|
||||
var deferredResult;
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("Record.setIndexDataForKey", {trace:false});
|
||||
deferredResult.addMethod(this, 'getIndexDataForKey', aKey);
|
||||
deferredResult.addCallback(MochiKit.Base.bind(function (aCurrentValue) {
|
||||
var result;
|
||||
var originalValue;
|
||||
|
||||
originalValue = this.transientState().getValue('originalValues.indexData.' + aKey);
|
||||
if (originalValue == null) {
|
||||
originalValue = this.transientState().setValue('originalValues.indexData.' + aKey, aCurrentValue);
|
||||
}
|
||||
|
||||
if (aCurrentValue != aValue) {
|
||||
if (originalValue != aValue) {
|
||||
this.transientState().setValue('hasPendingChanges.indexData.' + aKey, true);
|
||||
} else {
|
||||
this.transientState().setValue('hasPendingChanges.indexData.' + aKey, false);
|
||||
}
|
||||
|
||||
result = this._updateIndexDataFunction(this.reference(), aKey, aValue);
|
||||
} else {
|
||||
result = MochiKit.Async.succeed(aValue);
|
||||
}
|
||||
|
||||
return result;
|
||||
}, this));
|
||||
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
/*
|
||||
'key': function () {
|
||||
return this.getIndexDataForKey('key');
|
||||
},
|
||||
*/
|
||||
//=========================================================================
|
||||
|
||||
'label': function () {
|
||||
return this.getIndexDataForKey('label');
|
||||
},
|
||||
|
||||
//.........................................................................
|
||||
|
||||
'setLabel': function (aValue) {
|
||||
return this.setIndexDataForKey('label', aValue);
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'headerNotes': function () {
|
||||
return this.getIndexDataForKey('notes');
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'notes': function () {
|
||||
return Clipperz.Async.callbacks("Record.notes", [
|
||||
MochiKit.Base.method(this, 'headerNotes'),
|
||||
MochiKit.Base.bind(function (someHeaderNotes) {
|
||||
var result;
|
||||
|
||||
if ((someHeaderNotes == null) || (typeof(someHeaderNotes) == 'undefined')) {
|
||||
result = this.getValue('notes');
|
||||
} else {
|
||||
result = MochiKit.Async.succeed(someHeaderNotes);
|
||||
}
|
||||
|
||||
return result;
|
||||
}, this)
|
||||
], {trace:false});
|
||||
},
|
||||
|
||||
//.........................................................................
|
||||
|
||||
'setNotes': function (aValue) {
|
||||
return this.setValue('notes', aValue);
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'updateDate': function () {
|
||||
return MochiKit.Async.succeed(this._updateDate);
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'favicon': function () {
|
||||
var result;
|
||||
var directLogins;
|
||||
|
||||
directLogins = MochiKit.Base.values(this.directLogins());
|
||||
if (directLogins.length > 0) {
|
||||
result = directLogins[0].favicon();
|
||||
// } else if (/* is there an URL to use for searching a favicon */){
|
||||
} else {
|
||||
result = null; // MochiKit.Async.succeed(Clipperz.PM.Strings['defaultFaviconUrl']);
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'searchableContent': function () {
|
||||
var deferredResult;
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("Record.searchableContent", {trace:false});
|
||||
|
||||
deferredResult.collectResults({
|
||||
'recordLabel': MochiKit.Base.method(this, 'label'),
|
||||
'directLoginLabels': [
|
||||
MochiKit.Base.method(this, 'directLoginReferences'),
|
||||
MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.itemgetter('label'))
|
||||
]
|
||||
})
|
||||
deferredResult.addCallback(function (someValues) {
|
||||
return someValues['recordLabel'] + ' ' + someValues['directLoginLabels'].join(' ');
|
||||
});
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'isMatching': function (aRegExp) {
|
||||
return Clipperz.Async.callbacks("deferredFilterFunction", [
|
||||
MochiKit.Base.method(this, 'searchableContent'),
|
||||
MochiKit.Base.method(aRegExp, 'test'),
|
||||
function (doesItMatch) {
|
||||
var result;
|
||||
|
||||
if (doesItMatch) {
|
||||
result = MochiKit.Async.succeed('match');
|
||||
} else {
|
||||
result = MochiKit.Async.fail('miss');
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
], {trace:false});
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'content': function () {
|
||||
var deferredResult;
|
||||
var result;
|
||||
|
||||
result = {
|
||||
'fields': [],
|
||||
'directLogins': []
|
||||
};
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("Record.content", {trace:false});
|
||||
deferredResult.addMethod(this, 'reference');
|
||||
deferredResult.addCallback(function (aValue) { result['reference'] = aValue; });
|
||||
deferredResult.addMethod(this, 'label');
|
||||
deferredResult.addCallback(function (aValue) { result['title'] = aValue; });
|
||||
deferredResult.addMethod(this, 'notes');
|
||||
deferredResult.addCallback(function (aValue) { result['notes'] = aValue; });
|
||||
|
||||
deferredResult.addMethod(this, 'fields');
|
||||
deferredResult.addCallback(MochiKit.Base.values);
|
||||
deferredResult.addCallback(MochiKit.Base.map, MochiKit.Base.methodcaller('content'));
|
||||
deferredResult.addCallback(Clipperz.Async.collectAll);
|
||||
deferredResult.addCallback(MochiKit.Base.map, function (aValue) { result['fields'].push(aValue); });
|
||||
|
||||
deferredResult.addMethod(this, 'directLogins');
|
||||
deferredResult.addCallback(MochiKit.Base.values);
|
||||
deferredResult.addCallback(MochiKit.Base.map, MochiKit.Base.methodcaller('content'));
|
||||
deferredResult.addCallback(Clipperz.Async.collectAll);
|
||||
deferredResult.addCallback(MochiKit.Base.map, function (aValue) { result['directLogins'].push(aValue); });
|
||||
deferredResult.addCallback(function () { return result; });
|
||||
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'directLogins': function () {
|
||||
return this._directLogins;
|
||||
},
|
||||
|
||||
'addDirectLogin': function (aDirectLogin) {
|
||||
this._directLogins[aDirectLogin.reference()] = aDirectLogin;
|
||||
},
|
||||
|
||||
'directLoginWithReference': function (aDirectLoginReference) {
|
||||
return this._directLogins[aDirectLoginReference];
|
||||
},
|
||||
|
||||
'createNewDirectLoginFunction': function () {
|
||||
return this._createNewDirectLoginFunction;
|
||||
},
|
||||
|
||||
'saveOriginalDirectLoginStatusToTransientState': function () {
|
||||
if (this.transientState().getValue('directLogins') == null) {
|
||||
// this.transientState().setValue('directLogins', this._directLogins)
|
||||
MochiKit.Iter.forEach(MochiKit.Base.keys(this._directLogins), MochiKit.Base.bind(function(aKey) {
|
||||
this.transientState().setValue('directLogins' + '.' + aKey, this._directLogins[aKey])
|
||||
}, this))
|
||||
}
|
||||
},
|
||||
|
||||
'createNewDirectLogin': function () {
|
||||
this.saveOriginalDirectLoginStatusToTransientState();
|
||||
|
||||
return this.createNewDirectLoginFunction()(this);
|
||||
},
|
||||
|
||||
'removeDirectLogin': function(aDirectLogin) {
|
||||
this.saveOriginalDirectLoginStatusToTransientState();
|
||||
|
||||
return Clipperz.Async.callbacks("Record.removeDirectLogin", [
|
||||
MochiKit.Base.method(this, 'removeValue', 'directLogins' + '.' + aDirectLogin.reference()),
|
||||
MochiKit.Base.bind(function () {
|
||||
delete this._directLogins[aDirectLogin.reference()]
|
||||
}, this)
|
||||
], {trace:false});
|
||||
|
||||
},
|
||||
|
||||
'directLoginReferences': function () {
|
||||
var result;
|
||||
|
||||
result = Clipperz.Async.callbacks("Record.directLoginReferences", [
|
||||
MochiKit.Base.method(this, 'directLogins'),
|
||||
MochiKit.Base.values,
|
||||
function (someDirectLogins) {
|
||||
var result;
|
||||
var i,c;
|
||||
|
||||
result = [];
|
||||
c = someDirectLogins.length;
|
||||
for (i=0; i<c; i++) {
|
||||
result.push(Clipperz.Async.collectResults("Record.directLoginReferences - collectResults", {
|
||||
'_rowObject': MochiKit.Async.succeed,
|
||||
'_reference': MochiKit.Base.methodcaller('reference'),
|
||||
'label': MochiKit.Base.methodcaller('label'),
|
||||
'favicon': MochiKit.Base.methodcaller('favicon')
|
||||
}, {trace:false})(someDirectLogins[i]));
|
||||
};
|
||||
|
||||
return result;
|
||||
},
|
||||
Clipperz.Async.collectAll
|
||||
], {trace:false});
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'unpackRemoteData': function (someData) {
|
||||
var result;
|
||||
|
||||
/*
|
||||
this._currentRecordVersion = new Clipperz.PM.DataModel.Record.Version({
|
||||
'reference': someData['currentVersion']['reference'],
|
||||
'retrieveKeyFunction': MochiKit.Base.method(this, 'getCurrentRecordVersionKey'),
|
||||
'remoteData': someData['currentVersion'],
|
||||
});
|
||||
*/
|
||||
var versionKey;
|
||||
|
||||
for (versionKey in someData['versions']) {
|
||||
this._versions[versionKey] = new Clipperz.PM.DataModel.Record.Version({
|
||||
'reference': versionKey,
|
||||
'retrieveKeyFunction': MochiKit.Base.method(this, 'getVersionKey'),
|
||||
'remoteData': someData['versions'][versionKey],
|
||||
'getVersion': MochiKit.Base.method(this, 'getVersion')
|
||||
})
|
||||
}
|
||||
|
||||
// this._currentVersionReference = someData['currentVersion']['reference'];
|
||||
this._currentVersionReference = someData['currentVersion'];
|
||||
|
||||
result = Clipperz.PM.DataModel.Record.superclass.unpackRemoteData.apply(this, arguments);
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'unpackData': function (someData) {
|
||||
var result;
|
||||
|
||||
result = Clipperz.PM.DataModel.Record.superclass.unpackData.apply(this, arguments);
|
||||
|
||||
if (MochiKit.Base.isUndefinedOrNull(result['notes'])) {
|
||||
result['notes'] = ''
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'prepareRemoteDataWithKey': function (aKey) {
|
||||
var deferredResult;
|
||||
var newVersionKey;
|
||||
var result;
|
||||
|
||||
newVersionKey = Clipperz.PM.Crypto.randomKey();
|
||||
result = {};
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("Record.prepareRemoteDataWithKey", {trace:false});
|
||||
deferredResult.addCallbackList([
|
||||
Clipperz.Async.collectResults("Record.prepareRemoteDataWithKey - collect results", {
|
||||
'isBrandNew': MochiKit.Base.method(this, 'isBrandNew'),
|
||||
'versionHasPendingChanges': [
|
||||
// MochiKit.Base.method(this, 'getCurrentRecordVersion'),
|
||||
// MochiKit.Base.methodcaller('hasPendingChanges')
|
||||
MochiKit.Base.method(this, 'invokeCurrentRecordVersionMethod', 'hasPendingChanges')
|
||||
]
|
||||
}),
|
||||
Clipperz.Async.or,
|
||||
|
||||
Clipperz.Async.deferredIf("Current Version has pending changes", [
|
||||
MochiKit.Base.method(this, 'createNewRecordVersion'),
|
||||
MochiKit.Base.methodcaller('prepareRemoteDataWithKey', newVersionKey),
|
||||
MochiKit.Base.partial(Clipperz.Async.setItem, result, 'currentRecordVersion'),
|
||||
MochiKit.Base.method(this, 'setCurrentRecordVersionKey', newVersionKey)
|
||||
], []),
|
||||
|
||||
MochiKit.Base.bind(Clipperz.PM.DataModel.Record.superclass.prepareRemoteDataWithKey, this, aKey),
|
||||
MochiKit.Base.partial(Clipperz.Async.setItem, result, 'record'),
|
||||
|
||||
MochiKit.Base.partial(MochiKit.Async.succeed, result)
|
||||
]);
|
||||
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'fields': function () {
|
||||
return this.invokeCurrentRecordVersionMethod('fields');
|
||||
},
|
||||
|
||||
'addField': function (someParameters) {
|
||||
return this.invokeCurrentRecordVersionMethod('addField', someParameters);
|
||||
},
|
||||
|
||||
'removeField': function (someParameters) {
|
||||
return this.invokeCurrentRecordVersionMethod('removeField', someParameters);
|
||||
},
|
||||
|
||||
// 'sortFieldReference': function (someSortedFieldReferences) {
|
||||
// return this.invokeCurrentRecordVersionMethod('sortFieldReference', someSortedFieldReferences);
|
||||
// },
|
||||
|
||||
'getFieldsValues': function () {
|
||||
return this.invokeCurrentRecordVersionMethod('getFieldsValues');
|
||||
},
|
||||
|
||||
'fieldWithLabel': function (aLabel) {
|
||||
return Clipperz.Async.callbacks("Record.fieldWithLabel", [
|
||||
MochiKit.Base.method(this, 'fields'),
|
||||
MochiKit.Base.values,
|
||||
MochiKit.Base.partial(Clipperz.Async.deferredFilter, function (aField) {
|
||||
return Clipperz.Async.callbacks("Record.fieldWithLabel - check field label", [
|
||||
MochiKit.Base.methodcaller('label'),
|
||||
MochiKit.Base.partial(MochiKit.Base.operator.eq, aLabel)
|
||||
], {trace:false}, aField);
|
||||
}),
|
||||
function (someFilteredResults) {
|
||||
var result;
|
||||
|
||||
switch (someFilteredResults.length) {
|
||||
case 0:
|
||||
result = null;
|
||||
break;
|
||||
case 1:
|
||||
result = someFilteredResults[0];
|
||||
break;
|
||||
default:
|
||||
WTF = TODO;
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
], {trace:false});
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'getVersion': function (aVersionReference) {
|
||||
return Clipperz.Async.callbacks("Record.getVersion", [
|
||||
MochiKit.Base.method(this, 'getVersions'),
|
||||
MochiKit.Base.itemgetter(aVersionReference)
|
||||
], {trace:false});
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'getVersionKey': function (aVersionReference) {
|
||||
var deferredResult;
|
||||
var transientStateKey;
|
||||
|
||||
transientStateKey = 'versionKeys' + '.' + aVersionReference;
|
||||
if (this.transientState().getValue(transientStateKey) != null) {
|
||||
deferredResult = MochiKit.Async.succeed(this.transientState().getValue(transientStateKey));
|
||||
} else {
|
||||
deferredResult = Clipperz.Async.callbacks("Record.getVersionKey", [
|
||||
MochiKit.Base.method(this, 'getVersions'),
|
||||
MochiKit.Base.partial(MochiKit.Base.operator.eq, aVersionReference, this.currentVersionReference()),
|
||||
Clipperz.Async.deferredIf("getVersionKey for current version", [
|
||||
MochiKit.Base.method(this, 'getCurrentRecordVersionKey'),
|
||||
MochiKit.Base.method(this.transientState(), 'setValue', transientStateKey)
|
||||
],[
|
||||
MochiKit.Async.fail
|
||||
])
|
||||
], {trace:false});
|
||||
}
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'versions': function () {
|
||||
return this._versions;
|
||||
},
|
||||
|
||||
'getVersions': function () {
|
||||
return Clipperz.Async.callbacks("Record.versions", [
|
||||
MochiKit.Base.method(this, 'getValue', 'fakeKey, just to trigger unpackRemoteData'),
|
||||
MochiKit.Base.bind(function () { return this._versions; }, this)
|
||||
], {trace:false});
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'getCurrentRecordVersion': function () {
|
||||
return Clipperz.Async.callbacks("Record.getCurrentRecordVersion", [
|
||||
// MochiKit.Base.method(this, 'getValue', 'fakeKey, just to trigger unpackRemoteData'),
|
||||
// MochiKit.Base.bind(function () { return this._currentRecordVersion; }, this)
|
||||
|
||||
MochiKit.Base.method(this, 'versions'),
|
||||
MochiKit.Base.itemgetter(this.currentVersionReference()),
|
||||
Clipperz.Async.deferredIf("The current version is available", [
|
||||
MochiKit.Async.succeed
|
||||
], [
|
||||
MochiKit.Base.method(this, 'getVersions'),
|
||||
MochiKit.Base.bind(function (someVersions) { return someVersions[this.currentVersionReference()]}, this)
|
||||
])
|
||||
], {trace:false});
|
||||
},
|
||||
|
||||
'setCurrentRecordVersion': function (aRecordVersion) {
|
||||
this._currentVersionReference = aRecordVersion.reference();
|
||||
},
|
||||
|
||||
//.........................................................................
|
||||
|
||||
'currentVersionReference': function () {
|
||||
return this._currentVersionReference;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'createNewRecordVersion': function () {
|
||||
var deferredResult;
|
||||
|
||||
if (this.isBrandNew()) {
|
||||
deferredResult = this.getCurrentRecordVersion();
|
||||
} else {
|
||||
var newVersion;
|
||||
|
||||
newVersion = new Clipperz.PM.DataModel.Record.Version({
|
||||
// 'reference': versionKey,
|
||||
'retrieveKeyFunction': MochiKit.Base.method(this, 'getVersionKey'),
|
||||
// 'remoteData': {},
|
||||
'getVersion': MochiKit.Base.method(this, 'getVersion')
|
||||
})
|
||||
this._versions[newVersion.reference()] = newVersion;
|
||||
|
||||
deferredResult = Clipperz.Async.callbacks("Record.createNewRecordVersion", [
|
||||
// MochiKit.Base.method(this, 'getCurrentRecordVersion'),
|
||||
// MochiKit.Base.methodcaller('values'),
|
||||
MochiKit.Base.method(this, 'invokeCurrentRecordVersionMethod', 'values'),
|
||||
MochiKit.Base.method(newVersion, 'setValues'),
|
||||
|
||||
Clipperz.Async.collectResults("Record.createNewRecordVersion [collect results]", {
|
||||
'reference': MochiKit.Base.method(this, 'currentVersionReference'),
|
||||
'key': MochiKit.Base.method(this, 'getCurrentRecordVersionKey')
|
||||
}, {trace:false}),
|
||||
MochiKit.Base.method(newVersion, 'setPreviousVersionReferenceAndKey'),
|
||||
|
||||
// MochiKit.Base.method(this, 'getCurrentRecordVersion'),
|
||||
// MochiKit.Base.method(this, 'revertChanges'),
|
||||
MochiKit.Base.method(this, 'invokeCurrentRecordVersionMethod', 'revertChanges'),
|
||||
|
||||
MochiKit.Base.method(this, 'setCurrentRecordVersion', newVersion),
|
||||
MochiKit.Base.partial(MochiKit.Async.succeed, newVersion)
|
||||
], {trace:false});
|
||||
}
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'getCurrentRecordVersionKey': function () {
|
||||
return Clipperz.Async.callbacks("Record.getCurrentRecordVersionKey", [
|
||||
MochiKit.Base.method(this, 'getValue', 'currentVersionKey'),
|
||||
Clipperz.Async.deferredIf("currentVersionKey is NOT null", [
|
||||
MochiKit.Async.succeed
|
||||
], [
|
||||
MochiKit.Base.method(this, 'getKey')
|
||||
])
|
||||
], {trace:false});
|
||||
},
|
||||
|
||||
'setCurrentRecordVersionKey': function (aValue) {
|
||||
// TODO: triple check this method!
|
||||
return Clipperz.Async.callbacks("Record.setCurrentRecordVersionKey", [
|
||||
MochiKit.Base.method(this, 'setValue', 'currentVersionKey', aValue)
|
||||
], {trace:false});
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'invokeCurrentRecordVersionMethod': function (aMethodName, someValues) {
|
||||
return Clipperz.Async.callbacks("Record.invokeCurrentRecordVersionMethod", [
|
||||
MochiKit.Base.method(this, 'getCurrentRecordVersion'),
|
||||
MochiKit.Base.methodcaller(aMethodName, someValues)
|
||||
], {trace:false});
|
||||
},
|
||||
|
||||
|
||||
'lazilyinvokeCurrentRecordVersionMethod': function (aMethodName, someValues, defaultResult) {
|
||||
return Clipperz.Async.callbacks("Record.lazilyinvokeCurrentRecordVersionMethod", [
|
||||
MochiKit.Base.method(this, 'currentVersionReference'),
|
||||
Clipperz.Async.deferredIf("versions has been loaded", [
|
||||
MochiKit.Base.method(this, 'getCurrentRecordVersion'),
|
||||
MochiKit.Base.methodcaller(aMethodName, someValues),
|
||||
], [
|
||||
MochiKit.Base.partial(MochiKit.Async.succeed, defaultResult),
|
||||
])
|
||||
], {trace:false});
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'hasPendingChanges': function () {
|
||||
var deferredResult;
|
||||
|
||||
if (this.hasInitiatedObjectDataStore()) {
|
||||
deferredResult = new Clipperz.Async.Deferred("Clipperz.PM.DataModel.Record.hasPendingChanges", {trace:false});
|
||||
deferredResult.collectResults({
|
||||
'super': MochiKit.Base.bind(Clipperz.PM.DataModel.Record.superclass.hasPendingChanges, this),
|
||||
'currentVersion': [
|
||||
// MochiKit.Base.method(this, 'getCurrentRecordVersion'),
|
||||
// MochiKit.Base.methodcaller('hasPendingChanges')
|
||||
MochiKit.Base.method(this, 'invokeCurrentRecordVersionMethod', 'hasPendingChanges')
|
||||
],
|
||||
'directLogins': [
|
||||
MochiKit.Base.method(this, 'directLogins'),
|
||||
MochiKit.Base.values,
|
||||
MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.methodcaller('hasPendingChanges')),
|
||||
Clipperz.Async.collectAll,
|
||||
Clipperz.Async.or
|
||||
// function(someValues) {
|
||||
// return MochiKit.Iter.some(someValues, MochiKit.Base.operator.identity);
|
||||
// }
|
||||
]
|
||||
});
|
||||
deferredResult.addCallback(MochiKit.Base.values);
|
||||
deferredResult.addCallback(MochiKit.Base.bind(function(someValues) {
|
||||
var result;
|
||||
result = MochiKit.Iter.some(someValues, MochiKit.Base.operator.identity);
|
||||
|
||||
if ((result == false) && (this.isBrandNew() == false)) {
|
||||
result = MochiKit.Iter.some(MochiKit.Base.values(this.transientState().getValue('hasPendingChanges.indexData')), MochiKit.Base.operator.identity);
|
||||
}
|
||||
|
||||
return result;
|
||||
}, this));
|
||||
|
||||
deferredResult.callback();
|
||||
} else {
|
||||
deferredResult = Clipperz.Async.callbacks("Recrod.hasPendingChanges [hasInitiatedObjectDataStore == false]", [
|
||||
MochiKit.Base.method(this, 'directLogins'),
|
||||
MochiKit.Base.values,
|
||||
MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.methodcaller('hasPendingChanges')),
|
||||
Clipperz.Async.collectAll,
|
||||
Clipperz.Async.or
|
||||
// function(someValues) {
|
||||
// return MochiKit.Iter.some(someValues, MochiKit.Base.operator.identity);
|
||||
// }
|
||||
], {trace:false})
|
||||
}
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'hasPendingChangesWhenBrandNew': function () {
|
||||
var deferredResult;
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("Clipperz.PM.DataModel.Record.hasPendingChangesWhenBrandNew", {trace:false});
|
||||
deferredResult.collectResults({
|
||||
'label': [
|
||||
MochiKit.Base.method(this, 'label'),
|
||||
MochiKit.Base.partial(MochiKit.Base.operator.ne, '')
|
||||
],
|
||||
'notes': [
|
||||
MochiKit.Base.method(this, 'notes'),
|
||||
MochiKit.Base.partial(MochiKit.Base.operator.ne, '')
|
||||
]
|
||||
});
|
||||
// deferredResult.addCallback(MochiKit.Base.values);
|
||||
// deferredResult.addCallback(function(someValues) {
|
||||
// return MochiKit.Iter.some(someValues, MochiKit.Base.operator.identity);
|
||||
// });
|
||||
deferredResult.addCallback(Clipperz.Async.or);
|
||||
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'isBrandNewWithNoPendingChanges': function () {
|
||||
var deferredResult;
|
||||
|
||||
if (this.isBrandNew() == false) {
|
||||
deferredResult = MochiKit.Async.succeed(false);
|
||||
} else {
|
||||
deferredResult = Clipperz.Async.callbacks("Record.isBrandNewWithNoPendingChanges", [
|
||||
MochiKit.Base.method(this, 'hasPendingChanges'),
|
||||
MochiKit.Base.operator.lognot
|
||||
], {trace:false});
|
||||
}
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'revertChanges': function () {
|
||||
var deferredResult;
|
||||
|
||||
if (this.isBrandNew() == false) {
|
||||
deferredResult = new Clipperz.Async.Deferred("Clipperz.PM.DataModel.Record.revertChanges", {trace:false});
|
||||
deferredResult.addMethod(this, 'hasPendingChanges');
|
||||
deferredResult.addIf([
|
||||
// MochiKit.Base.method(this, 'getCurrentRecordVersion'),
|
||||
// MochiKit.Base.methodcaller('revertChanges'),
|
||||
MochiKit.Base.method(this,'invokeCurrentRecordVersionMethod', 'revertChanges'),
|
||||
|
||||
MochiKit.Base.method(this, 'directLogins'),
|
||||
MochiKit.Base.values,
|
||||
MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.methodcaller('revertChanges')),
|
||||
|
||||
MochiKit.Base.bind(Clipperz.PM.DataModel.Record.superclass.revertChanges, this)
|
||||
], [
|
||||
MochiKit.Async.succeed
|
||||
]);
|
||||
deferredResult.callback();
|
||||
} else {
|
||||
// this.deleteAllCleanTextData();
|
||||
deferredResult = MochiKit.Async.succeed();
|
||||
}
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'resetTransientState': function (isCommitting) {
|
||||
// if ((isCommitting == false) && (this.transientState().getValue('directLogins') != null)) {
|
||||
// this._directLogins = this.transientState().getValue('directLogins');
|
||||
// }
|
||||
|
||||
return Clipperz.Async.callbacks("Record.resetTransientState", [
|
||||
//- MochiKit.Base.method(this, 'getCurrentRecordVersion'),
|
||||
//- MochiKit.Base.methodcaller('resetTransientState'),
|
||||
// MochiKit.Base.method(this, 'invokeCurrentRecordVersionMethod', 'resetTransientState'),
|
||||
MochiKit.Base.method(this, 'lazilyinvokeCurrentRecordVersionMethod', 'resetTransientState'),
|
||||
|
||||
MochiKit.Base.method(this, 'directLogins'),
|
||||
MochiKit.Base.values,
|
||||
MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.methodcaller('resetTransientState')),
|
||||
|
||||
MochiKit.Base.bind(function () {
|
||||
if ((isCommitting == false) && (this.transientState().getValue('directLogins') != null)) {
|
||||
this._directLogins = this.transientState().getValue('directLogins');
|
||||
}
|
||||
}, this),
|
||||
|
||||
MochiKit.Base.bind(Clipperz.PM.DataModel.Record.superclass.resetTransientState, this, isCommitting)
|
||||
], {trace:false})
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'commitTransientState': function () {
|
||||
var deferredResult;
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("Clipperz.PM.DataModel.Record.commitTransientState", {trace:false});
|
||||
deferredResult.addMethod(this, 'hasPendingChanges');
|
||||
deferredResult.addIf([
|
||||
MochiKit.Base.bind(Clipperz.PM.DataModel.Record.superclass.commitTransientState, this),
|
||||
// MochiKit.Base.method(this, 'getCurrentRecordVersion'),
|
||||
// MochiKit.Base.methodcaller('commitTransientState'),
|
||||
MochiKit.Base.method(this, 'invokeCurrentRecordVersionMethod', 'commitTransientState'),
|
||||
MochiKit.Base.method(this, 'directLogins'),
|
||||
MochiKit.Base.values,
|
||||
MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.methodcaller('commitTransientState'))
|
||||
], [
|
||||
MochiKit.Async.succeed
|
||||
]);
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'retrieveDirectLoginIndexDataFunction': function () {
|
||||
return this._retrieveDirectLoginIndexDataFunction;
|
||||
},
|
||||
|
||||
'setDirectLoginIndexDataFunction': function () {
|
||||
return this._setDirectLoginIndexDataFunction;
|
||||
},
|
||||
|
||||
'removeDirectLoginIndexDataFunction': function () {
|
||||
return this._removeDirectLoginIndexDataFunction;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'deleteAllCleanTextData': function () {
|
||||
// return Clipperz.PM.DataModel.Record.superclass.deleteAllCleanTextData.apply(this, arguments);
|
||||
|
||||
return Clipperz.Async.callbacks("Record.deleteAllCleanTextData", [
|
||||
MochiKit.Base.method(this, 'versions'),
|
||||
MochiKit.Base.values,
|
||||
MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.methodcaller('deleteAllCleanTextData')),
|
||||
|
||||
MochiKit.Base.method(this, 'directLogins'),
|
||||
MochiKit.Base.values,
|
||||
MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.methodcaller('deleteAllCleanTextData')),
|
||||
|
||||
MochiKit.Base.bind(Clipperz.PM.DataModel.Record.superclass.deleteAllCleanTextData, this)
|
||||
], {trace:false});
|
||||
},
|
||||
|
||||
'hasAnyCleanTextData': function () {
|
||||
// return Clipperz.PM.DataModel.Record.superclass.hasAnyCleanTextData.apply(this, arguments);
|
||||
|
||||
return Clipperz.Async.callbacks("Record.hasAnyCleanTextData", [
|
||||
Clipperz.Async.collectResults("Record.hasAnyCleanTextData [collect results]", {
|
||||
'versions': [
|
||||
MochiKit.Base.method(this, 'versions'),
|
||||
MochiKit.Base.values,
|
||||
MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.methodcaller('hasAnyCleanTextData')),
|
||||
Clipperz.Async.collectAll
|
||||
],
|
||||
'directLogins': [
|
||||
MochiKit.Base.method(this, 'directLogins'),
|
||||
MochiKit.Base.values,
|
||||
MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.methodcaller('hasAnyCleanTextData')),
|
||||
Clipperz.Async.collectAll
|
||||
],
|
||||
'super': [
|
||||
MochiKit.Base.bind(Clipperz.PM.DataModel.Record.superclass.hasAnyCleanTextData, this)
|
||||
]
|
||||
}, {trace:false}),
|
||||
Clipperz.Async.or
|
||||
])
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
__syntaxFix__: "syntax fix"
|
||||
});
|
||||
|
||||
|
||||
182
frontend/delta/js/Clipperz/PM/DataModel/User.Header.Legacy.js
Normal file
182
frontend/delta/js/Clipperz/PM/DataModel/User.Header.Legacy.js
Normal file
@@ -0,0 +1,182 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
try { if (typeof(Clipperz.PM.DataModel.User) == 'undefined') { throw ""; }} catch (e) {
|
||||
throw "Clipperz.PM.DataModel.User.Header.Legacy depends on Clipperz.PM.DataModel.User!";
|
||||
}
|
||||
|
||||
if (typeof(Clipperz.PM.DataModel.User.Header) == 'undefined') { Clipperz.PM.DataModel.User.Header = {}; }
|
||||
|
||||
Clipperz.PM.DataModel.User.Header.Legacy = function(args) {
|
||||
// args = args || {};
|
||||
Clipperz.PM.DataModel.User.Header.Legacy.superclass.constructor.apply(this, arguments);
|
||||
|
||||
this._retrieveRecordDetailFunction = args.retrieveRecordDetailFunction || Clipperz.Base.exception.raise('MandatoryParameter');
|
||||
this._records = null;
|
||||
// this._directLogins = null;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
Clipperz.Base.extend(Clipperz.PM.DataModel.User.Header.Legacy, Clipperz.PM.DataModel.EncryptedRemoteObject, {
|
||||
|
||||
'toString': function() {
|
||||
return "Clipperz.PM.DataModel.User.Header.Legacy";
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'retrieveRecordDetailFunction': function () {
|
||||
return this._retrieveRecordDetailFunction;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'getRecordKey': function (aRecordReference) {
|
||||
var deferredResult;
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("User.Header.Legacy.getRecordKey", {trace:false});
|
||||
deferredResult.addMethod(this, 'getRecordIndexData');
|
||||
deferredResult.addCallback(MochiKit.Base.itemgetter('key'))
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'getRecordIndexData': function (aRecordReference) {
|
||||
return this.getValue('records.' + aRecordReference);
|
||||
},
|
||||
|
||||
'updateRecordIndexData': function (aRecordReference, aKey, aValue) {
|
||||
return this.setValue('records.' + aRecordReference + "." + aKey, aValue);
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'getDirectLoginIndexData': function (aDirectLoginReference) {
|
||||
return this.getValue('directLogins.' + aDirectLoginReference);
|
||||
},
|
||||
|
||||
'setDirectLoginIndexData': function (aDirectLoginReference, aKey, aValue) {
|
||||
return this.setValue('directLogins.' + aDirectLoginReference + '.' + aKey, aValue);
|
||||
},
|
||||
|
||||
'removeDirectLoginIndexData': function (aDirectLoginReference) {
|
||||
return this.removeValue('directLogins.' + aDirectLoginReference);
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'records': function () {
|
||||
var deferredResult;
|
||||
var deferredLock;
|
||||
|
||||
deferredLock = this.getDeferredLockForKey('records');
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("User.Header.Legacy.records", {trace:false});
|
||||
deferredResult.acquireLock(deferredLock);
|
||||
deferredResult.addCallback(MochiKit.Base.bind(function () {
|
||||
var innerDeferredResult;
|
||||
|
||||
if (this._records == null) {
|
||||
innerDeferredResult = new Clipperz.Async.Deferred("User.Header.Legacy.records <inner deferred>", {trace:false});
|
||||
innerDeferredResult.collectResults({
|
||||
'header': [
|
||||
// MochiKit.Base.method(this, 'getObjectDataStore'),
|
||||
// MochiKit.Base.methodcaller('values')
|
||||
MochiKit.Base.method(this, 'values')
|
||||
],
|
||||
'recordsStats': [
|
||||
MochiKit.Base.method(this, 'getRemoteData'),
|
||||
MochiKit.Base.itemgetter('recordsStats')
|
||||
]
|
||||
});
|
||||
innerDeferredResult.addCallback(MochiKit.Base.bind(function (someObjectData) {
|
||||
var reference;
|
||||
|
||||
this._records = {};
|
||||
// this._directLogins = {};
|
||||
|
||||
for (reference in someObjectData['header']['records']) {
|
||||
var record;
|
||||
|
||||
record = new Clipperz.PM.DataModel.Record({
|
||||
'reference': reference,
|
||||
'retrieveKeyFunction': MochiKit.Base.method(this, 'getRecordKey'),
|
||||
'retrieveRemoteDataFunction': this.retrieveRecordDetailFunction(),
|
||||
// 'encryptedDataKeypath': 'data',
|
||||
// 'encryptedVersionKeypath': 'version',
|
||||
|
||||
'retrieveIndexDataFunction': MochiKit.Base.method(this, 'getRecordIndexData'),
|
||||
'updateIndexDataFunction': MochiKit.Base.method(this, 'updateRecordIndexData'),
|
||||
'updateDate': someObjectData['recordsStats'][reference]['updateDate'],
|
||||
|
||||
'retrieveDirectLoginIndexDataFunction': MochiKit.Base.method(this, 'getDirectLoginIndexData'),
|
||||
'setDirectLoginIndexDataFunction': MochiKit.Base.method(this, 'setDirectLoginIndexData'),
|
||||
'removeDirectLoginIndexDataFunction': MochiKit.Base.method(this, 'removeDirectLoginIndexData')
|
||||
});
|
||||
|
||||
this._records[reference] = record;
|
||||
}
|
||||
|
||||
for (reference in someObjectData['header']['directLogins']) {
|
||||
var directLogin;
|
||||
var record;
|
||||
|
||||
record = this._records[someObjectData['header']['directLogins'][reference]['record']];
|
||||
if (record != null) {
|
||||
directLogin = new Clipperz.PM.DataModel.DirectLogin({
|
||||
'reference': reference,
|
||||
'record': record //,
|
||||
// 'retrieveIndexDataFunction': MochiKit.Base.method(this, 'getDirectLoginIndexData'),
|
||||
// 'setIndexDataFunction': MochiKit.Base.method(this, 'setDirectLoginIndexData'),
|
||||
// 'removeIndexDataFunction': MochiKit.Base.method(this, 'removeDirectLoginIndexData')
|
||||
});
|
||||
} else {
|
||||
Clipperz.log("WARNING: DIRECT LOGIN without a matching RECORD!!");
|
||||
}
|
||||
}
|
||||
|
||||
return this._records;
|
||||
}, this));
|
||||
innerDeferredResult.callback();
|
||||
} else {
|
||||
innerDeferredResult = MochiKit.Async.succeed(this._records);
|
||||
}
|
||||
|
||||
return innerDeferredResult;
|
||||
}, this));
|
||||
deferredResult.releaseLock(deferredLock);
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
__syntaxFix__: "syntax fix"
|
||||
});
|
||||
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
try { if (typeof(Clipperz.PM.DataModel.User) == 'undefined') { throw ""; }} catch (e) {
|
||||
throw "Clipperz.PM.DataModel.User.Header.OneTimePasswords depends on Clipperz.PM.DataModel.User!";
|
||||
}
|
||||
if (typeof(Clipperz.PM.DataModel.User.Header) == 'undefined') { Clipperz.PM.DataModel.User.Header = {}; }
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
Clipperz.PM.DataModel.User.Header.OneTimePasswords = function(args) {
|
||||
Clipperz.PM.DataModel.User.Header.OneTimePasswords.superclass.constructor.apply(this, arguments);
|
||||
|
||||
this._oneTimePasswords = null;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
Clipperz.Base.extend(Clipperz.PM.DataModel.User.Header.OneTimePasswords, Clipperz.PM.DataModel.EncryptedRemoteObject, {
|
||||
|
||||
'toString': function() {
|
||||
return "Clipperz.PM.DataModel.User.Header.OneTimePasswords";
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
'packData': function (someData) { // ++
|
||||
var result;
|
||||
|
||||
result = Clipperz.PM.DataModel.User.Header.OneTimePasswords.superclass.packData.apply(this, arguments);
|
||||
|
||||
return result;
|
||||
},
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
'packRemoteData': function (someData) {
|
||||
var result;
|
||||
|
||||
result = Clipperz.PM.DataModel.User.Header.OneTimePasswords.superclass.packRemoteData.apply(this, arguments);
|
||||
|
||||
return result;
|
||||
},
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
'prepareRemoteDataWithKey': function (aKey) {
|
||||
var result;
|
||||
|
||||
result = Clipperz.PM.DataModel.User.Header.OneTimePasswords.superclass.prepareRemoteDataWithKey.apply(this, arguments);
|
||||
|
||||
return result;
|
||||
},
|
||||
*/
|
||||
//=========================================================================
|
||||
|
||||
'oneTimePasswords': function () {
|
||||
var deferredResult;
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("User.Header.OneTimePasswords.oneTimePasswords", {trace:false});
|
||||
if (this._oneTimePasswords == null) {
|
||||
deferredResult.addMethod(this, 'values')
|
||||
deferredResult.addCallback(MochiKit.Base.bind(function (someData) {
|
||||
var otpKey;
|
||||
|
||||
this._oneTimePasswords = {};
|
||||
|
||||
for (otpKey in someData) {
|
||||
var otp;
|
||||
var otpParameters;
|
||||
|
||||
otpParameters = Clipperz.Base.deepClone(someData[otpKey]);
|
||||
otpParameters['reference'] = otpKey;
|
||||
|
||||
otp = new Clipperz.PM.DataModel.OneTimePassword(otpParameters);
|
||||
this._oneTimePasswords[otpKey] = otp;
|
||||
}
|
||||
|
||||
return this._oneTimePasswords;
|
||||
|
||||
}, this));
|
||||
deferredResult.callback();
|
||||
} else {
|
||||
deferredResult = MochiKit.Async.succeed(this._oneTimePasswords);
|
||||
}
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
__syntaxFix__: "syntax fix"
|
||||
});
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
try { if (typeof(Clipperz.PM.DataModel.User) == 'undefined') { throw ""; }} catch (e) {
|
||||
throw "Clipperz.PM.DataModel.User.Header.Preferences depends on Clipperz.PM.DataModel.User!";
|
||||
}
|
||||
|
||||
if (typeof(Clipperz.PM.DataModel.User.Header) == 'undefined') { Clipperz.PM.DataModel.User.Header = {}; }
|
||||
|
||||
Clipperz.PM.DataModel.User.Header.Preferences = function(args) {
|
||||
Clipperz.PM.DataModel.User.Header.Preferences.superclass.constructor.apply(this, arguments);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
Clipperz.Base.extend(Clipperz.PM.DataModel.User.Header.Preferences, Clipperz.PM.DataModel.EncryptedRemoteObject, {
|
||||
|
||||
'toString': function() {
|
||||
return "Clipperz.PM.DataModel.User.Header.Preferences";
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//=========================================================================
|
||||
__syntaxFix__: "syntax fix"
|
||||
});
|
||||
|
||||
|
||||
@@ -0,0 +1,685 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
try { if (typeof(Clipperz.PM.DataModel.User) == 'undefined') { throw ""; }} catch (e) {
|
||||
throw "Clipperz.PM.DataModel.User.Header.RecordIndex depends on Clipperz.PM.DataModel.User!";
|
||||
}
|
||||
|
||||
if (typeof(Clipperz.PM.DataModel.User.Header) == 'undefined') { Clipperz.PM.DataModel.User.Header = {}; }
|
||||
|
||||
Clipperz.PM.DataModel.User.Header.RecordIndex = function(args) {
|
||||
Clipperz.PM.DataModel.User.Header.RecordIndex.superclass.constructor.apply(this, arguments);
|
||||
|
||||
this._recordsData = new Clipperz.PM.DataModel.EncryptedRemoteObject({
|
||||
'name': 'recordsData',
|
||||
'retrieveKeyFunction': args.retrieveKeyFunction,
|
||||
'remoteData': {
|
||||
'data': args.recordsData['data'],
|
||||
'version': args.encryptedDataVersion,
|
||||
'recordsStats': args.recordsStats
|
||||
}//,
|
||||
// 'encryptedDataKeypath': 'data',
|
||||
// 'encryptedVersionKeypath': 'version'
|
||||
});
|
||||
|
||||
this._directLoginsData = new Clipperz.PM.DataModel.EncryptedRemoteObject({
|
||||
'name': 'directLoginsData',
|
||||
'retrieveKeyFunction': args.retrieveKeyFunction,
|
||||
'remoteData': {
|
||||
'data': args.directLoginsData['data'],
|
||||
'version': args.encryptedDataVersion
|
||||
}//,
|
||||
// 'encryptedDataKeypath': 'data',
|
||||
// 'encryptedVersionKeypath': 'version'
|
||||
});
|
||||
|
||||
this._lock = new MochiKit.Async.DeferredLock();
|
||||
this._transientState = null;
|
||||
|
||||
this._retrieveRecordDetailFunction = args.retrieveRecordDetailFunction || Clipperz.Base.exception.raise('MandatoryParameter');
|
||||
this._recordsIndex = args.recordsData['index'] || Clipperz.Base.exception.raise('MandatoryParameter');
|
||||
this._directLoginsIndex = args.directLoginsData['index'] || Clipperz.Base.exception.raise('MandatoryParameter');
|
||||
|
||||
this._records = null;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
Clipperz.Base.extend(Clipperz.PM.DataModel.User.Header.RecordIndex, Object, {
|
||||
|
||||
'toString': function() {
|
||||
return "Clipperz.PM.DataModel.User.Header.RecordIndex";
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'retrieveRecordDetailFunction': function () {
|
||||
return this._retrieveRecordDetailFunction;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'recordsIndex': function () {
|
||||
return this._recordsIndex;
|
||||
},
|
||||
|
||||
'recordsData': function () {
|
||||
return this._recordsData;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'directLoginsIndex': function () {
|
||||
return this._directLoginsIndex;
|
||||
},
|
||||
|
||||
'directLoginsData': function () {
|
||||
return this._directLoginsData;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'lock': function () {
|
||||
return this._lock;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'transientState': function () {
|
||||
if (this._transientState == null) {
|
||||
this._transientState = new Clipperz.KeyValueObjectStore(/*{'name':'User.Header.RecordIndex.transientState [1]'}*/);
|
||||
}
|
||||
|
||||
return this._transientState;
|
||||
},
|
||||
|
||||
'resetTransientState': function (isCommitting) {
|
||||
if (this._transientState != null) {
|
||||
this._transientState.removeAllData();
|
||||
}
|
||||
|
||||
this._transientState = null;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'getRecordKey': function (aRecordReference) {
|
||||
return Clipperz.Async.callbacks("User.Header.RecordIndex.getRecordKey", [
|
||||
MochiKit.Base.method(this, 'getRecordIndexData', aRecordReference),
|
||||
MochiKit.Base.itemgetter('key')
|
||||
], {trace:false});
|
||||
},
|
||||
|
||||
'setRecordKey': function (aRecordReference, aValue) {
|
||||
return this.updateRecordIndexData(aRecordReference, 'key', aValue);
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'getRecordIndexData': function (aRecordReference) {
|
||||
return this.recordsData().getValue(this.recordsIndex()[aRecordReference]);
|
||||
},
|
||||
|
||||
//.........................................................................
|
||||
|
||||
'updateRecordIndexData': function (aRecordReference, aKey, aValue) {
|
||||
return this.recordsData().setValue(this.recordsIndex()[aRecordReference]+'.'+aKey, aValue);
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'getDirectLoginIndexData': function (aDirectLoginReference) {
|
||||
return this.directLoginsData().getValue(this.directLoginsIndex()[aDirectLoginReference]);
|
||||
},
|
||||
|
||||
'setDirectLoginIndexData': function (aDirectLoginReference, aKey, aValue) {
|
||||
//if (MochiKit.Base.isUndefinedOrNull(this.directLoginsIndex()[aDirectLoginReference])) {
|
||||
// throw "PIPPO";
|
||||
//}
|
||||
return this.directLoginsData().setValue(this.directLoginsIndex()[aDirectLoginReference] + '.' + aKey, aValue);
|
||||
},
|
||||
|
||||
'addDirectLoginIndexData': function (aDirectLoginReference) {
|
||||
return this.directLoginsData().setValue(this.directLoginsIndex()[aDirectLoginReference], {});
|
||||
},
|
||||
|
||||
'removeDirectLoginIndexData': function (aDirectLoginReference) {
|
||||
return this.directLoginsData().removeValue(this.directLoginsIndex()[aDirectLoginReference])
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'records': function () {
|
||||
var deferredResult;
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("User.Header.RecordIndex.records", {trace:false});
|
||||
deferredResult.acquireLock(this.lock());
|
||||
deferredResult.addCallback(MochiKit.Base.bind(function () {
|
||||
var innerDeferredResult;
|
||||
|
||||
if (this._records == null) {
|
||||
innerDeferredResult = new Clipperz.Async.Deferred("User.Header.RecordIndex.records <inner deferred>", {trace:false});
|
||||
innerDeferredResult.collectResults({
|
||||
'records': [
|
||||
// MochiKit.Base.method(this.recordsData(), 'getObjectDataStore'),
|
||||
// MochiKit.Base.methodcaller('values')
|
||||
MochiKit.Base.method(this.recordsData(), 'values')
|
||||
],
|
||||
'recordsStats': [
|
||||
MochiKit.Base.method(this.recordsData(), 'getRemoteData'),
|
||||
MochiKit.Base.itemgetter('recordsStats')
|
||||
],
|
||||
'directLogins': [
|
||||
// MochiKit.Base.method(this.directLoginsData(), 'getObjectDataStore'),
|
||||
// MochiKit.Base.methodcaller('values')
|
||||
MochiKit.Base.method(this.directLoginsData(), 'values')
|
||||
]
|
||||
})
|
||||
innerDeferredResult.addCallback(MochiKit.Base.bind(function (someData) {
|
||||
var indexReference;
|
||||
var recordsInvertedIndex;
|
||||
var directLoginsInvertedIndex;
|
||||
|
||||
recordsInvertedIndex = Clipperz.PM.DataModel.User.Header.RecordIndex.invertIndex(this.recordsIndex());
|
||||
directLoginsInvertedIndex = Clipperz.PM.DataModel.User.Header.RecordIndex.invertIndex(this.directLoginsIndex());
|
||||
|
||||
this._records = {};
|
||||
|
||||
for (indexReference in someData['records']) {
|
||||
var record;
|
||||
var reference;
|
||||
var updateDate;
|
||||
|
||||
reference = recordsInvertedIndex[indexReference];
|
||||
|
||||
if (typeof(someData['recordsStats'][reference]) != 'undefined') {
|
||||
updateDate = someData['recordsStats'][reference]['updateDate'];
|
||||
|
||||
record = new Clipperz.PM.DataModel.Record({
|
||||
'reference': reference,
|
||||
'retrieveKeyFunction': MochiKit.Base.method(this, 'getRecordKey'),
|
||||
'retrieveRemoteDataFunction': this.retrieveRecordDetailFunction(),
|
||||
|
||||
'retrieveIndexDataFunction': MochiKit.Base.method(this, 'getRecordIndexData'),
|
||||
'updateIndexDataFunction': MochiKit.Base.method(this, 'updateRecordIndexData'),
|
||||
'updateDate': updateDate,
|
||||
|
||||
'retrieveDirectLoginIndexDataFunction': MochiKit.Base.method(this, 'getDirectLoginIndexData'),
|
||||
'setDirectLoginIndexDataFunction': MochiKit.Base.method(this, 'setDirectLoginIndexData'),
|
||||
'removeDirectLoginIndexDataFunction': MochiKit.Base.method(this, 'removeDirectLoginIndexData'),
|
||||
|
||||
'createNewDirectLoginFunction': MochiKit.Base.method(this, 'createNewDirectLogin')
|
||||
});
|
||||
|
||||
this._records[reference] = record;
|
||||
} else {
|
||||
Clipperz.log("SKIPPING record " + reference + " as there are no stas associated - " + Clipperz.Base.serializeJSON(someData['records'][reference]));
|
||||
// # skip the record, as it seems it is not present in the DB
|
||||
// updateDate = Clipperz.PM.Date.formatDateWithUTCFormat(new Date());
|
||||
}
|
||||
}
|
||||
|
||||
for (indexReference in someData['directLogins']) {
|
||||
// var directLogin;
|
||||
var reference;
|
||||
var record;
|
||||
|
||||
reference = directLoginsInvertedIndex[indexReference];
|
||||
record = this._records[recordsInvertedIndex[someData['directLogins'][indexReference]['record']]];
|
||||
|
||||
if (record != null) {
|
||||
// directLogin = new Clipperz.PM.DataModel.DirectLogin({
|
||||
new Clipperz.PM.DataModel.DirectLogin({
|
||||
'reference': reference,
|
||||
'record': record
|
||||
});
|
||||
} else {
|
||||
Clipperz.logWarning("WARNING: DIRECT LOGIN without a matching RECORD!!");
|
||||
}
|
||||
}
|
||||
|
||||
return this._records;
|
||||
}, this));
|
||||
innerDeferredResult.callback();
|
||||
} else {
|
||||
innerDeferredResult = MochiKit.Async.succeed(this._records);
|
||||
}
|
||||
|
||||
return innerDeferredResult;
|
||||
}, this));
|
||||
deferredResult.releaseLock(this.lock());
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'updateRecordIndexForNewRecord': function (aNewRecord) {
|
||||
var newRecordIndex;
|
||||
var recordReference;
|
||||
|
||||
recordReference = aNewRecord.reference();
|
||||
newRecordIndex = (MochiKit.Base.listMax(MochiKit.Base.map(MochiKit.Base.partial(MochiKit.Base.operator.mul, 1), MochiKit.Base.values(this.recordsIndex()))) + 1) + '';
|
||||
this.recordsIndex()[recordReference] = newRecordIndex;
|
||||
|
||||
this.transientState().setValue('newlyCreatedRecordsIndex' + '.' + recordReference, newRecordIndex);
|
||||
this.transientState().setValue('newlyCreatedRecordsReferences' + '.' + recordReference, aNewRecord);
|
||||
},
|
||||
|
||||
//.........................................................................
|
||||
|
||||
'createNewRecord': function () {
|
||||
var deferredResult;
|
||||
var newRecord;
|
||||
|
||||
newRecord = new Clipperz.PM.DataModel.Record({
|
||||
'retrieveKeyFunction': MochiKit.Base.method(this, 'getRecordKey'),
|
||||
'retrieveRemoteDataFunction': this.retrieveRecordDetailFunction(),
|
||||
|
||||
'retrieveIndexDataFunction': MochiKit.Base.method(this, 'getRecordIndexData'),
|
||||
'updateIndexDataFunction': MochiKit.Base.method(this, 'updateRecordIndexData'),
|
||||
'updateDate': Clipperz.PM.Date.formatDateWithUTCFormat(new Date()),
|
||||
|
||||
'retrieveDirectLoginIndexDataFunction': MochiKit.Base.method(this, 'getDirectLoginIndexData'),
|
||||
'setDirectLoginIndexDataFunction': MochiKit.Base.method(this, 'setDirectLoginIndexData'),
|
||||
'removeDirectLoginIndexDataFunction': MochiKit.Base.method(this, 'removeDirectLoginIndexData'),
|
||||
|
||||
'createNewDirectLoginFunction': MochiKit.Base.method(this, 'createNewDirectLogin')
|
||||
});
|
||||
|
||||
this.transientState().setValue('newRecordsReferences' + '.' + newRecord.reference(), newRecord);
|
||||
this.updateRecordIndexForNewRecord(newRecord);
|
||||
|
||||
deferredResult = Clipperz.Async.callbacks("User.Header.RecordIndex.createNewRecord", [
|
||||
MochiKit.Base.method(this, 'records'),
|
||||
MochiKit.Base.partial(Clipperz.Async.setItemOnObject, newRecord.reference(), newRecord),
|
||||
MochiKit.Base.method(this, 'setRecordKey', newRecord.reference(), Clipperz.PM.Crypto.randomKey()),
|
||||
MochiKit.Base.method(newRecord, 'setLabel', ''),
|
||||
MochiKit.Base.partial(MochiKit.Async.succeed, newRecord)
|
||||
], {trace:false});
|
||||
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'deleteRecord': function (aRecord) {
|
||||
var deferredResult;
|
||||
var recordReference;
|
||||
|
||||
recordReference = aRecord.reference();
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("User.Header.RecordIndex.deleteRecord", {trace:false});
|
||||
|
||||
deferredResult.addMethod(aRecord, 'directLogins');
|
||||
deferredResult.addCallback(MochiKit.Base.values);
|
||||
deferredResult.addCallback(MochiKit.Base.map, MochiKit.Base.method(this, 'removeDirectLogin'));
|
||||
|
||||
deferredResult.addMethod(this.recordsData(), 'removeValue', this.recordsIndex()[recordReference]);
|
||||
deferredResult.addCallback(MochiKit.Base.bind(function () {
|
||||
this.transientState().setValue('deleteRecordsIndex' + '.' + recordReference, this.recordsIndex()[recordReference]);
|
||||
delete this.recordsIndex()[recordReference];
|
||||
}, this));
|
||||
|
||||
deferredResult.addMethod(this, 'records');
|
||||
deferredResult.addCallback(MochiKit.Base.itemgetter(recordReference));
|
||||
deferredResult.addMethod(this.transientState(), 'setValue', 'deleteRecordsReferences' + '.' + recordReference);
|
||||
|
||||
deferredResult.addMethod(this, 'records');
|
||||
deferredResult.addCallback(MochiKit.Base.bind(function (someRecords) {
|
||||
delete someRecords[recordReference];
|
||||
}, this));
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'removeDirectLogin': function (aDirectLogin) {
|
||||
this.directLoginsData().removeValue(this.directLoginsIndex()[aDirectLogin.reference()]);
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'createNewDirectLogin': function (aRecord) {
|
||||
var newDirectLogin;
|
||||
var newDirectLoginIndexValue;
|
||||
|
||||
newDirectLogin = new Clipperz.PM.DataModel.DirectLogin({record:aRecord});
|
||||
newDirectLoginIndexValue = MochiKit.Base.listMax(MochiKit.Base.map(function (aValue) { return aValue * 1; }, MochiKit.Base.values(this.directLoginsIndex()))) + 1;
|
||||
|
||||
this.transientState().setValue('newDirectLoginReferences' + '.' + newDirectLogin.reference(), newDirectLogin);
|
||||
|
||||
this.directLoginsIndex()[newDirectLogin.reference()] = newDirectLoginIndexValue;
|
||||
this.directLoginsData().setValue(this.directLoginsIndex()[newDirectLogin.reference()], {'record': this.recordsIndex()[aRecord.reference()]});
|
||||
|
||||
return newDirectLogin;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'deleteAllCleanTextData': function () {
|
||||
return Clipperz.Async.callbacks("User.Header.RecordIndex.deleteAllCleanTextData", [
|
||||
// MochiKit.Base.method(this, 'records'),
|
||||
// MochiKit.Base.values,
|
||||
// MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.methodcaller('deleteAllCleanTextData')),
|
||||
|
||||
MochiKit.Base.method(this, 'recordsData'),
|
||||
MochiKit.Base.methodcaller('deleteAllCleanTextData'),
|
||||
MochiKit.Base.method(this, 'directLoginsData'),
|
||||
MochiKit.Base.methodcaller('deleteAllCleanTextData')
|
||||
], {trace:false});
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'hasAnyCleanTextData': function () {
|
||||
var deferredResult;
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred({trace:false});
|
||||
deferredResult.collectResults({
|
||||
'recordsData': [
|
||||
MochiKit.Base.method(this, 'recordsData'),
|
||||
MochiKit.Base.methodcaller('hasAnyCleanTextData')
|
||||
],
|
||||
'directLoginsData': [
|
||||
MochiKit.Base.method(this, 'directLoginsData'),
|
||||
MochiKit.Base.methodcaller('hasAnyCleanTextData')
|
||||
],
|
||||
// 'records': [
|
||||
// MochiKit.Base.method(this, 'records'),
|
||||
// MochiKit.Base.values,
|
||||
// MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.methodcaller('hasAnyCleanTextData')),
|
||||
// Clipperz.Async.collectAll
|
||||
// ]
|
||||
});
|
||||
|
||||
// deferredResult.addCallback(MochiKit.Base.values);
|
||||
// deferredResult.addCallback(MochiKit.Base.flattenArguments);
|
||||
// deferredResult.addCallback(function(someValues) {
|
||||
// return MochiKit.Iter.some(someValues, MochiKit.Base.operator.identity);
|
||||
// });
|
||||
deferredResult.addCallback(Clipperz.Async.or);
|
||||
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'hasPendingChanges': function () {
|
||||
var deferredResult;
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("User.Header.RecordIndex.hasPendingChanges", {trace:false});
|
||||
deferredResult.collectResults({
|
||||
'recordsData': [
|
||||
MochiKit.Base.method(this, 'recordsData'),
|
||||
MochiKit.Base.methodcaller('hasPendingChanges')
|
||||
],
|
||||
'directLoginsData': [
|
||||
MochiKit.Base.method(this, 'directLoginsData'),
|
||||
MochiKit.Base.methodcaller('hasPendingChanges')
|
||||
]
|
||||
});
|
||||
deferredResult.addCallback(Clipperz.Async.or);
|
||||
// deferredResult.addCallback(MochiKit.Base.values);
|
||||
// deferredResult.addCallback(MochiKit.Base.flattenArguments);
|
||||
// deferredResult.addCallback(function(someValues) {
|
||||
// return MochiKit.Iter.some(someValues, MochiKit.Base.operator.identity);
|
||||
// });
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'commitTransientState': function () {
|
||||
var deferredResult;
|
||||
|
||||
deferredResut = Clipperz.Async.callbacks("User.Header.RecordIndex.commitTransientState", [
|
||||
MochiKit.Base.method(this, 'recordsData'),
|
||||
MochiKit.Base.methodcaller('commitTransientState'),
|
||||
|
||||
MochiKit.Base.method(this, 'directLoginsData'),
|
||||
MochiKit.Base.methodcaller('commitTransientState'),
|
||||
|
||||
MochiKit.Base.method(this, 'resetTransientState', true)
|
||||
], {trace:false});
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'revertChanges': function () {
|
||||
return Clipperz.Async.callbacks("User.Header.RecordIndex.revertChanges", [
|
||||
MochiKit.Base.method(this, 'recordsData'),
|
||||
MochiKit.Base.methodcaller('revertChanges'),
|
||||
|
||||
// MochiKit.Base.method(this, 'directLoginsData'),
|
||||
// MochiKit.Base.methodcaller('revertChanges'),
|
||||
|
||||
MochiKit.Base.method(this, 'records'),
|
||||
MochiKit.Base.bind(function (someRecords) {
|
||||
var recordReference;
|
||||
|
||||
for (recordReference in this.transientState().getValue('deleteRecordsReferences')) {
|
||||
this.recordsIndex()[recordReference] = this.transientState().getValue('deleteRecordsIndex' + '.' + recordReference);
|
||||
someRecords[recordReference] = this.transientState().getValue('deleteRecordsReferences' + '.' + recordReference);
|
||||
}
|
||||
|
||||
for (recordReference in this.transientState().getValue('newRecordsReferences')) {
|
||||
delete this.recordsIndex()[recordReference];
|
||||
delete someRecords[recordReference];
|
||||
}
|
||||
}, this),
|
||||
|
||||
// MochiKit.Base.method(this, 'directLogins'),
|
||||
MochiKit.Base.bind(function () {
|
||||
var directLoginReference;
|
||||
|
||||
// this.transientState().setValue('newDirectLoginReferences' + '.' + newDirectLogin.reference(), newDirectLogin);
|
||||
//
|
||||
// this.directLoginsIndex()[newDirectLogin.reference()] = newDirectLoginIndexValue;
|
||||
// this.directLoginsData().setValue(this.directLoginsIndex()[newDirectLogin.reference()], {'record': this.recordsIndex()[aRecord.reference()]});
|
||||
|
||||
|
||||
// for (directLoginReference in this.transientState().getValue('deleteDirectLoginReferences')) {
|
||||
// someDirectLogins[directLoginReference] = this.transientState().getValue('deleteDirectLoginReferences' + '.' + recordReference);
|
||||
// }
|
||||
|
||||
for (directLoginReference in this.transientState().getValue('newDirectLoginReferences')) {
|
||||
// this.directLoginsData().removeValue(this.directLoginsIndex()[directLoginReference]);
|
||||
delete this.directLoginsIndex()[directLoginReference];
|
||||
}
|
||||
}, this),
|
||||
|
||||
MochiKit.Base.method(this, 'directLoginsData'),
|
||||
MochiKit.Base.methodcaller('revertChanges'),
|
||||
|
||||
MochiKit.Base.method(this, 'resetTransientState', false)
|
||||
], {trace:false});
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'prepareRemoteDataWithKey': function (aKey) {
|
||||
// "records": {
|
||||
// "index": {
|
||||
// "eeda70e0392261967bda71c3764da78989c45bbd2bb7be6b941b90f81d9b81b5": "0",
|
||||
// "13a5e52976337ab210903cd04872588e1b21fb72bc183e91aa25c494b8138551": "1",
|
||||
// ...
|
||||
// "465a067a0bd2b470fa834de5397e38494de0c7707938262fae3427932e219744": "18",
|
||||
// "4fd1dc2ca860b7fb47cef10a84edb3270da05510b0a30a6b0b083898712d4b9e": "19"
|
||||
// },
|
||||
// "data": "n+AzGEEQXaSRSY4d ... BDypotrXgPo94uHfoXvGFzwCn8w="
|
||||
// },
|
||||
// "directLogins": {
|
||||
// "index": {
|
||||
// "61e87fdc4f1d9112e3b30c1f6812d095dcdb24f014c83319091eb6c9899ec348":"0",
|
||||
// "989593d4c48929f0c8f1581aa96969c622807e99619ed4732026e967530a68ad":"1",
|
||||
// ...
|
||||
// "cb9ae0bba1957075ccdbfd3b3481704d62087687a2ac7c411a4f07d444bde0f7":"17",
|
||||
// "7e1d069b7fa57c03bd7bf48807520feb953157834503aaff8c9d493f37dea69d":"18"
|
||||
// },
|
||||
// "data":"5YG9KKU/OZ5guUgFlms6k1 ... ZG/5Fn0uN+LoAsNfHm+EE62x"
|
||||
// },
|
||||
|
||||
var deferredResult;
|
||||
var result;
|
||||
|
||||
result = {};
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("User.Header.RecordIndex.prepareRemoteDataWithKey", {trace:false});
|
||||
deferredResult.collectResults({
|
||||
'index': MochiKit.Base.partial(MochiKit.Async.succeed, this.recordsIndex()),
|
||||
'data': [
|
||||
MochiKit.Base.method(this.recordsData(), 'prepareRemoteDataWithKey', aKey),
|
||||
MochiKit.Base.itemgetter('data')
|
||||
]
|
||||
});
|
||||
deferredResult.addCallback(Clipperz.Async.setItem, result, 'records');
|
||||
|
||||
deferredResult.collectResults({
|
||||
'index': MochiKit.Base.partial(MochiKit.Async.succeed, this.directLoginsIndex()),
|
||||
'data': [
|
||||
MochiKit.Base.method(this.directLoginsData(), 'prepareRemoteDataWithKey', aKey),
|
||||
MochiKit.Base.itemgetter('data')
|
||||
]
|
||||
});
|
||||
deferredResult.addCallback(Clipperz.Async.setItem, result, 'directLogins');
|
||||
|
||||
deferredResult.addCallback(MochiKit.Async.succeed, result);
|
||||
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'updateRecordKeyAndPrepareRemoteData': function (aRecord) {
|
||||
var newRecordKey;
|
||||
var deferredResult;
|
||||
|
||||
newRecordKey = Clipperz.PM.Crypto.randomKey();
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("User.Header.RecordIndex.updateRecordKeyAndPrepareRemoteData", {trace:false});
|
||||
deferredResult.addCallback(MochiKit.Base.method(aRecord, 'prepareRemoteDataWithKey', newRecordKey));
|
||||
deferredResult.addCallbackPass(MochiKit.Base.method(this, 'setRecordKey', aRecord.reference(), newRecordKey));
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//.........................................................................
|
||||
|
||||
'removeNewRecordWithNoChanges': function (aRecord) {
|
||||
var deferredResult;
|
||||
var recordReference;
|
||||
|
||||
recordReference = aRecord.reference();
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("User.Header.RecordIndex.removeNewRecordWithNoChanges", {trace:false});
|
||||
|
||||
deferredResult.addMethod(this.recordsData(), 'removeValue', this.recordsIndex()[recordReference]);
|
||||
deferredResult.addCallback(MochiKit.Base.bind(function () {
|
||||
delete this.recordsIndex()[recordReference];
|
||||
}, this));
|
||||
|
||||
deferredResult.addMethod(this, 'records');
|
||||
deferredResult.addCallback(MochiKit.Base.bind(function (someRecords) {
|
||||
delete someRecords[recordReference];
|
||||
}, this));
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//.........................................................................
|
||||
|
||||
'prepareRemoteDataForChangedRecords': function () {
|
||||
var deferredResult;
|
||||
var result;
|
||||
|
||||
result = {};
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("User.Header.RecordIndex.prepareRemoteDataForChangedRecords", {trace:false});
|
||||
|
||||
deferredResult.addMethod(this, 'records');
|
||||
deferredResult.addCallback(MochiKit.Base.values);
|
||||
deferredResult.addCallback(Clipperz.Async.deferredFilter, MochiKit.Base.methodcaller('isBrandNewWithNoPendingChanges'));
|
||||
deferredResult.addCallback(MochiKit.Base.map, MochiKit.Base.method(this, 'removeNewRecordWithNoChanges'));
|
||||
|
||||
deferredResult.addMethod(this, 'records');
|
||||
deferredResult.addCallback(MochiKit.Base.values);
|
||||
deferredResult.addCallback(Clipperz.Async.deferredFilter, MochiKit.Base.methodcaller('hasPendingChanges'));
|
||||
deferredResult.addCallback(MochiKit.Base.map, MochiKit.Base.method(this, 'updateRecordKeyAndPrepareRemoteData'));
|
||||
deferredResult.addCallback(Clipperz.Async.collectAll);
|
||||
|
||||
deferredResult.addCallback(Clipperz.Async.deferredIf("updated records != null", [
|
||||
MochiKit.Base.operator.identity
|
||||
], [
|
||||
MochiKit.Base.partial(MochiKit.Async.succeed, [])
|
||||
]));
|
||||
deferredResult.addCallback(Clipperz.Async.setItem, result, 'updated');
|
||||
|
||||
deferredResult.addMethod(this.transientState(), 'getValue', 'deleteRecordsReferences');
|
||||
deferredResult.addCallback(MochiKit.Base.keys);
|
||||
deferredResult.addCallback(Clipperz.Async.deferredIf("deleted records != null", [
|
||||
MochiKit.Base.operator.identity
|
||||
], [
|
||||
MochiKit.Base.partial(MochiKit.Async.succeed, [])
|
||||
]));
|
||||
deferredResult.addCallback(Clipperz.Async.setItem, result, 'deleted');
|
||||
|
||||
deferredResult.addCallback(MochiKit.Async.succeed, result);
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
__syntaxFix__: "syntax fix"
|
||||
});
|
||||
|
||||
|
||||
|
||||
Clipperz.PM.DataModel.User.Header.RecordIndex.invertIndex = function (anIndex) {
|
||||
var result;
|
||||
var key;
|
||||
|
||||
result = {};
|
||||
|
||||
for (key in anIndex) {
|
||||
result[anIndex[key]] = key;
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
53
frontend/delta/js/Clipperz/PM/DataModel/User.Subscription.js
Normal file
53
frontend/delta/js/Clipperz/PM/DataModel/User.Subscription.js
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
try { if (typeof(Clipperz.PM.DataModel.User) == 'undefined') { throw ""; }} catch (e) {
|
||||
throw "Clipperz.PM.DataModel.User.Subscription depends on Clipperz.PM.DataModel.User!";
|
||||
}
|
||||
|
||||
Clipperz.PM.DataModel.User.Subscription = function(args) {
|
||||
this._attributes = args;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
Clipperz.Base.extend(Clipperz.PM.DataModel.User.Subscription, Object, {
|
||||
|
||||
'features': function () {
|
||||
return this._attributes['features'];
|
||||
},
|
||||
|
||||
'type': function () {
|
||||
return this._attributes['type'];
|
||||
},
|
||||
|
||||
'validity': function () {
|
||||
return {
|
||||
'from': this._attributes['fromDate'],
|
||||
'to': this._attributes['toDate']
|
||||
};
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
__syntaxFix__: "syntax fix"
|
||||
});
|
||||
827
frontend/delta/js/Clipperz/PM/DataModel/User.js
Normal file
827
frontend/delta/js/Clipperz/PM/DataModel/User.js
Normal file
@@ -0,0 +1,827 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
|
||||
if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
|
||||
if (typeof(Clipperz.PM.DataModel) == 'undefined') { Clipperz.PM.DataModel = {}; }
|
||||
|
||||
|
||||
//#############################################################################
|
||||
|
||||
Clipperz.PM.DataModel.User = function (args) {
|
||||
args = args || {};
|
||||
|
||||
Clipperz.PM.DataModel.User.superclass.constructor.apply(this, arguments);
|
||||
|
||||
this._username = args.username || null;
|
||||
this._getPassphraseFunction = args.getPassphraseFunction || null;
|
||||
|
||||
this._data = null;
|
||||
|
||||
this._connection = null;
|
||||
this._connectionVersion = 'current';
|
||||
|
||||
this._subscription = null;
|
||||
this._serverData = null;
|
||||
// this._serverLockValue = null;
|
||||
this._transientState = null;
|
||||
|
||||
this._deferredLocks = {
|
||||
'passphrase': new MochiKit.Async.DeferredLock(),
|
||||
'serverData': new MochiKit.Async.DeferredLock(),
|
||||
// 'recordsIndex': new MochiKit.Async.DeferredLock(),
|
||||
// 'directLoginsIndex': new MochiKit.Async.DeferredLock()
|
||||
// 'preferences': new MochiKit.Async.DeferredLock()
|
||||
// 'oneTimePasswords': new MochiKit.Async.DeferredLock()
|
||||
'__syntaxFix__': 'syntax fix'
|
||||
};
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
Clipperz.Base.extend(Clipperz.PM.DataModel.User, Object, {
|
||||
|
||||
'toString': function () {
|
||||
return "Clipperz.PM.DataModel.User - " + this.username();
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'username': function () {
|
||||
return this._username;
|
||||
},
|
||||
|
||||
'setUsername': function (aValue) {
|
||||
this._username = aValue;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
// this.setSubscription(new Clipperz.PM.DataModel.User.Subscription(someServerData['subscription']));
|
||||
'subscription': function () {
|
||||
return this._subscription;
|
||||
},
|
||||
|
||||
'setSubscription': function (aValue) {
|
||||
this._subscription = aValue;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'displayName': function() {
|
||||
return "" + this.username() + "";
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'data': function () {
|
||||
if (this._data == null) {
|
||||
this._data = new Clipperz.KeyValueObjectStore(/*{'name':'User.data [1]'}*/);
|
||||
};
|
||||
|
||||
return this._data;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
'serverLockValue': function () {
|
||||
return this._serverLockValue;
|
||||
},
|
||||
|
||||
'setServerLockValue': function (aValue) {
|
||||
this._serverLockValue = aValue;
|
||||
},
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'transientState': function () {
|
||||
if (this._transientState == null) {
|
||||
this._transientState = {}
|
||||
}
|
||||
|
||||
return this._transientState;
|
||||
},
|
||||
|
||||
'resetTransientState': function (isCommitting) {
|
||||
this._transientState = null;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'deferredLockForSection': function(aSectionName) {
|
||||
return this._deferredLocks[aSectionName];
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'getPassphrase': function() {
|
||||
var deferredResult;
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("User.getPassphrase", {trace:false});
|
||||
deferredResult.acquireLock(this.deferredLockForSection('passphrase'));
|
||||
deferredResult.addMethod(this.data(), 'deferredGetOrSet', 'passphrase', this.getPassphraseFunction());
|
||||
deferredResult.releaseLock(this.deferredLockForSection('passphrase'));
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
'getPassphraseFunction': function () {
|
||||
return this._getPassphraseFunction;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'getCredentials': function () {
|
||||
return Clipperz.Async.collectResults("User; get username and passphrase", {
|
||||
'username': MochiKit.Base.method(this, 'username'),
|
||||
'password': MochiKit.Base.method(this, 'getPassphrase')
|
||||
}, {trace:false})();
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'changePassphrase': function (aNewValue) {
|
||||
return this.updateCredentials(this.username(), aNewValue);
|
||||
},
|
||||
|
||||
//.........................................................................
|
||||
|
||||
'updateCredentials': function (aUsername, aPassphrase) {
|
||||
var deferredResult;
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("User.updateCredentials", {trace:false});
|
||||
// deferredResult.addMethod(this, 'getPassphrase');
|
||||
// deferredResult.setValue('currentPassphrase');
|
||||
deferredResult.addMethod(this.connection(), 'ping');
|
||||
deferredResult.addMethod(this, 'setUsername', aUsername)
|
||||
deferredResult.acquireLock(this.deferredLockForSection('passphrase'));
|
||||
deferredResult.addMethod(this.data(), 'deferredGetOrSet', 'passphrase', aPassphrase);
|
||||
deferredResult.releaseLock(this.deferredLockForSection('passphrase'));
|
||||
// deferredResult.getValue('currentPassphrase');
|
||||
deferredResult.addMethod(this, 'prepareRemoteDataWithKey', aPassphrase);
|
||||
deferredResult.addMethod(this.connection(), 'updateCredentials', aUsername, aPassphrase);
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'initialSetupWithNoData': function () {
|
||||
this._serverData = {
|
||||
'version': '0.1',
|
||||
'statistics': "",
|
||||
'header': {
|
||||
'data': null,
|
||||
'version': Clipperz.PM.Crypto.encryptingFunctions.currentVersion,
|
||||
|
||||
'recordsIndex': new Clipperz.PM.DataModel.User.Header.RecordIndex({
|
||||
'retrieveKeyFunction': MochiKit.Base.method(this, 'getPassphrase'),
|
||||
'recordsData': {'data':null, 'index':{}},
|
||||
'recordsStats': null,
|
||||
'directLoginsData': {'data':null, 'index':{}},
|
||||
'encryptedDataVersion': Clipperz.PM.Crypto.encryptingFunctions.currentVersion,
|
||||
'retrieveRecordDetailFunction': MochiKit.Base.method(this, 'getRecordDetail')
|
||||
}),
|
||||
'preferences': new Clipperz.PM.DataModel.User.Header.Preferences({
|
||||
'name': 'preferences',
|
||||
'retrieveKeyFunction': MochiKit.Base.method(this, 'getPassphrase')
|
||||
}),
|
||||
'oneTimePasswords': new Clipperz.PM.DataModel.User.Header.OneTimePasswords({
|
||||
'name': 'preferences',
|
||||
'retrieveKeyFunction': MochiKit.Base.method(this, 'getPassphrase')
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
// this._serverLockValue = Clipperz.PM.Crypto.randomKey();
|
||||
},
|
||||
|
||||
//.........................................................................
|
||||
|
||||
'registerAsNewAccount': function () {
|
||||
var deferredResult;
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("User.registerAsNewAccount", {trace:false});
|
||||
// deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'updateProgress', {'extraSteps':3});
|
||||
deferredResult.addMethod(this, 'initialSetupWithNoData')
|
||||
deferredResult.addMethod(this, 'getPassphrase');
|
||||
deferredResult.addMethod(this, 'prepareRemoteDataWithKey');
|
||||
// deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'advanceProgress');
|
||||
deferredResult.addMethod(this.connection(), 'register');
|
||||
// deferredResult.addCallback(MochiKit.Base.itemgetter('lock'));
|
||||
// deferredResult.addMethod(this, 'setServerLockValue');
|
||||
// deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'userSuccessfullyRegistered');
|
||||
|
||||
// deferredResult.addErrback (MochiKit.Base.method(this, 'handleRegistrationFailure'));
|
||||
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'login': function () {
|
||||
var deferredResult;
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("User.login", {trace:false});
|
||||
// deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'updateProgress', {'extraSteps':3});
|
||||
deferredResult.addMethod(this, 'getPassphrase');
|
||||
deferredResult.addCallback(Clipperz.PM.DataModel.OneTimePassword.isValidOneTimePasswordValue);
|
||||
deferredResult.addCallback(Clipperz.Async.deferredIf("Is the passphrase an OTP", [
|
||||
// MochiKit.Base.partial(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'updateProgress', {'extraSteps':1}),
|
||||
MochiKit.Base.method(this, 'getCredentials'),
|
||||
MochiKit.Base.method(this.connection(), 'redeemOneTimePassword'),
|
||||
MochiKit.Base.method(this.data(), 'setValue', 'passphrase')
|
||||
], []));
|
||||
deferredResult.addErrback(MochiKit.Base.method(this, 'getPassphrase'));
|
||||
deferredResult.addMethod(this.connection(), 'login', false);
|
||||
deferredResult.addMethod(this, 'setupConnectionInfo');
|
||||
// deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'userSuccessfullyLoggedIn');
|
||||
deferredResult.addErrback (MochiKit.Base.method(this, 'handleConnectionFallback'));
|
||||
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//.........................................................................
|
||||
|
||||
'handleConnectionFallback': function(aValue) {
|
||||
var result;
|
||||
|
||||
//console.log("USER - handleConnectionFallback", aValue, aValue['isPermanent']);
|
||||
if (aValue instanceof MochiKit.Async.CancelledError) {
|
||||
result = aValue;
|
||||
} else if ((aValue['isPermanent'] === true) || (Clipperz.PM.Connection.communicationProtocol.fallbackVersions[this.connectionVersion()] == null)) {
|
||||
result = Clipperz.Async.callbacks("User.handleConnectionFallback - failed", [
|
||||
MochiKit.Base.method(this.data(), 'removeValue', 'passphrase'),
|
||||
MochiKit.Base.method(this, 'setConnectionVersion', 'current'),
|
||||
// MochiKit.Base.partial(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'userLoginFailed'),
|
||||
// MochiKit.Base.partial(MochiKit.Async.fail, Clipperz.PM.DataModel.User.exception.LoginFailed)
|
||||
MochiKit.Base.partial(MochiKit.Async.fail, aValue)
|
||||
], {trace:false});
|
||||
} else {
|
||||
this.setConnectionVersion(Clipperz.PM.Connection.communicationProtocol.fallbackVersions[this.connectionVersion()]);
|
||||
result = new Clipperz.Async.Deferred("User.handleConnectionFallback - retry");
|
||||
result.addMethod(this, 'login');
|
||||
result.callback();
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'setupConnectionInfo': function (aValue) {
|
||||
// this.setLoginInfo(aValue['loginInfo']);
|
||||
this.setSubscription(new Clipperz.PM.DataModel.User.Subscription(aValue['subscription']));
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'lock': function () {
|
||||
return Clipperz.Async.callbacks("User.lock", [
|
||||
MochiKit.Base.method(this, 'deleteAllCleanTextData')
|
||||
], {trace:false});
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'logout': function () {
|
||||
return Clipperz.Async.callbacks("User.logout", [
|
||||
MochiKit.Base.method(this, 'deleteAllCleanTextData'),
|
||||
MochiKit.Base.method(this.connection(), 'logout')
|
||||
], {trace:false});
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'headerFormatVersion': function(anHeader) {
|
||||
var result;
|
||||
|
||||
if (anHeader.charAt(0) == '{') {
|
||||
var headerData;
|
||||
|
||||
headerData = Clipperz.Base.evalJSON(anHeader);
|
||||
result = headerData['version'];
|
||||
} else {
|
||||
result = 'LEGACY';
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'unpackServerData': function (someServerData) {
|
||||
var unpackedData;
|
||||
var headerVersion;
|
||||
|
||||
var recordsIndex;
|
||||
var preferences;
|
||||
var oneTimePasswords;
|
||||
|
||||
// this.setServerLockValue(someServerData['lock']);
|
||||
|
||||
headerVersion = this.headerFormatVersion(someServerData['header']);
|
||||
switch (headerVersion) {
|
||||
case 'LEGACY':
|
||||
var legacyHeader;
|
||||
|
||||
legacyHeader = new Clipperz.PM.DataModel.User.Header.Legacy({
|
||||
'retrieveKeyFunction': MochiKit.Base.method(this, 'getPassphrase'),
|
||||
'remoteData': {
|
||||
'data': someServerData['header'],
|
||||
'version': someServerData['version'],
|
||||
'recordsStats': someServerData['recordsStats']
|
||||
},
|
||||
// 'encryptedDataKeypath': 'data',
|
||||
// 'encryptedVersionKeypath': 'version',
|
||||
'retrieveRecordDetailFunction': MochiKit.Base.method(this, 'getRecordDetail')
|
||||
});
|
||||
|
||||
recordsIndex = legacyHeader;
|
||||
preferences = legacyHeader;
|
||||
oneTimePasswords = legacyHeader;
|
||||
break;
|
||||
case '0.1':
|
||||
var headerData;
|
||||
|
||||
headerData = Clipperz.Base.evalJSON(someServerData['header']);
|
||||
|
||||
recordsIndex = new Clipperz.PM.DataModel.User.Header.RecordIndex({
|
||||
'retrieveKeyFunction': MochiKit.Base.method(this, 'getPassphrase'),
|
||||
'recordsData': headerData['records'],
|
||||
'recordsStats': someServerData['recordsStats'],
|
||||
'directLoginsData': headerData['directLogins'],
|
||||
'encryptedDataVersion': someServerData['version'],
|
||||
'retrieveRecordDetailFunction': MochiKit.Base.method(this, 'getRecordDetail')
|
||||
});
|
||||
|
||||
// Still missing a test case that actually fais with the old version of the code, where the check for undefined was missing
|
||||
if (typeof(headerData['preferences']) != 'undefined') {
|
||||
preferences = new Clipperz.PM.DataModel.User.Header.Preferences({
|
||||
'name': 'preferences',
|
||||
'retrieveKeyFunction': MochiKit.Base.method(this, 'getPassphrase'),
|
||||
'remoteData': {
|
||||
'data': headerData['preferences']['data'],
|
||||
'version': someServerData['version']
|
||||
}
|
||||
});
|
||||
} else {
|
||||
preferences = new Clipperz.PM.DataModel.User.Header.Preferences({
|
||||
'name': 'preferences',
|
||||
'retrieveKeyFunction': MochiKit.Base.method(this, 'getPassphrase')
|
||||
});
|
||||
}
|
||||
|
||||
if (typeof(headerData['oneTimePasswords']) != 'undefined') {
|
||||
oneTimePasswords = new Clipperz.PM.DataModel.User.Header.OneTimePasswords({
|
||||
'name': 'preferences',
|
||||
'retrieveKeyFunction': MochiKit.Base.method(this, 'getPassphrase'),
|
||||
'remoteData': {
|
||||
'data': headerData['oneTimePasswords']['data'],
|
||||
'version': someServerData['version']
|
||||
}
|
||||
});
|
||||
} else {
|
||||
oneTimePasswords = new Clipperz.PM.DataModel.User.Header.OneTimePasswords({
|
||||
'name': 'preferences',
|
||||
'retrieveKeyFunction': MochiKit.Base.method(this, 'getPassphrase')
|
||||
});
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
unpackedData = {
|
||||
'version': someServerData['version'],
|
||||
'statistics': someServerData['statistics'],
|
||||
'header': {
|
||||
'data': someServerData['header'],
|
||||
'version': headerVersion,
|
||||
|
||||
'recordsIndex': recordsIndex,
|
||||
'preferences': preferences,
|
||||
'oneTimePasswords': oneTimePasswords
|
||||
}
|
||||
};
|
||||
|
||||
this._serverData = unpackedData;
|
||||
|
||||
return this._serverData;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'getServerData': function() {
|
||||
var deferredResult;
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("User.getServerData", {trace:false});
|
||||
deferredResult.acquireLock(this.deferredLockForSection('serverData'));
|
||||
deferredResult.addCallback(MochiKit.Base.bind(function(aResult) {
|
||||
var innerDeferredResult;
|
||||
|
||||
innerDeferredResult = new Clipperz.Async.Deferred("User.getUserDetails.innerDeferred", {trace:false});
|
||||
if (this._serverData == null) {
|
||||
innerDeferredResult.addCallbackPass(MochiKit.Signal.signal, this, 'loadingUserDetails');
|
||||
innerDeferredResult.addMethod(this.connection(), 'message', 'getUserDetails');
|
||||
innerDeferredResult.addMethod(this, 'unpackServerData');
|
||||
innerDeferredResult.addCallbackPass(MochiKit.Signal.signal, this, 'loadedUserDetails');
|
||||
}
|
||||
|
||||
innerDeferredResult.addCallback(MochiKit.Base.bind(function () {
|
||||
return this._serverData;
|
||||
},this));
|
||||
innerDeferredResult.callback();
|
||||
|
||||
return innerDeferredResult;
|
||||
}, this));
|
||||
deferredResult.releaseLock(this.deferredLockForSection('serverData'));
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'connectionVersion': function() {
|
||||
return this._connectionVersion;
|
||||
},
|
||||
|
||||
'setConnectionVersion': function(aValue) {
|
||||
if (this._connectionVersion != aValue) {
|
||||
this.resetConnection();
|
||||
}
|
||||
this._connectionVersion = aValue;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'connection': function() {
|
||||
if ((this._connection == null) && (this.connectionVersion() != null) ){
|
||||
this._connection = new Clipperz.PM.Connection.communicationProtocol.versions[this.connectionVersion()]({
|
||||
getCredentialsFunction: MochiKit.Base.method(this, 'getCredentials')
|
||||
});
|
||||
}
|
||||
|
||||
return this._connection;
|
||||
},
|
||||
|
||||
'resetConnection': function(aValue) {
|
||||
if (this._connection != null) {
|
||||
this._connection.reset();
|
||||
}
|
||||
|
||||
this._connection = null;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'getHeaderIndex': function (aKey) {
|
||||
return Clipperz.Async.callbacks("User.getHeaderIndex", [
|
||||
MochiKit.Base.method(this, 'getServerData'),
|
||||
MochiKit.Base.itemgetter('header'),
|
||||
MochiKit.Base.itemgetter(aKey)
|
||||
], {trace:false})
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'getRecords': function () {
|
||||
return Clipperz.Async.callbacks("User.getRecords", [
|
||||
MochiKit.Base.method(this, 'getHeaderIndex', 'recordsIndex'),
|
||||
MochiKit.Base.methodcaller('records'),
|
||||
MochiKit.Base.values
|
||||
], {trace:false});
|
||||
},
|
||||
|
||||
'recordWithLabel': function (aLabel) {
|
||||
return Clipperz.Async.callbacks("User.recordWithLabel", [
|
||||
MochiKit.Base.method(this, 'getRecords'),
|
||||
MochiKit.Base.partial(Clipperz.Async.deferredFilter, function (aRecord) {
|
||||
return Clipperz.Async.callbacks("User.recordWithLabel - check record label", [
|
||||
MochiKit.Base.methodcaller('label'),
|
||||
MochiKit.Base.partial(MochiKit.Base.operator.eq, aLabel)
|
||||
], {trace:false}, aRecord);
|
||||
}),
|
||||
function (someFilteredResults) {
|
||||
var result;
|
||||
|
||||
switch (someFilteredResults.length) {
|
||||
case 0:
|
||||
result = null;
|
||||
break;
|
||||
case 1:
|
||||
result = someFilteredResults[0];
|
||||
break;
|
||||
default:
|
||||
WTF = TODO;
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
], {trace:false});
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'getRecord': function (aRecordReference) {
|
||||
return Clipperz.Async.callbacks("User.getRecord", [
|
||||
MochiKit.Base.method(this, 'getHeaderIndex', 'recordsIndex'),
|
||||
MochiKit.Base.methodcaller('records'),
|
||||
MochiKit.Base.itemgetter(aRecordReference),
|
||||
|
||||
Clipperz.Async.deferredIf("record != null", [
|
||||
MochiKit.Base.operator.identity
|
||||
], [
|
||||
function () { throw "Record does not exists"}
|
||||
])
|
||||
], {trace:false});
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'getRecordDetail': function (aRecordReference) {
|
||||
return this.connection().message('getRecordDetail', {reference: aRecordReference});
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'deleteRecord': function (aRecord) {
|
||||
return Clipperz.Async.callbacks("User.deleteRecord", [
|
||||
MochiKit.Base.method(this, 'getHeaderIndex', 'recordsIndex'),
|
||||
MochiKit.Base.methodcaller('deleteRecord', aRecord)
|
||||
], {trace:false});
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'createNewRecord': function () {
|
||||
return Clipperz.Async.callbacks("User.createNewRecord", [
|
||||
MochiKit.Base.method(this, 'getHeaderIndex', 'recordsIndex'),
|
||||
MochiKit.Base.methodcaller('createNewRecord')
|
||||
], {trace:false});
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'getDirectLogins': function() {
|
||||
var deferredResult;
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("User.getDirectLogins", {trace:false});
|
||||
deferredResult.addMethod(this, 'getRecords');
|
||||
deferredResult.addCallback(MochiKit.Base.map, MochiKit.Base.compose(MochiKit.Base.values, MochiKit.Base.methodcaller('directLogins')));
|
||||
deferredResult.addCallback(MochiKit.Base.flattenArray);
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'getOneTimePasswords': function () {
|
||||
return Clipperz.Async.callbacks("User.getOneTimePasswords", [
|
||||
MochiKit.Base.method(this, 'getHeaderIndex', 'oneTimePasswords'),
|
||||
MochiKit.Base.methodcaller('oneTimePasswords'),
|
||||
MochiKit.Base.values
|
||||
], {trace:false});
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'invokeMethodNamedOnHeader': function (aMethodName, aValue) {
|
||||
return Clipperz.Async.collectResults("User.invokeMethodNamedOnHeader [" + aMethodName + "]", {
|
||||
'recordIndex': [
|
||||
MochiKit.Base.method(this, 'getHeaderIndex', 'recordsIndex'),
|
||||
MochiKit.Base.methodcaller(aMethodName, aValue)
|
||||
],
|
||||
'preferences': [
|
||||
MochiKit.Base.method(this, 'getHeaderIndex', 'preferences'),
|
||||
MochiKit.Base.methodcaller(aMethodName, aValue)
|
||||
],
|
||||
'oneTimePasswords': [
|
||||
MochiKit.Base.method(this, 'getHeaderIndex', 'oneTimePasswords'),
|
||||
MochiKit.Base.methodcaller(aMethodName, aValue)
|
||||
]//,
|
||||
// 'statistics': [
|
||||
// MochiKit.Base.method(this, 'getStatistics'),
|
||||
// MochiKit.Base.methodcaller(aMethodName, aValue)
|
||||
// ]
|
||||
}, {trace:false})();
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'invokeMethodNamedOnRecords': function (aMethodName, aValue) {
|
||||
return Clipperz.Async.callbacks("User.invokeMethodNamedOnRecords[" + aMethodName + "]", [
|
||||
MochiKit.Base.method(this, 'getRecords'),
|
||||
MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.methodcaller(aMethodName, aValue)),
|
||||
Clipperz.Async.collectAll
|
||||
], {trace:false});
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'hasPendingChanges': function () {
|
||||
var deferredResult;
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("User.hasPendingChanges", {trace:false});
|
||||
deferredResult.collectResults({
|
||||
'header': [
|
||||
MochiKit.Base.method(this, 'invokeMethodNamedOnHeader', 'hasPendingChanges'),
|
||||
MochiKit.Base.values
|
||||
],
|
||||
'records': MochiKit.Base.method(this, 'invokeMethodNamedOnRecords', 'hasPendingChanges')
|
||||
});
|
||||
deferredResult.addCallback(Clipperz.Async.or);
|
||||
deferredResult.callback();
|
||||
// recordsIndex = legacyHeader;
|
||||
// preferences = legacyHeader;
|
||||
// oneTimePasswords = legacyHeader;
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'commitTransientState': function () {
|
||||
return Clipperz.Async.callbacks("User.commitTransientState", [
|
||||
MochiKit.Base.method(this, 'invokeMethodNamedOnHeader', 'commitTransientState'),
|
||||
MochiKit.Base.method(this, 'invokeMethodNamedOnRecords', 'commitTransientState'),
|
||||
|
||||
MochiKit.Base.method(this, 'transientState'),
|
||||
// MochiKit.Base.itemgetter('lock'),
|
||||
// MochiKit.Base.method(this, 'setServerLockValue'),
|
||||
MochiKit.Base.method(this, 'resetTransientState', true)
|
||||
], {trace:false});
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'revertChanges': function () {
|
||||
return Clipperz.Async.callbacks("User.revertChanges", [
|
||||
MochiKit.Base.method(this, 'invokeMethodNamedOnHeader', 'revertChanges'),
|
||||
MochiKit.Base.method(this, 'invokeMethodNamedOnRecords', 'revertChanges'),
|
||||
MochiKit.Base.method(this, 'resetTransientState', false)
|
||||
], {trace:false});
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'deleteAllCleanTextData': function () {
|
||||
return Clipperz.Async.callbacks("User.deleteAllCleanTextData", [
|
||||
MochiKit.Base.method(this, 'invokeMethodNamedOnRecords', 'deleteAllCleanTextData'),
|
||||
MochiKit.Base.method(this, 'invokeMethodNamedOnHeader', 'deleteAllCleanTextData'),
|
||||
|
||||
MochiKit.Base.method(this.data(), 'removeAllData'),
|
||||
MochiKit.Base.method(this, 'resetTransientState', false)
|
||||
], {trace:false});
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'hasAnyCleanTextData': function () {
|
||||
var deferredResult;
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("User.hasAnyCleanTextData", {trace:false});
|
||||
deferredResult.collectResults({
|
||||
'header': [
|
||||
MochiKit.Base.method(this, 'invokeMethodNamedOnHeader', 'hasAnyCleanTextData'),
|
||||
MochiKit.Base.values
|
||||
],
|
||||
'records': MochiKit.Base.method(this, 'invokeMethodNamedOnRecords', 'hasAnyCleanTextData'),
|
||||
'data': MochiKit.Base.bind(function () {
|
||||
return MochiKit.Async.succeed(! this.data().isEmpty());
|
||||
}, this),
|
||||
'transientState': MochiKit.Base.bind(function () {
|
||||
return MochiKit.Async.succeed(MochiKit.Base.keys(this.transientState()).length != 0);
|
||||
}, this)
|
||||
});
|
||||
deferredResult.addCallback(Clipperz.Async.or);
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'prepareRemoteDataWithKey': function (aKey /*, aCurrentKey*/) {
|
||||
var deferredResult;
|
||||
var result;
|
||||
|
||||
result = {};
|
||||
deferredResult = new Clipperz.Async.Deferred("User.prepareRemoteDataWithKey", {trace:false});
|
||||
deferredResult.addMethod(this, 'invokeMethodNamedOnHeader', 'prepareRemoteDataWithKey', aKey /*, aCurrentKey*/);
|
||||
deferredResult.addCallback(MochiKit.Base.bind(function (aResult, someHeaderPackedData) {
|
||||
var header;
|
||||
|
||||
header = {};
|
||||
header['records'] = someHeaderPackedData['recordIndex']['records'];
|
||||
header['directLogins'] = someHeaderPackedData['recordIndex']['directLogins'];
|
||||
header['preferences'] = {'data': someHeaderPackedData['preferences']['data']};
|
||||
header['oneTimePasswords'] = {'data': someHeaderPackedData['oneTimePasswords']['data']};
|
||||
header['version'] = '0.1';
|
||||
|
||||
aResult['header'] = Clipperz.Base.serializeJSON(header);
|
||||
aResult['statistics'] = this._serverData['statistics']; // "someHeaderPackedData['statistics']['data']";
|
||||
|
||||
return aResult;
|
||||
}, this), result);
|
||||
deferredResult.addCallback(Clipperz.Async.setItem, result, 'version', Clipperz.PM.Crypto.encryptingFunctions.currentVersion);
|
||||
// deferredResult.addCallback(Clipperz.Async.setItem, result, 'lock', this.serverLockValue());
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'saveChanges': function () {
|
||||
var deferredResult;
|
||||
var messageParameters;
|
||||
|
||||
messageParameters = {};
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("User.saveChangaes", {trace:false});
|
||||
|
||||
deferredResult.addMethod(this, 'getHeaderIndex', 'recordsIndex');
|
||||
deferredResult.addCallback(MochiKit.Base.methodcaller('prepareRemoteDataForChangedRecords'));
|
||||
deferredResult.addCallback(Clipperz.Async.setItem, messageParameters, 'records');
|
||||
// deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'advanceProgress');
|
||||
|
||||
deferredResult.addMethod(this, 'getPassphrase');
|
||||
deferredResult.addMethod(this, 'prepareRemoteDataWithKey');
|
||||
deferredResult.addCallback(Clipperz.Async.setItem, messageParameters, 'user');
|
||||
// deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'advanceProgress');
|
||||
|
||||
deferredResult.addCallback(MochiKit.Async.succeed, messageParameters);
|
||||
deferredResult.addMethod(this.connection(), 'message', 'saveChanges');
|
||||
deferredResult.addCallback(MochiKit.Base.update, this.transientState())
|
||||
// deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'advanceProgress');
|
||||
|
||||
deferredResult.addMethod(this, 'commitTransientState');
|
||||
// deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'advanceProgress');
|
||||
// deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'userDataSuccessfullySaved');
|
||||
|
||||
deferredResult.addErrbackPass(MochiKit.Base.method(this, 'revertChanges'));
|
||||
// deferredResult.addErrbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'failureWhileSavingUserData');
|
||||
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
__syntaxFix__: "syntax fix"
|
||||
});
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
Clipperz.PM.DataModel.User.registerNewAccount = function (anUsername, aPassphraseFunction) {
|
||||
var deferredResult;
|
||||
var user;
|
||||
|
||||
user = new Clipperz.PM.DataModel.User({'username':anUsername, 'getPassphraseFunction':aPassphraseFunction});
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("Clipperz.PM.DataModel.User.registerNewAccount", {trace:false});
|
||||
deferredResult.addMethod(user, 'registerAsNewAccount');
|
||||
deferredResult.addMethod(user, 'login');
|
||||
deferredResult.addCallback(MochiKit.Async.succeed, user);
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
Clipperz.PM.DataModel.User.exception = {
|
||||
LoginFailed: new MochiKit.Base.NamedError("Clipperz.PM.DataModel.User.exception.LoginFailed"),
|
||||
CredentialUpgradeFailed: new MochiKit.Base.NamedError("Clipperz.PM.DataModel.User.exception.CredentialUpgradeFailed")
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
196
frontend/delta/js/Clipperz/PM/Date.js
Normal file
196
frontend/delta/js/Clipperz/PM/Date.js
Normal file
@@ -0,0 +1,196 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
|
||||
if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
|
||||
if (typeof(Clipperz.PM.Date) == 'undefined') { Clipperz.PM.Date = {}; }
|
||||
|
||||
Clipperz.PM.Date.VERSION = "0.1";
|
||||
Clipperz.PM.Date.NAME = "Clipperz.PM.Date";
|
||||
|
||||
MochiKit.Base.update(Clipperz.PM.Date, {
|
||||
|
||||
'__repr__': function () {
|
||||
return "[" + this.NAME + " " + this.VERSION + "]";
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'toString': function () {
|
||||
return this.__repr__();
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'locale': function() {
|
||||
return {
|
||||
'amDesignation': Clipperz.PM.Strings.getValue('calendarStrings.amDesignation'),
|
||||
'pmDesignation': Clipperz.PM.Strings.getValue('calendarStrings.pmDesignation'),
|
||||
'days': Clipperz.PM.Strings.getValue('calendarStrings.days'),
|
||||
'shortDays': Clipperz.PM.Strings.getValue('calendarStrings.shortDays'),
|
||||
'shortMonths': Clipperz.PM.Strings.getValue('calendarStrings.shortMonths'),
|
||||
'months': Clipperz.PM.Strings.getValue('calendarStrings.months')
|
||||
}
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
/*
|
||||
'formatDateWithPHPLikeTemplate': function(aDate, aTemplate) {
|
||||
return Clipperz.Date.formatDateWithPHPLikeTemplateAndLocale(aDate, aTemplate, Clipperz.PM.Date.locale());
|
||||
},
|
||||
|
||||
'parseDateWithPHPLikeTemplate': function(aDate, aTemplate) {
|
||||
return Clipperz.Date.parseDateWithPHPTemplateAndLocale(aDate, aTemplate, Clipperz.PM.Date.locale());
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'formatDateWithJavaLikeTemplate': function(aDate, aTemplate) {
|
||||
return Clipperz.Date.formatDateWithJavaLikeTemplateAndLocale(aDate, aTemplate, Clipperz.PM.Date.locale());
|
||||
},
|
||||
|
||||
'parseDateWithJavaLikeTemplate': function(aDate, aTemplate) {
|
||||
return Clipperz.Date.parseDateWithJavaLikeTemplateAndLocale(aDate, aTemplate, Clipperz.PM.Date.locale());
|
||||
},
|
||||
*/
|
||||
//=========================================================================
|
||||
|
||||
'formatWithTemplate': function (aTemplate, aDate) {
|
||||
return Clipperz.PM.Date.formatDateWithTemplate(aDate, aTemplate);
|
||||
},
|
||||
|
||||
'formatDateWithTemplate': function(aDate, aTemplate) {
|
||||
var result;
|
||||
|
||||
if (aDate == null) {
|
||||
result = ""
|
||||
} else {
|
||||
result = Clipperz.Date.formatDateWithPHPLikeTemplateAndLocale(aDate, aTemplate, Clipperz.PM.Date.locale());
|
||||
};
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
'parseDateWithTemplate': function(aValue, aTemplate) {
|
||||
return Clipperz.Date.parseDateWithPHPTemplateAndLocale(aValue, aTemplate, Clipperz.PM.Date.locale());
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'formatDateWithUTCFormat': function(aDate) {
|
||||
return Clipperz.Date.formatDateWithUTCFormatAndLocale(aDate, Clipperz.PM.Date.locale());
|
||||
},
|
||||
|
||||
'parseDateWithUTCFormat': function(aValue) {
|
||||
var result;
|
||||
|
||||
if (aValue == null) {
|
||||
result = null;
|
||||
} else {
|
||||
result = Clipperz.Date.parseDateWithUTCFormatAndLocale(aValue, Clipperz.PM.Date.locale());
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'getElapsedTimeDescription': function(aDate) {
|
||||
var result;
|
||||
|
||||
result = ""
|
||||
|
||||
if (aDate != null) {
|
||||
var now;
|
||||
var elapsedTime;
|
||||
|
||||
var millisencondsInAMinute;
|
||||
var millisencondsInAnHour;
|
||||
var millisencondsInADay;
|
||||
var millisencondsInAWeek;
|
||||
var millisencondsInAMonth;
|
||||
|
||||
now = new Date();
|
||||
elapsedTime = now.getTime() - aDate.getTime();
|
||||
|
||||
millisencondsInAMinute = 60 * 1000;
|
||||
millisencondsInAnHour = millisencondsInAMinute * 60;
|
||||
millisencondsInADay = millisencondsInAnHour * 24;
|
||||
millisencondsInAWeek = millisencondsInADay * 7;
|
||||
millisencondsInAMonth = millisencondsInAWeek * 5;
|
||||
|
||||
if ((elapsedTime / millisencondsInAMonth) > 1) {
|
||||
result = Clipperz.PM.Strings.getValue('elapsedTimeDescriptions.MORE_THAN_A_MONTH_AGO');
|
||||
} else if ((elapsedTime / millisencondsInAWeek) > 1) {
|
||||
var elapsedWeeks;
|
||||
|
||||
elapsedWeeks = Math.floor((elapsedTime / millisencondsInAWeek));
|
||||
if (elapsedWeeks == 1) {
|
||||
result = Clipperz.PM.Strings.getValue('elapsedTimeDescriptions.MORE_THAN_A_WEEK_AGO');
|
||||
} else {
|
||||
result = Clipperz.PM.Strings.getValue('elapsedTimeDescriptions.MORE_THAN_*_WEEKS_AGO').replace(/__elapsed__/, elapsedWeeks);
|
||||
}
|
||||
} else if ((elapsedTime / millisencondsInADay) > 1) {
|
||||
var elapsedDays;
|
||||
|
||||
elapsedDays = Math.floor((elapsedTime / millisencondsInADay));
|
||||
if (elapsedDays == 1) {
|
||||
result = Clipperz.PM.Strings.getValue('elapsedTimeDescriptions.YESTERDAY');
|
||||
} else {
|
||||
result = Clipperz.PM.Strings.getValue('elapsedTimeDescriptions.*_DAYS_AGO').replace(/__elapsed__/, elapsedDays);
|
||||
}
|
||||
} else if ((elapsedTime / millisencondsInAnHour) > 1) {
|
||||
var elapsedHours;
|
||||
|
||||
elapsedHours = Math.floor((elapsedTime / millisencondsInAnHour));
|
||||
if (elapsedHours == 1) {
|
||||
result = Clipperz.PM.Strings.getValue('elapsedTimeDescriptions.ABOUT_AN_HOUR_AGO');
|
||||
} else {
|
||||
result = Clipperz.PM.Strings.getValue('elapsedTimeDescriptions.*_HOURS_AGO').replace(/__elapsed__/, elapsedHours);
|
||||
}
|
||||
} else {
|
||||
var elapsed10Minutes;
|
||||
|
||||
elapsed10Minutes = (Math.floor((elapsedTime / millisencondsInAMinute) / 10)) * 10;
|
||||
if (elapsed10Minutes == 0) {
|
||||
result = Clipperz.PM.Strings.getValue('elapsedTimeDescriptions.JUST_A_FEW_MINUTES_AGO');
|
||||
} else {
|
||||
result = Clipperz.PM.Strings.getValue('elapsedTimeDescriptions.ABOUT_*_MINUTES_AGO').replace(/__elapsed__/, elapsed10Minutes+"");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'parse': function (aValue) {
|
||||
return Clipperz.PM.Date.parseDateWithUTCFormat(aValue);
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
__syntaxFix__: "syntax fix"
|
||||
|
||||
});
|
||||
|
||||
132
frontend/delta/js/Clipperz/PM/PIN.js
Normal file
132
frontend/delta/js/Clipperz/PM/PIN.js
Normal file
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
|
||||
if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
|
||||
if (typeof(Clipperz.PM.PIN) == 'undefined') { Clipperz.PM.PIN = {}; }
|
||||
|
||||
MochiKit.Base.update(Clipperz.PM.PIN, {
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'__repr__': function () {
|
||||
return "[" + this.NAME + " " + this.VERSION + "]";
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'toString': function () {
|
||||
return this.__repr__();
|
||||
},
|
||||
|
||||
'CREDENTIALS': 'CLIPPERZ.CREDENTIALS',
|
||||
'FAILURE_COUNT': 'CLIPPERZ.FAILED_LOGIN_COUNT',
|
||||
'ALLOWED_RETRY': 3,
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'isSet': function () {
|
||||
return (this.storedCredentials() != null);
|
||||
},
|
||||
|
||||
'storedCredentials': function () {
|
||||
return localStorage[this.CREDENTIALS];
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'recordFailedAttempt': function () {
|
||||
var failureCount;
|
||||
var result;
|
||||
|
||||
failureCount = localStorage[this.FAILURE_COUNT];
|
||||
|
||||
if (failureCount == null) {
|
||||
failureCount = 0
|
||||
}
|
||||
|
||||
failureCount ++;
|
||||
|
||||
if (failureCount < this.ALLOWED_RETRY) {
|
||||
localStorage[this.FAILURE_COUNT] = failureCount;
|
||||
result = failureCount;
|
||||
} else {
|
||||
this.removeLocalCredentials();
|
||||
result = -1;
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
'resetFailedAttemptCount': function () {
|
||||
localStorage.removeItem(this.FAILURE_COUNT);
|
||||
},
|
||||
|
||||
'failureCount': function () {
|
||||
return localStorage[this.FAILURE_COUNT];
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'deriveKeyFromPin': function (aPIN) {
|
||||
return Clipperz.Crypto.SHA.sha256(new Clipperz.ByteArray(aPIN));
|
||||
},
|
||||
|
||||
'credentialsWithPIN': function (aPIN) {
|
||||
var byteArrayValue;
|
||||
var decryptedValue;
|
||||
var result;
|
||||
|
||||
byteArrayValue = (new Clipperz.ByteArray()).appendBase64String(localStorage[this.CREDENTIALS]);
|
||||
decryptedValue = Clipperz.Crypto.AES.decrypt(this.deriveKeyFromPin(aPIN), byteArrayValue).asString();
|
||||
try {
|
||||
result = Clipperz.Base.evalJSON(decryptedValue);
|
||||
} catch (error) {
|
||||
result = {'username':'fakeusername', 'passphrase':'fakepassphrase'};
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
'setCredentialsWithPIN': function (aPIN, someCredentials) {
|
||||
var encodedValue;
|
||||
var byteArrayValue;
|
||||
var encryptedValue;
|
||||
|
||||
encodedValue = Clipperz.Base.serializeJSON(someCredentials);
|
||||
byteArrayValue = new Clipperz.ByteArray(encodedValue);
|
||||
encryptedValue = Clipperz.Crypto.AES.encrypt(this.deriveKeyFromPin(aPIN), byteArrayValue).toBase64String();
|
||||
|
||||
localStorage[this.CREDENTIALS] = encryptedValue;
|
||||
},
|
||||
|
||||
'removeLocalCredentials': function () {
|
||||
localStorage.removeItem(this.CREDENTIALS);
|
||||
localStorage.removeItem(this.FAILURE_COUNT);
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
__syntaxFix__: "syntax fix"
|
||||
|
||||
});
|
||||
|
||||
186
frontend/delta/js/Clipperz/PM/Proxy.js
Normal file
186
frontend/delta/js/Clipperz/PM/Proxy.js
Normal file
@@ -0,0 +1,186 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
|
||||
if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
|
||||
|
||||
//=============================================================================
|
||||
|
||||
Clipperz.PM.Proxy = function(args) {
|
||||
args = args || {};
|
||||
|
||||
this._shouldPayTolls = args.shouldPayTolls || false;
|
||||
|
||||
this._tolls = {
|
||||
'CONNECT': [],
|
||||
'REGISTER': [],
|
||||
'MESSAGE': []
|
||||
};
|
||||
|
||||
if (args.isDefault === true) {
|
||||
Clipperz.PM.Proxy.defaultProxy = this;
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
Clipperz.PM.Proxy.prototype = MochiKit.Base.update(null, {
|
||||
|
||||
'toString': function() {
|
||||
return "Clipperz.PM.Proxy";
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'shouldPayTolls': function() {
|
||||
return this._shouldPayTolls;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'tolls': function() {
|
||||
return this._tolls;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'payToll': function(aRequestType, someParameters) {
|
||||
var deferredResult;
|
||||
|
||||
if (this.shouldPayTolls()) {
|
||||
deferredResult = new Clipperz.Async.Deferred("Proxy.payToll", {trace:false});
|
||||
|
||||
if (this.tolls()[aRequestType].length == 0) {
|
||||
deferredResult.addMethod(this, 'sendMessage', 'knock', {requestType:aRequestType});
|
||||
deferredResult.addMethod(this, 'setTollCallback');
|
||||
}
|
||||
deferredResult.addMethod(this.tolls()[aRequestType], 'pop');
|
||||
deferredResult.addCallback(MochiKit.Base.methodcaller('deferredPay'));
|
||||
deferredResult.addCallback(function(aToll) {
|
||||
var result;
|
||||
|
||||
result = {
|
||||
parameters: someParameters,
|
||||
toll: aToll
|
||||
}
|
||||
|
||||
return result;
|
||||
});
|
||||
|
||||
deferredResult.callback();
|
||||
} else {
|
||||
deferredResult = MochiKit.Async.succeed({parameters:someParameters});
|
||||
}
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'addToll': function(aToll) {
|
||||
this.tolls()[aToll.requestType()].push(aToll);
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'setTollCallback': function(someParameters) {
|
||||
if (typeof(someParameters['toll']) != 'undefined') {
|
||||
this.addToll(new Clipperz.PM.Toll(someParameters['toll']));
|
||||
}
|
||||
|
||||
return someParameters['result'];
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'registration': function (someParameters) {
|
||||
return this.processMessage('registration', someParameters, 'REGISTER');
|
||||
},
|
||||
|
||||
'handshake': function (someParameters) {
|
||||
return this.processMessage('handshake', someParameters, 'CONNECT');
|
||||
},
|
||||
|
||||
'message': function (someParameters) {
|
||||
return this.processMessage('message', someParameters, 'MESSAGE');
|
||||
},
|
||||
|
||||
'logout': function (someParameters) {
|
||||
return this.processMessage('logout', someParameters, 'MESSAGE');
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'processMessage': function (aFunctionName, someParameters, aRequestType) {
|
||||
var deferredResult;
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("Proxy.processMessage", {trace:false});
|
||||
deferredResult.addMethod(this, 'payToll', aRequestType);
|
||||
deferredResult.addMethod(this, 'sendMessage', aFunctionName);
|
||||
deferredResult.addMethod(this, 'setTollCallback');
|
||||
deferredResult.callback(someParameters);
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'_sendMessage': function (aFunctionName, aVersion, someParameters) {
|
||||
throw Clipperz.Base.exception.AbstractMethod;
|
||||
},
|
||||
|
||||
'sendMessage': function (aFunctionName, someParameters) {
|
||||
var deferredResult;
|
||||
|
||||
// TODO: read actual application version for a property set at build time
|
||||
deferredResult = new Clipperz.Async.Deferred("Proxy.sendMessage", {trace:false});
|
||||
deferredResult.addMethod(this, '_sendMessage', aFunctionName, 'fake-app-version');
|
||||
deferredResult.addErrback(MochiKit.Base.method(this, 'handleError'));
|
||||
deferredResult.callback(someParameters);
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'handleError': function (anError) {
|
||||
if (anError['message'] == 'Wrong application version') {
|
||||
anError['isPermanent'] = true;
|
||||
}
|
||||
return anError;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'isReadOnly': function () {
|
||||
return false;
|
||||
},
|
||||
|
||||
'canRegisterNewUsers': function () {
|
||||
return true;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
__syntaxFix__: "syntax fix"
|
||||
|
||||
});
|
||||
86
frontend/delta/js/Clipperz/PM/Proxy/Proxy.JSON.js
Executable file
86
frontend/delta/js/Clipperz/PM/Proxy/Proxy.JSON.js
Executable file
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
|
||||
if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
|
||||
|
||||
//=============================================================================
|
||||
|
||||
Clipperz.PM.Proxy.JSON = function(args) {
|
||||
Clipperz.PM.Proxy.JSON.superclass.constructor.call(this, args);
|
||||
|
||||
this._url = args.url || Clipperz.Base.exception.raise('MandatoryParameter');
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
Clipperz.Base.extend(Clipperz.PM.Proxy.JSON, Clipperz.PM.Proxy, {
|
||||
|
||||
'toString': function() {
|
||||
return "Clipperz.PM.Proxy.JSON";
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'url': function () {
|
||||
return this._url;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'_sendMessage': function(aFunctionName, aVersion, someParameters) {
|
||||
var deferredResult;
|
||||
var parameters;
|
||||
|
||||
parameters = {
|
||||
method: aFunctionName,
|
||||
version: aVersion,
|
||||
parameters: Clipperz.Base.serializeJSON(someParameters)
|
||||
};
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("Proxy.JSON.sendMessage", {trace:false});
|
||||
deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'remoteRequestSent');
|
||||
deferredResult.addCallback(MochiKit.Async.doXHR, this.url(), {
|
||||
method:'POST',
|
||||
sendContent:MochiKit.Base.queryString(parameters),
|
||||
headers:{"Content-Type":"application/x-www-form-urlencoded"}
|
||||
});
|
||||
deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'remoteRequestReceived');
|
||||
deferredResult.addCallback(MochiKit.Base.itemgetter('responseText'));
|
||||
deferredResult.addCallback(Clipperz.Base.evalJSON);
|
||||
deferredResult.addCallback(function (someValues) {
|
||||
if (someValues['result'] == 'EXCEPTION') {
|
||||
throw someValues['message'];
|
||||
}
|
||||
|
||||
return someValues;
|
||||
})
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
__syntaxFix__: "syntax fix"
|
||||
|
||||
});
|
||||
793
frontend/delta/js/Clipperz/PM/Proxy/Proxy.Offline.DataStore.js
Normal file
793
frontend/delta/js/Clipperz/PM/Proxy/Proxy.Offline.DataStore.js
Normal file
@@ -0,0 +1,793 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
try { if (typeof(Clipperz.PM.Proxy.Offline) == 'undefined') { throw ""; }} catch (e) {
|
||||
throw "Clipperz.PM.Proxy.Offline.DataStore depends on Clipperz.PM.Proxy.Offline!";
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
||||
Clipperz.PM.Proxy.Offline.DataStore = function(args) {
|
||||
args = args || {};
|
||||
|
||||
this._data = args.data || (typeof(_clipperz_dump_data_) != 'undefined' ? _clipperz_dump_data_ : null);
|
||||
this._isReadOnly = (typeof(args.readOnly) == 'undefined' ? true : args.readOnly);
|
||||
this._shouldPayTolls = args.shouldPayTolls || false;
|
||||
|
||||
this._tolls = {};
|
||||
this._currentStaticConnection = null;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
Clipperz.Base.extend(Clipperz.PM.Proxy.Offline.DataStore, Object, {
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'isReadOnly': function () {
|
||||
return this._isReadOnly;
|
||||
},
|
||||
|
||||
'canRegisterNewUsers': function () {
|
||||
return false;
|
||||
},
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'shouldPayTolls': function() {
|
||||
return this._shouldPayTolls;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'data': function () {
|
||||
return this._data;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'tolls': function () {
|
||||
return this._tolls;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'resetData': function() {
|
||||
this._data = {
|
||||
'users': {
|
||||
'catchAllUser': {
|
||||
__masterkey_test_value__: 'masterkey',
|
||||
s: '112233445566778899aabbccddeeff00112233445566778899aabbccddeeff00',
|
||||
v: '112233445566778899aabbccddeeff00112233445566778899aabbccddeeff00'
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'setupWithEncryptedData': function(someData) {
|
||||
this._data = Clipperz.Base.deepClone(someData);
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'setupWithData': function(someData) {
|
||||
var deferredResult;
|
||||
var resultData;
|
||||
var i, c;
|
||||
|
||||
//Clipperz.log(">>> Proxy.Test.setupWithData");
|
||||
resultData = this._data;
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("Proxy.Test.seupWithData", {trace:false});
|
||||
c = someData['users'].length;
|
||||
|
||||
for (i=0; i<c; i++) {
|
||||
var newConnection;
|
||||
var recordConfiguration;
|
||||
|
||||
deferredResult.addMethod(this, 'userSerializedEncryptedData', someData['users'][i]);
|
||||
deferredResult.addCallback(MochiKit.Base.bind(function(aUserSerializationContext) {
|
||||
resultData['users'][aUserSerializationContext['credentials']['C']] = {
|
||||
's': aUserSerializationContext['credentials']['s'],
|
||||
'v': aUserSerializationContext['credentials']['v'],
|
||||
'version': aUserSerializationContext['data']['connectionVersion'],
|
||||
'userDetails': aUserSerializationContext['encryptedData']['user']['header'],
|
||||
'userDetailsVersion': aUserSerializationContext['encryptedData']['user']['version'],
|
||||
'statistics': aUserSerializationContext['encryptedData']['user']['statistics'],
|
||||
'lock': aUserSerializationContext['encryptedData']['user']['lock'],
|
||||
'records': this.rearrangeRecordsData(aUserSerializationContext['encryptedData']['records'])
|
||||
}
|
||||
}, this));
|
||||
}
|
||||
|
||||
deferredResult.addCallback(MochiKit.Base.bind(function() {
|
||||
this._data = resultData;
|
||||
}, this));
|
||||
|
||||
deferredResult.callback();
|
||||
//Clipperz.log("<<< Proxy.Test.setupWithData");
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'getTollForRequestType': function (aRequestType) {
|
||||
var result;
|
||||
var targetValue;
|
||||
var cost;
|
||||
|
||||
targetValue = Clipperz.Crypto.PRNG.defaultRandomGenerator().getRandomBytes(32).toHexString().substring(2);
|
||||
switch (aRequestType) {
|
||||
case 'REGISTER':
|
||||
cost = 5;
|
||||
break;
|
||||
case 'CONNECT':
|
||||
cost = 5;
|
||||
break;
|
||||
case 'MESSAGE':
|
||||
cost = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
result = {
|
||||
requestType: aRequestType,
|
||||
targetValue: targetValue,
|
||||
cost: cost
|
||||
}
|
||||
|
||||
if (this.shouldPayTolls()) {
|
||||
this.tolls()[targetValue] = result;
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'checkToll': function (aFunctionName, someParameters) {
|
||||
if (this.shouldPayTolls()) {
|
||||
var localToll;
|
||||
var tollParameters;
|
||||
|
||||
tollParameters = someParameters['toll'];
|
||||
localToll = this.tolls()[tollParameters['targetValue']];
|
||||
|
||||
if (localToll != null) {
|
||||
if (! Clipperz.PM.Toll.validate(tollParameters['targetValue'], tollParameters['toll'], localToll['cost'])) {
|
||||
throw "Toll value too low.";
|
||||
};
|
||||
} else {
|
||||
throw "Missing toll";
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'currentStaticConnection': function () {
|
||||
if (this._currentStaticConnection == null) {
|
||||
this._currentStaticConnection = {};
|
||||
}
|
||||
|
||||
return this._currentStaticConnection;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'getConnectionForRequest': function (aFunctionName, someParameters) {
|
||||
var result;
|
||||
|
||||
if (this.shouldPayTolls()) {
|
||||
if ((typeof(someParameters['toll']) != 'undefined') && (typeof(someParameters['toll']['targetValue']) != 'undefined')) {
|
||||
result = this.tolls()[someParameters['toll']['targetValue']]['connection'];
|
||||
if (typeof(result) == 'undefined') {
|
||||
result = {};
|
||||
}
|
||||
} else {
|
||||
result = {};
|
||||
}
|
||||
} else {
|
||||
result = this.currentStaticConnection();
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'storeConnectionForRequestWithConnectionAndResponse': function (aFunctionName, someParameters, aConnection, aResponse) {
|
||||
if (this.shouldPayTolls()) {
|
||||
if ((typeof(aResponse['toll']) != 'undefined')
|
||||
&& (typeof(aResponse['toll']['targetValue']) != 'undefined')
|
||||
&& (typeof(this.tolls()[aResponse['toll']['targetValue']]) != 'undefined')
|
||||
) {
|
||||
this.tolls()[aResponse['toll']['targetValue']]['connection'] = aConnection;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'processMessage': function (aFunctionName, someParameters) {
|
||||
var result;
|
||||
var connection;
|
||||
|
||||
connection = this.getConnectionForRequest(aFunctionName, someParameters);
|
||||
|
||||
switch(aFunctionName) {
|
||||
case 'knock':
|
||||
result = this._knock(connection, someParameters);
|
||||
break;
|
||||
case 'registration':
|
||||
this.checkToll(aFunctionName, someParameters);
|
||||
result = this._registration(connection, someParameters.parameters);
|
||||
break;
|
||||
case 'handshake':
|
||||
this.checkToll(aFunctionName, someParameters);
|
||||
result = this._handshake(connection, someParameters.parameters);
|
||||
break;
|
||||
case 'message':
|
||||
this.checkToll(aFunctionName, someParameters);
|
||||
result = this._message(connection, someParameters.parameters);
|
||||
break;
|
||||
case 'logout':
|
||||
this._currentStaticConnection = null;
|
||||
result = this._logout(connection, someParameters.parameters);
|
||||
break;
|
||||
}
|
||||
|
||||
this.storeConnectionForRequestWithConnectionAndResponse(aFunctionName, someParameters, connection, result);
|
||||
|
||||
return MochiKit.Async.succeed(result);
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'_knock': function(aConnection, someParameters) {
|
||||
var result;
|
||||
|
||||
result = {
|
||||
toll: this.getTollForRequestType(someParameters['requestType'])
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'_registration': function(aConnection, someParameters) {
|
||||
if (this.isReadOnly() == false) {
|
||||
if (typeof(this.data()['users'][someParameters['credentials']['C']]) == 'undefined') {
|
||||
this.data()['users'][someParameters['credentials']['C']] = {
|
||||
's': someParameters['credentials']['s'],
|
||||
'v': someParameters['credentials']['v'],
|
||||
'version': someParameters['credentials']['version'],
|
||||
// 'lock': Clipperz.Crypto.Base.generateRandomSeed(),
|
||||
'userDetails': someParameters['user']['header'],
|
||||
'statistics': someParameters['user']['statistics'],
|
||||
'userDetailsVersion': someParameters['user']['version'],
|
||||
'records': {}
|
||||
}
|
||||
} else {
|
||||
throw "user already exists";
|
||||
}
|
||||
} else {
|
||||
throw Clipperz.PM.Proxy.Offline.DataStore.exception.ReadOnly;
|
||||
}
|
||||
|
||||
result = {
|
||||
result: {
|
||||
'lock': this.data()['users'][someParameters['credentials']['C']]['lock'],
|
||||
'result': 'done'
|
||||
},
|
||||
toll: this.getTollForRequestType('CONNECT')
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'_handshake': function(aConnection, someParameters) {
|
||||
var result;
|
||||
var nextTollRequestType;
|
||||
|
||||
result = {};
|
||||
if (someParameters.message == "connect") {
|
||||
var userData;
|
||||
var randomBytes;
|
||||
var v;
|
||||
|
||||
userData = this.data()['users'][someParameters.parameters.C];
|
||||
|
||||
if ((typeof(userData) != 'undefined') && (userData['version'] == someParameters.version)) {
|
||||
aConnection['userData'] = userData;
|
||||
aConnection['C'] = someParameters.parameters.C;
|
||||
} else {
|
||||
aConnection['userData'] = this.data()['users']['catchAllUser'];
|
||||
}
|
||||
|
||||
randomBytes = Clipperz.Crypto.Base.generateRandomSeed();
|
||||
aConnection['b'] = new Clipperz.Crypto.BigInt(randomBytes, 16);
|
||||
v = new Clipperz.Crypto.BigInt(aConnection['userData']['v'], 16);
|
||||
aConnection['B'] = v.add(Clipperz.Crypto.SRP.g().powerModule(aConnection['b'], Clipperz.Crypto.SRP.n()));
|
||||
|
||||
aConnection['A'] = someParameters.parameters.A;
|
||||
|
||||
result['s'] = aConnection['userData']['s'];
|
||||
result['B'] = aConnection['B'].asString(16);
|
||||
|
||||
nextTollRequestType = 'CONNECT';
|
||||
} else if (someParameters.message == "credentialCheck") {
|
||||
var v, u, S, A, K, M1;
|
||||
|
||||
v = new Clipperz.Crypto.BigInt(aConnection['userData']['v'], 16);
|
||||
u = new Clipperz.Crypto.BigInt(Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(aConnection['B'].asString(10))).toHexString(), 16);
|
||||
A = new Clipperz.Crypto.BigInt(aConnection['A'], 16);
|
||||
S = (A.multiply(v.powerModule(u, Clipperz.Crypto.SRP.n()))).powerModule(aConnection['b'], Clipperz.Crypto.SRP.n());
|
||||
|
||||
K = Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(S.asString(10))).toHexString().slice(2);
|
||||
|
||||
M1 = Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(A.asString(10) + aConnection['B'].asString(10) + K)).toHexString().slice(2);
|
||||
if (someParameters.parameters.M1 == M1) {
|
||||
var M2;
|
||||
|
||||
M2 = Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(A.asString(10) + someParameters.parameters.M1 + K)).toHexString().slice(2);
|
||||
result['M2'] = M2;
|
||||
} else {
|
||||
throw new Error("Client checksum verification failed! Expected <" + M1 + ">, received <" + someParameters.parameters.M1 + ">.", "Error");
|
||||
}
|
||||
|
||||
nextTollRequestType = 'MESSAGE';
|
||||
} else if (someParameters.message == "oneTimePassword") {
|
||||
var otpData;
|
||||
|
||||
otpData = this.data()['onetimePasswords'][someParameters.parameters.oneTimePasswordKey];
|
||||
|
||||
try {
|
||||
if (typeof(otpData) != 'undefined') {
|
||||
if (otpData['status'] == 'ACTIVE') {
|
||||
if (otpData['key_checksum'] == someParameters.parameters.oneTimePasswordKeyChecksum) {
|
||||
result = {
|
||||
'data': otpData['data'],
|
||||
'version': otpData['version']
|
||||
}
|
||||
|
||||
otpData['status'] = 'REQUESTED';
|
||||
} else {
|
||||
otpData['status'] = 'DISABLED';
|
||||
throw "The requested One Time Password has been disabled, due to a wrong keyChecksum";
|
||||
}
|
||||
} else {
|
||||
throw "The requested One Time Password was not active";
|
||||
}
|
||||
} else {
|
||||
throw "The requested One Time Password has not been found"
|
||||
}
|
||||
} catch (exception) {
|
||||
result = {
|
||||
'data': Clipperz.PM.Crypto.randomKey(),
|
||||
'version': Clipperz.PM.Connection.communicationProtocol.currentVersion
|
||||
}
|
||||
}
|
||||
nextTollRequestType = 'CONNECT';
|
||||
} else {
|
||||
Clipperz.logError("Clipperz.PM.Proxy.Test.handshake - unhandled message: " + someParameters.message);
|
||||
}
|
||||
|
||||
result = {
|
||||
result: result,
|
||||
toll: this.getTollForRequestType(nextTollRequestType)
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'_message': function(aConnection, someParameters) {
|
||||
var result;
|
||||
|
||||
result = {};
|
||||
|
||||
//=====================================================================
|
||||
//
|
||||
// R E A D - O N L Y M e t h o d s
|
||||
//
|
||||
//=====================================================================
|
||||
if (someParameters.message == 'getUserDetails') {
|
||||
var recordsStats;
|
||||
var recordReference;
|
||||
|
||||
recordsStats = {};
|
||||
for (recordReference in aConnection['userData']['records']) {
|
||||
recordsStats[recordReference] = {
|
||||
'updateDate': aConnection['userData']['records'][recordReference]['updateDate']
|
||||
}
|
||||
}
|
||||
|
||||
result['header'] = this.userDetails(aConnection);
|
||||
result['statistics'] = this.statistics(aConnection);
|
||||
result['maxNumberOfRecords'] = aConnection['userData']['maxNumberOfRecords'];
|
||||
result['version'] = aConnection['userData']['userDetailsVersion'];
|
||||
result['recordsStats'] = recordsStats;
|
||||
|
||||
if (this.isReadOnly() == false) {
|
||||
var lock;
|
||||
|
||||
if (typeof(aConnection['userData']['lock']) == 'undefined') {
|
||||
aConnection['userData']['lock'] = "<<LOCK>>";
|
||||
}
|
||||
|
||||
result['lock'] = aConnection['userData']['lock'];
|
||||
}
|
||||
|
||||
//=====================================================================
|
||||
} else if (someParameters.message == 'getRecordDetail') {
|
||||
/*
|
||||
var recordData;
|
||||
var currentVersionData;
|
||||
|
||||
recordData = this.userData()['records'][someParameters['parameters']['reference']];
|
||||
result['reference'] = someParameters['parameters']['reference'];
|
||||
result['data'] = recordData['data'];
|
||||
result['version'] = recordData['version'];
|
||||
result['creationData'] = recordData['creationDate'];
|
||||
result['updateDate'] = recordData['updateDate'];
|
||||
result['accessDate'] = recordData['accessDate'];
|
||||
|
||||
currentVersionData = recordData['versions'][recordData['currentVersion']];
|
||||
|
||||
result['currentVersion'] = {};
|
||||
result['currentVersion']['reference'] = recordData['currentVersion'];
|
||||
result['currentVersion']['version'] = currentVersionData['version'];
|
||||
result['currentVersion']['header'] = currentVersionData['header'];
|
||||
result['currentVersion']['data'] = currentVersionData['data'];
|
||||
result['currentVersion']['creationData'] = currentVersionData['creationDate'];
|
||||
result['currentVersion']['updateDate'] = currentVersionData['updateDate'];
|
||||
result['currentVersion']['accessDate'] = currentVersionData['accessDate'];
|
||||
if (typeof(currentVersionData['previousVersion']) != 'undefined') {
|
||||
result['currentVersion']['previousVersionKey'] = currentVersionData['previousVersionKey'];
|
||||
result['currentVersion']['previousVersion'] = currentVersionData['previousVersion'];
|
||||
}
|
||||
*/
|
||||
MochiKit.Base.update(result, aConnection['userData']['records'][someParameters['parameters']['reference']]);
|
||||
result['reference'] = someParameters['parameters']['reference'];
|
||||
|
||||
//=====================================================================
|
||||
//
|
||||
// R E A D - W R I T E M e t h o d s
|
||||
//
|
||||
//=====================================================================
|
||||
} else if (someParameters.message == 'upgradeUserCredentials') {
|
||||
if (this.isReadOnly() == false) {
|
||||
var parameters;
|
||||
var credentials;
|
||||
|
||||
parameters = someParameters['parameters'];
|
||||
credentials = parameters['credentials'];
|
||||
|
||||
if ((credentials['C'] == null)
|
||||
|| (credentials['s'] == null)
|
||||
|| (credentials['v'] == null)
|
||||
|| (credentials['version'] != Clipperz.PM.Connection.communicationProtocol.currentVersion)
|
||||
) {
|
||||
result = Clipperz.PM.DataModel.User.exception.CredentialUpgradeFailed;
|
||||
} else {
|
||||
var oldCValue;
|
||||
oldCValue = aConnection['C'];
|
||||
|
||||
this.data()['users'][credentials['C']] = aConnection['userData'];
|
||||
aConnection['C'] = credentials['C'];
|
||||
|
||||
aConnection['userData']['s'] = credentials['s'];
|
||||
aConnection['userData']['v'] = credentials['v'];
|
||||
aConnection['userData']['version'] = credentials['version'];
|
||||
|
||||
aConnection['userData']['userDetails'] = parameters['user']['header'];
|
||||
aConnection['userData']['userDetailsVersion'] = parameters['user']['version'];
|
||||
aConnection['userData']['statistics'] = parameters['user']['statistics'];
|
||||
|
||||
aConnection['userData']['lock'] = parameters['user']['lock'];
|
||||
|
||||
delete this.data()['users'][oldCValue];
|
||||
|
||||
result = {result:"done", parameters:parameters};
|
||||
}
|
||||
} else {
|
||||
throw Clipperz.PM.Proxy.Offline.DataStore.exception.ReadOnly;
|
||||
}
|
||||
//=====================================================================
|
||||
/* } else if (someParameters.message == 'updateData') {
|
||||
if (this.isReadOnly() == false) {
|
||||
var i, c;
|
||||
|
||||
if (this.userData()['lock'] != someParameters['parameters']['user']['lock']) {
|
||||
throw "the lock attribute is not processed correctly"
|
||||
}
|
||||
|
||||
this.userData()['userDetails'] = someParameters['parameters']['user']['header'];
|
||||
this.userData()['statistics'] = someParameters['parameters']['user']['statistics'];
|
||||
this.userData()['userDetailsVersions'] = someParameters['parameters']['user']['version'];
|
||||
|
||||
c = someParameters['parameters']['records'].length;
|
||||
for (i=0; i<c; i++) {
|
||||
var currentRecord;
|
||||
var currentRecordData;
|
||||
|
||||
currentRecordData = someParameters['parameters']['records'][i];
|
||||
currentRecord = this.userData()['records'][currentRecordData['record']['reference']];
|
||||
|
||||
if (currentRecord == null) {
|
||||
}
|
||||
|
||||
currentRecord['data'] = currentRecordData['record']['data'];
|
||||
currentRecord['version'] = currentRecordData['record']['version'];
|
||||
currentRecord['currentVersion'] = currentRecordData['currentRecordVersion']['reference'];
|
||||
|
||||
currentRecord['versions'][currentRecordData['currentRecordVersion']['reference']] = {
|
||||
'data': currentRecordData['currentRecordVersion']['data'],
|
||||
'version': currentRecordData['currentRecordVersion']['version'],
|
||||
'previousVersion': currentRecordData['currentRecordVersion']['previousVersion'],
|
||||
'previousVersionKey': currentRecordData['currentRecordVersion']['previousVersionKey']
|
||||
}
|
||||
}
|
||||
|
||||
this.userData()['lock'] = Clipperz.PM.Crypto.randomKey();
|
||||
result['lock'] = this.userData()['lock'];
|
||||
result['result'] = 'done';
|
||||
} else {
|
||||
throw Clipperz.PM.Proxy.Offline.DataStore.exception.ReadOnly;
|
||||
}
|
||||
*/ //=====================================================================
|
||||
} else if (someParameters.message == 'saveChanges') {
|
||||
if (this.isReadOnly() == false) {
|
||||
var i, c;
|
||||
|
||||
if (aConnection['userData']['lock'] != someParameters['parameters']['user']['lock']) {
|
||||
throw "the lock attribute is not processed correctly"
|
||||
}
|
||||
|
||||
aConnection['userData']['userDetails'] = someParameters['parameters']['user']['header'];
|
||||
aConnection['userData']['statistics'] = someParameters['parameters']['user']['statistics'];
|
||||
aConnection['userData']['userDetailsVersion'] = someParameters['parameters']['user']['version'];
|
||||
|
||||
c = someParameters['parameters']['records']['updated'].length;
|
||||
for (i=0; i<c; i++) {
|
||||
var currentRecord;
|
||||
var currentRecordData;
|
||||
|
||||
currentRecordData = someParameters['parameters']['records']['updated'][i];
|
||||
currentRecord = aConnection['userData']['records'][currentRecordData['record']['reference']];
|
||||
|
||||
if (
|
||||
(typeof(aConnection['userData']['records'][currentRecordData['record']['reference']]) == 'undefined')
|
||||
&&
|
||||
(typeof(currentRecordData['currentRecordVersion']) == 'undefined')
|
||||
) {
|
||||
throw "Record added without a recordVersion";
|
||||
}
|
||||
|
||||
if (currentRecord == null) {
|
||||
currentRecord = {};
|
||||
currentRecord['versions'] = {};
|
||||
currentRecord['creationDate'] = Clipperz.PM.Date.formatDateWithUTCFormat(new Date());
|
||||
currentRecord['accessDate'] = Clipperz.PM.Date.formatDateWithUTCFormat(new Date());
|
||||
|
||||
aConnection['userData']['records'][currentRecordData['record']['reference']] = currentRecord;
|
||||
}
|
||||
|
||||
currentRecord['data'] = currentRecordData['record']['data'];
|
||||
currentRecord['version'] = currentRecordData['record']['version'];
|
||||
currentRecord['updateDate'] = Clipperz.PM.Date.formatDateWithUTCFormat(new Date());
|
||||
|
||||
if (typeof(currentRecordData['currentRecordVersion']) != 'undefined') {
|
||||
currentRecord['currentVersion'] = currentRecordData['currentRecordVersion']['reference'];
|
||||
currentRecord['versions'][currentRecordData['currentRecordVersion']['reference']] = {
|
||||
'data': currentRecordData['currentRecordVersion']['data'],
|
||||
'version': currentRecordData['currentRecordVersion']['version'],
|
||||
'previousVersion': currentRecordData['currentRecordVersion']['previousVersion'],
|
||||
'previousVersionKey': currentRecordData['currentRecordVersion']['previousVersionKey'],
|
||||
'creationDate': Clipperz.PM.Date.formatDateWithUTCFormat(new Date()),
|
||||
'updateDate': Clipperz.PM.Date.formatDateWithUTCFormat(new Date()),
|
||||
'accessDate': Clipperz.PM.Date.formatDateWithUTCFormat(new Date())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
c = someParameters['parameters']['records']['deleted'].length;
|
||||
for (i=0; i<c; i++) {
|
||||
var currentRecordReference;
|
||||
|
||||
currentRecordReference = someParameters['parameters']['records']['deleted'][i];
|
||||
delete aConnection['userData']['records'][currentRecordReference];
|
||||
}
|
||||
|
||||
aConnection['userData']['lock'] = Clipperz.PM.Crypto.randomKey();
|
||||
result['lock'] = aConnection['userData']['lock'];
|
||||
result['result'] = 'done';
|
||||
} else {
|
||||
throw Clipperz.PM.Proxy.Offline.DataStore.exception.ReadOnly;
|
||||
}
|
||||
|
||||
//=====================================================================
|
||||
//
|
||||
// U N H A N D L E D M e t h o d
|
||||
//
|
||||
//=====================================================================
|
||||
} else {
|
||||
Clipperz.logError("Clipperz.PM.Proxy.Test.message - unhandled message: " + someParameters.message);
|
||||
}
|
||||
|
||||
result = {
|
||||
result: result,
|
||||
toll: this.getTollForRequestType('MESSAGE')
|
||||
}
|
||||
|
||||
// return MochiKit.Async.succeed(result);
|
||||
return result;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'_logout': function(someParameters) {
|
||||
// return MochiKit.Async.succeed({result: 'done'});
|
||||
return {result: 'done'};
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
//#########################################################################
|
||||
|
||||
'isTestData': function(aConnection) {
|
||||
return (typeof(aConnection['userData']['__masterkey_test_value__']) != 'undefined');
|
||||
},
|
||||
|
||||
'userDetails': function(aConnection) {
|
||||
var result;
|
||||
|
||||
if (this.isTestData(aConnection)) {
|
||||
var serializedHeader;
|
||||
var version;
|
||||
|
||||
//Clipperz.logDebug("### test data");
|
||||
version = aConnection['userData']['userDetailsVersion'];
|
||||
serializedHeader = Clipperz.Base.serializeJSON(aConnection['userData']['userDetails']);
|
||||
result = Clipperz.PM.Crypto.encryptingFunctions.versions[version].encrypt(aConnection['userData']['__masterkey_test_value__'], serializedHeader);
|
||||
} else {
|
||||
//Clipperz.logDebug("### NOT test data");
|
||||
result = aConnection['userData']['userDetails'];
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
'statistics': function(aConnection) {
|
||||
var result;
|
||||
|
||||
if (aConnection['userData']['statistics'] != null) {
|
||||
if (this.isTestData(aConnection)) {
|
||||
var serializedStatistics;
|
||||
var version;
|
||||
|
||||
version = aConnection['userData']['userDetailsVersion'];
|
||||
serializedStatistics = Clipperz.Base.serializeJSON(aConnection['userData']['statistics']);
|
||||
result = Clipperz.PM.Crypto.encryptingFunctions.versions[version].encrypt(aConnection['userData']['__masterkey_test_value__'], serializedStatistics);
|
||||
} else {
|
||||
result = aConnection['userData']['statistics'];
|
||||
}
|
||||
} else {
|
||||
result = null;
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
/*
|
||||
'userSerializedEncryptedData': function(someData) {
|
||||
var deferredResult;
|
||||
var deferredContext;
|
||||
|
||||
deferredContext = { 'data': someData };
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred('Proxy.Test.serializeUserEncryptedData', {trace:false});
|
||||
deferredResult.addCallback(MochiKit.Base.bind(function(aDeferredContext) {
|
||||
aDeferredContext['user'] = this.createUserUsingConfigurationData(aDeferredContext['data']);
|
||||
return aDeferredContext;
|
||||
}, this));
|
||||
deferredResult.addCallback(function(aDeferredContext) {
|
||||
// return aDeferredContext['user'].encryptedDataUsingVersion(aDeferredContext['data']['version']);
|
||||
return aDeferredContext['user'].serializedDataUsingVersion(MochiKit.Base.values(aDeferredContext['user'].records()), aDeferredContext['data']['version']);
|
||||
});
|
||||
deferredResult.addCallback(function(aUserEncryptedData) {
|
||||
deferredContext['encryptedData'] = aUserEncryptedData;
|
||||
return deferredContext;
|
||||
});
|
||||
deferredResult.addCallback(function(aDeferredContext) {
|
||||
var connection;
|
||||
|
||||
connection = new Clipperz.PM.Connection.communicationProtocol.versions[aDeferredContext['data']['connectionVersion']]()
|
||||
aDeferredContext['credentials'] = connection.serverSideUserCredentials(aDeferredContext['user'].username(),aDeferredContext['user'].passphrase());
|
||||
|
||||
return aDeferredContext;
|
||||
});
|
||||
|
||||
// deferredResult.addCallback(function(aDeferredContext) {
|
||||
// return aDeferredContext['user'].serializedDataUsingVersion(MochiKit.Base.values(aDeferredContext['user'].records()), aDeferredContext['data']['version']);
|
||||
// }, deferredContext);
|
||||
// deferredResult.addCallback(function(aUserSerializedData) {
|
||||
// });
|
||||
//
|
||||
// deferredResult.addCallback(MochiKit.Async.succeed, deferredContext);
|
||||
deferredResult.callback(deferredContext);
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
'createUserUsingConfigurationData': function(someData) {
|
||||
var result;
|
||||
var user;
|
||||
var recordLabel;
|
||||
|
||||
user = new Clipperz.PM.DataModel.User();
|
||||
user.initForTests();
|
||||
user.setUsername(someData['username']);
|
||||
user.setPassphrase(someData['passphrase']);
|
||||
|
||||
for (recordLabel in someData['records']) {
|
||||
var recordData;
|
||||
var record;
|
||||
var i, c;
|
||||
|
||||
recordData = someData['records'][recordLabel];
|
||||
record = new Clipperz.PM.DataModel.Record({user:user, label:recordLabel});
|
||||
record.setNotes(recordData['notes']);
|
||||
|
||||
c = recordData['fields'].length;
|
||||
for (i=0; i<c; i++) {
|
||||
var recordField;
|
||||
|
||||
recordField = new Clipperz.PM.DataModel.RecordField();
|
||||
recordField.setLabel(recordData['fields'][i]['name']);
|
||||
recordField.setValue(recordData['fields'][i]['value']);
|
||||
recordField.setType(recordData['fields'][i]['type']);
|
||||
record.addField(recordField);
|
||||
}
|
||||
user.addRecord(record, true);
|
||||
}
|
||||
|
||||
result = user;
|
||||
|
||||
return result;
|
||||
},
|
||||
*/
|
||||
//=========================================================================
|
||||
__syntaxFix__: "syntax fix"
|
||||
});
|
||||
|
||||
Clipperz.PM.Proxy.Offline.DataStore['exception'] = {
|
||||
'ReadOnly': new MochiKit.Base.NamedError("Clipperz.PM.Proxy.Offline.DataStore.exception.ReadOnly")
|
||||
};
|
||||
@@ -0,0 +1,420 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
try { if (typeof(Clipperz.PM.Proxy.Offline.DataStore) == 'undefined') { throw ""; }} catch (e) {
|
||||
throw "Clipperz.PM.Proxy.Offline.LocalStorageDataStore depends on Clipperz.PM.Proxy.Offline.DataStore!";
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
||||
Clipperz.PM.Proxy.Offline.LocalStorageDataStore = function(args) {
|
||||
args = args || {};
|
||||
|
||||
this._data = args.data || (typeof(_clipperz_dump_data_) != 'undefined' ? _clipperz_dump_data_ : null);
|
||||
this._isReadOnly = (typeof(args.readOnly) == 'undefined' ? true : args.readOnly);
|
||||
this._shouldPayTolls = args.shouldPayTolls || false;
|
||||
|
||||
this._tolls = {};
|
||||
this._currentStaticConnection = null;
|
||||
|
||||
// Clipperz.PM.Proxy.Offline.LocalStorageDataStore.superclass.constructor.apply(this, arguments);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
Clipperz.Base.extend(Clipperz.PM.Proxy.Offline.LocalStorageDataStore, Clipperz.PM.Proxy.Offline.DataStore, {
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'_knock': function(aConnection, someParameters) {
|
||||
var result;
|
||||
|
||||
result = {
|
||||
toll: this.getTollForRequestType(someParameters['requestType'])
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'_registration': function(aConnection, someParameters) {
|
||||
throw Clipperz.PM.Proxy.Offline.DataStore.exception.ReadOnly;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'_handshake': function(aConnection, someParameters) {
|
||||
var result;
|
||||
var nextTollRequestType;
|
||||
|
||||
result = {};
|
||||
if (someParameters.message == "connect") {
|
||||
var userData;
|
||||
var randomBytes;
|
||||
var v;
|
||||
|
||||
userData = this.data()['users'][someParameters.parameters.C];
|
||||
|
||||
if ((typeof(userData) != 'undefined') && (userData['version'] == someParameters.version)) {
|
||||
aConnection['userData'] = userData;
|
||||
aConnection['C'] = someParameters.parameters.C;
|
||||
} else {
|
||||
aConnection['userData'] = this.data()['users']['catchAllUser'];
|
||||
}
|
||||
|
||||
randomBytes = Clipperz.Crypto.Base.generateRandomSeed();
|
||||
aConnection['b'] = new Clipperz.Crypto.BigInt(randomBytes, 16);
|
||||
v = new Clipperz.Crypto.BigInt(aConnection['userData']['v'], 16);
|
||||
aConnection['B'] = v.add(Clipperz.Crypto.SRP.g().powerModule(aConnection['b'], Clipperz.Crypto.SRP.n()));
|
||||
|
||||
aConnection['A'] = someParameters.parameters.A;
|
||||
|
||||
result['s'] = aConnection['userData']['s'];
|
||||
result['B'] = aConnection['B'].asString(16);
|
||||
|
||||
nextTollRequestType = 'CONNECT';
|
||||
} else if (someParameters.message == "credentialCheck") {
|
||||
var v, u, S, A, K, M1;
|
||||
|
||||
v = new Clipperz.Crypto.BigInt(aConnection['userData']['v'], 16);
|
||||
u = new Clipperz.Crypto.BigInt(Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(aConnection['B'].asString(10))).toHexString(), 16);
|
||||
A = new Clipperz.Crypto.BigInt(aConnection['A'], 16);
|
||||
S = (A.multiply(v.powerModule(u, Clipperz.Crypto.SRP.n()))).powerModule(aConnection['b'], Clipperz.Crypto.SRP.n());
|
||||
|
||||
K = Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(S.asString(10))).toHexString().slice(2);
|
||||
|
||||
M1 = Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(A.asString(10) + aConnection['B'].asString(10) + K)).toHexString().slice(2);
|
||||
if (someParameters.parameters.M1 == M1) {
|
||||
var M2;
|
||||
|
||||
M2 = Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(A.asString(10) + someParameters.parameters.M1 + K)).toHexString().slice(2);
|
||||
result['M2'] = M2;
|
||||
} else {
|
||||
throw new Error("Client checksum verification failed! Expected <" + M1 + ">, received <" + someParameters.parameters.M1 + ">.", "Error");
|
||||
}
|
||||
|
||||
nextTollRequestType = 'MESSAGE';
|
||||
} else if (someParameters.message == "oneTimePassword") {
|
||||
var otpData;
|
||||
|
||||
otpData = this.data()['onetimePasswords'][someParameters.parameters.oneTimePasswordKey];
|
||||
|
||||
try {
|
||||
if (typeof(otpData) != 'undefined') {
|
||||
if (otpData['status'] == 'ACTIVE') {
|
||||
if (otpData['key_checksum'] == someParameters.parameters.oneTimePasswordKeyChecksum) {
|
||||
result = {
|
||||
'data': otpData['data'],
|
||||
'version': otpData['version']
|
||||
}
|
||||
|
||||
otpData['status'] = 'REQUESTED';
|
||||
} else {
|
||||
otpData['status'] = 'DISABLED';
|
||||
throw "The requested One Time Password has been disabled, due to a wrong keyChecksum";
|
||||
}
|
||||
} else {
|
||||
throw "The requested One Time Password was not active";
|
||||
}
|
||||
} else {
|
||||
throw "The requested One Time Password has not been found"
|
||||
}
|
||||
} catch (exception) {
|
||||
result = {
|
||||
'data': Clipperz.PM.Crypto.randomKey(),
|
||||
'version': Clipperz.PM.Connection.communicationProtocol.currentVersion
|
||||
}
|
||||
}
|
||||
nextTollRequestType = 'CONNECT';
|
||||
} else {
|
||||
Clipperz.logError("Clipperz.PM.Proxy.Test.handshake - unhandled message: " + someParameters.message);
|
||||
}
|
||||
|
||||
result = {
|
||||
result: result,
|
||||
toll: this.getTollForRequestType(nextTollRequestType)
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'_message': function(aConnection, someParameters) {
|
||||
var result;
|
||||
|
||||
result = {};
|
||||
|
||||
//=====================================================================
|
||||
//
|
||||
// R E A D - O N L Y M e t h o d s
|
||||
//
|
||||
//=====================================================================
|
||||
if (someParameters.message == 'getUserDetails') {
|
||||
var recordsStats;
|
||||
var recordReference;
|
||||
|
||||
recordsStats = {};
|
||||
for (recordReference in aConnection['userData']['records']) {
|
||||
recordsStats[recordReference] = {
|
||||
'updateDate': aConnection['userData']['records'][recordReference]['updateDate']
|
||||
}
|
||||
}
|
||||
|
||||
result['header'] = this.userDetails(aConnection);
|
||||
result['statistics'] = this.statistics(aConnection);
|
||||
result['maxNumberOfRecords'] = aConnection['userData']['maxNumberOfRecords'];
|
||||
result['version'] = aConnection['userData']['userDetailsVersion'];
|
||||
result['recordsStats'] = recordsStats;
|
||||
|
||||
if (this.isReadOnly() == false) {
|
||||
var lock;
|
||||
|
||||
if (typeof(aConnection['userData']['lock']) == 'undefined') {
|
||||
aConnection['userData']['lock'] = "<<LOCK>>";
|
||||
}
|
||||
|
||||
result['lock'] = aConnection['userData']['lock'];
|
||||
}
|
||||
|
||||
//=====================================================================
|
||||
} else if (someParameters.message == 'getRecordDetail') {
|
||||
/*
|
||||
var recordData;
|
||||
var currentVersionData;
|
||||
|
||||
recordData = this.userData()['records'][someParameters['parameters']['reference']];
|
||||
result['reference'] = someParameters['parameters']['reference'];
|
||||
result['data'] = recordData['data'];
|
||||
result['version'] = recordData['version'];
|
||||
result['creationData'] = recordData['creationDate'];
|
||||
result['updateDate'] = recordData['updateDate'];
|
||||
result['accessDate'] = recordData['accessDate'];
|
||||
|
||||
currentVersionData = recordData['versions'][recordData['currentVersion']];
|
||||
|
||||
result['currentVersion'] = {};
|
||||
result['currentVersion']['reference'] = recordData['currentVersion'];
|
||||
result['currentVersion']['version'] = currentVersionData['version'];
|
||||
result['currentVersion']['header'] = currentVersionData['header'];
|
||||
result['currentVersion']['data'] = currentVersionData['data'];
|
||||
result['currentVersion']['creationData'] = currentVersionData['creationDate'];
|
||||
result['currentVersion']['updateDate'] = currentVersionData['updateDate'];
|
||||
result['currentVersion']['accessDate'] = currentVersionData['accessDate'];
|
||||
if (typeof(currentVersionData['previousVersion']) != 'undefined') {
|
||||
result['currentVersion']['previousVersionKey'] = currentVersionData['previousVersionKey'];
|
||||
result['currentVersion']['previousVersion'] = currentVersionData['previousVersion'];
|
||||
}
|
||||
*/
|
||||
MochiKit.Base.update(result, aConnection['userData']['records'][someParameters['parameters']['reference']]);
|
||||
result['reference'] = someParameters['parameters']['reference'];
|
||||
|
||||
//=====================================================================
|
||||
//
|
||||
// R E A D - W R I T E M e t h o d s
|
||||
//
|
||||
//=====================================================================
|
||||
} else if (someParameters.message == 'upgradeUserCredentials') {
|
||||
if (this.isReadOnly() == false) {
|
||||
var parameters;
|
||||
var credentials;
|
||||
|
||||
parameters = someParameters['parameters'];
|
||||
credentials = parameters['credentials'];
|
||||
|
||||
if ((credentials['C'] == null)
|
||||
|| (credentials['s'] == null)
|
||||
|| (credentials['v'] == null)
|
||||
|| (credentials['version'] != Clipperz.PM.Connection.communicationProtocol.currentVersion)
|
||||
) {
|
||||
result = Clipperz.PM.DataModel.User.exception.CredentialUpgradeFailed;
|
||||
} else {
|
||||
var oldCValue;
|
||||
oldCValue = aConnection['C'];
|
||||
|
||||
this.data()['users'][credentials['C']] = aConnection['userData'];
|
||||
aConnection['C'] = credentials['C'];
|
||||
|
||||
aConnection['userData']['s'] = credentials['s'];
|
||||
aConnection['userData']['v'] = credentials['v'];
|
||||
aConnection['userData']['version'] = credentials['version'];
|
||||
|
||||
aConnection['userData']['userDetails'] = parameters['user']['header'];
|
||||
aConnection['userData']['userDetailsVersion'] = parameters['user']['version'];
|
||||
aConnection['userData']['statistics'] = parameters['user']['statistics'];
|
||||
|
||||
aConnection['userData']['lock'] = parameters['user']['lock'];
|
||||
|
||||
delete this.data()['users'][oldCValue];
|
||||
|
||||
result = {result:"done", parameters:parameters};
|
||||
}
|
||||
} else {
|
||||
throw Clipperz.PM.Proxy.Offline.DataStore.exception.ReadOnly;
|
||||
}
|
||||
|
||||
//=====================================================================
|
||||
|
||||
} else if (someParameters.message == 'saveChanges') {
|
||||
if (this.isReadOnly() == false) {
|
||||
var i, c;
|
||||
|
||||
if (aConnection['userData']['lock'] != someParameters['parameters']['user']['lock']) {
|
||||
throw "the lock attribute is not processed correctly"
|
||||
}
|
||||
|
||||
aConnection['userData']['userDetails'] = someParameters['parameters']['user']['header'];
|
||||
aConnection['userData']['statistics'] = someParameters['parameters']['user']['statistics'];
|
||||
aConnection['userData']['userDetailsVersion'] = someParameters['parameters']['user']['version'];
|
||||
|
||||
c = someParameters['parameters']['records']['updated'].length;
|
||||
for (i=0; i<c; i++) {
|
||||
var currentRecord;
|
||||
var currentRecordData;
|
||||
|
||||
currentRecordData = someParameters['parameters']['records']['updated'][i];
|
||||
currentRecord = aConnection['userData']['records'][currentRecordData['record']['reference']];
|
||||
|
||||
if (
|
||||
(typeof(aConnection['userData']['records'][currentRecordData['record']['reference']]) == 'undefined')
|
||||
&&
|
||||
(typeof(currentRecordData['currentRecordVersion']) == 'undefined')
|
||||
) {
|
||||
throw "Record added without a recordVersion";
|
||||
}
|
||||
|
||||
if (currentRecord == null) {
|
||||
currentRecord = {};
|
||||
currentRecord['versions'] = {};
|
||||
currentRecord['creationDate'] = Clipperz.PM.Date.formatDateWithUTCFormat(new Date());
|
||||
currentRecord['accessDate'] = Clipperz.PM.Date.formatDateWithUTCFormat(new Date());
|
||||
|
||||
aConnection['userData']['records'][currentRecordData['record']['reference']] = currentRecord;
|
||||
}
|
||||
|
||||
currentRecord['data'] = currentRecordData['record']['data'];
|
||||
currentRecord['version'] = currentRecordData['record']['version'];
|
||||
currentRecord['updateDate'] = Clipperz.PM.Date.formatDateWithUTCFormat(new Date());
|
||||
|
||||
if (typeof(currentRecordData['currentRecordVersion']) != 'undefined') {
|
||||
currentRecord['currentVersion'] = currentRecordData['currentRecordVersion']['reference'];
|
||||
currentRecord['versions'][currentRecordData['currentRecordVersion']['reference']] = {
|
||||
'data': currentRecordData['currentRecordVersion']['data'],
|
||||
'version': currentRecordData['currentRecordVersion']['version'],
|
||||
'previousVersion': currentRecordData['currentRecordVersion']['previousVersion'],
|
||||
'previousVersionKey': currentRecordData['currentRecordVersion']['previousVersionKey'],
|
||||
'creationDate': Clipperz.PM.Date.formatDateWithUTCFormat(new Date()),
|
||||
'updateDate': Clipperz.PM.Date.formatDateWithUTCFormat(new Date()),
|
||||
'accessDate': Clipperz.PM.Date.formatDateWithUTCFormat(new Date())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
c = someParameters['parameters']['records']['deleted'].length;
|
||||
for (i=0; i<c; i++) {
|
||||
var currentRecordReference;
|
||||
|
||||
currentRecordReference = someParameters['parameters']['records']['deleted'][i];
|
||||
delete aConnection['userData']['records'][currentRecordReference];
|
||||
}
|
||||
|
||||
aConnection['userData']['lock'] = Clipperz.PM.Crypto.randomKey();
|
||||
result['lock'] = aConnection['userData']['lock'];
|
||||
result['result'] = 'done';
|
||||
} else {
|
||||
throw Clipperz.PM.Proxy.Offline.DataStore.exception.ReadOnly;
|
||||
}
|
||||
|
||||
//=====================================================================
|
||||
//
|
||||
// U N H A N D L E D M e t h o d
|
||||
//
|
||||
//=====================================================================
|
||||
} else {
|
||||
Clipperz.logError("Clipperz.PM.Proxy.Test.message - unhandled message: " + someParameters.message);
|
||||
}
|
||||
|
||||
result = {
|
||||
result: result,
|
||||
toll: this.getTollForRequestType('MESSAGE')
|
||||
}
|
||||
|
||||
// return MochiKit.Async.succeed(result);
|
||||
return result;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'_logout': function(someParameters) {
|
||||
// return MochiKit.Async.succeed({result: 'done'});
|
||||
return {result: 'done'};
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
//#########################################################################
|
||||
/*
|
||||
'userDetails': function(aConnection) {
|
||||
var result;
|
||||
|
||||
if (this.isTestData(aConnection)) {
|
||||
var serializedHeader;
|
||||
var version;
|
||||
|
||||
//Clipperz.logDebug("### test data");
|
||||
version = aConnection['userData']['userDetailsVersion'];
|
||||
serializedHeader = Clipperz.Base.serializeJSON(aConnection['userData']['userDetails']);
|
||||
result = Clipperz.PM.Crypto.encryptingFunctions.versions[version].encrypt(aConnection['userData']['__masterkey_test_value__'], serializedHeader);
|
||||
} else {
|
||||
//Clipperz.logDebug("### NOT test data");
|
||||
result = aConnection['userData']['userDetails'];
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
'statistics': function(aConnection) {
|
||||
var result;
|
||||
|
||||
if (aConnection['userData']['statistics'] != null) {
|
||||
if (this.isTestData(aConnection)) {
|
||||
var serializedStatistics;
|
||||
var version;
|
||||
|
||||
version = aConnection['userData']['userDetailsVersion'];
|
||||
serializedStatistics = Clipperz.Base.serializeJSON(aConnection['userData']['statistics']);
|
||||
result = Clipperz.PM.Crypto.encryptingFunctions.versions[version].encrypt(aConnection['userData']['__masterkey_test_value__'], serializedStatistics);
|
||||
} else {
|
||||
result = aConnection['userData']['statistics'];
|
||||
}
|
||||
} else {
|
||||
result = null;
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
*/
|
||||
//=========================================================================
|
||||
__syntaxFix__: "syntax fix"
|
||||
});
|
||||
|
||||
@@ -0,0 +1,643 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
try { if (typeof(Clipperz.PM.Proxy.Offline.DataStore) == 'undefined') { throw ""; }} catch (e) {
|
||||
throw "Clipperz.PM.Proxy.Offline.MemoryDataStore depends on Clipperz.PM.Proxy.Offline.DataStore!";
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
||||
Clipperz.PM.Proxy.Offline.MemoryDataStore = function(args) {
|
||||
args = args || {};
|
||||
|
||||
this._data = args.data || (typeof(_clipperz_dump_data_) != 'undefined' ? _clipperz_dump_data_ : null);
|
||||
this._isReadOnly = (typeof(args.readOnly) == 'undefined' ? true : args.readOnly);
|
||||
this._shouldPayTolls = args.shouldPayTolls || false;
|
||||
|
||||
this._tolls = {};
|
||||
this._currentStaticConnection = null;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
Clipperz.Base.extend(Clipperz.PM.Proxy.Offline.MemoryDataStore, Clipperz.PM.Proxy.Offline.DataStore, {
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'resetData': function() {
|
||||
this._data = {
|
||||
'users': {
|
||||
'catchAllUser': {
|
||||
__masterkey_test_value__: 'masterkey',
|
||||
s: '112233445566778899aabbccddeeff00112233445566778899aabbccddeeff00',
|
||||
v: '112233445566778899aabbccddeeff00112233445566778899aabbccddeeff00'
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'setupWithEncryptedData': function(someData) {
|
||||
this._data = Clipperz.Base.deepClone(someData);
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'setupWithData': function(someData) {
|
||||
var deferredResult;
|
||||
var resultData;
|
||||
var i, c;
|
||||
|
||||
//Clipperz.log(">>> Proxy.Test.setupWithData");
|
||||
resultData = this._data;
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("Proxy.Test.seupWithData", {trace:false});
|
||||
c = someData['users'].length;
|
||||
|
||||
for (i=0; i<c; i++) {
|
||||
var newConnection;
|
||||
var recordConfiguration;
|
||||
|
||||
deferredResult.addMethod(this, 'userSerializedEncryptedData', someData['users'][i]);
|
||||
deferredResult.addCallback(MochiKit.Base.bind(function(aUserSerializationContext) {
|
||||
resultData['users'][aUserSerializationContext['credentials']['C']] = {
|
||||
's': aUserSerializationContext['credentials']['s'],
|
||||
'v': aUserSerializationContext['credentials']['v'],
|
||||
'version': aUserSerializationContext['data']['connectionVersion'],
|
||||
'userDetails': aUserSerializationContext['encryptedData']['user']['header'],
|
||||
'userDetailsVersion': aUserSerializationContext['encryptedData']['user']['version'],
|
||||
'statistics': aUserSerializationContext['encryptedData']['user']['statistics'],
|
||||
'lock': aUserSerializationContext['encryptedData']['user']['lock'],
|
||||
'records': this.rearrangeRecordsData(aUserSerializationContext['encryptedData']['records'])
|
||||
}
|
||||
}, this));
|
||||
}
|
||||
|
||||
deferredResult.addCallback(MochiKit.Base.bind(function() {
|
||||
this._data = resultData;
|
||||
}, this));
|
||||
|
||||
deferredResult.callback();
|
||||
//Clipperz.log("<<< Proxy.Test.setupWithData");
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'getTollForRequestType': function (aRequestType) {
|
||||
var result;
|
||||
var targetValue;
|
||||
var cost;
|
||||
|
||||
targetValue = Clipperz.Crypto.PRNG.defaultRandomGenerator().getRandomBytes(32).toHexString().substring(2);
|
||||
switch (aRequestType) {
|
||||
case 'REGISTER':
|
||||
cost = 5;
|
||||
break;
|
||||
case 'CONNECT':
|
||||
cost = 5;
|
||||
break;
|
||||
case 'MESSAGE':
|
||||
cost = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
result = {
|
||||
requestType: aRequestType,
|
||||
targetValue: targetValue,
|
||||
cost: cost
|
||||
}
|
||||
|
||||
if (this.shouldPayTolls()) {
|
||||
this.tolls()[targetValue] = result;
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'checkToll': function (aFunctionName, someParameters) {
|
||||
if (this.shouldPayTolls()) {
|
||||
var localToll;
|
||||
var tollParameters;
|
||||
|
||||
tollParameters = someParameters['toll'];
|
||||
localToll = this.tolls()[tollParameters['targetValue']];
|
||||
|
||||
if (localToll != null) {
|
||||
if (! Clipperz.PM.Toll.validate(tollParameters['targetValue'], tollParameters['toll'], localToll['cost'])) {
|
||||
throw "Toll value too low.";
|
||||
};
|
||||
} else {
|
||||
throw "Missing toll";
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'currentStaticConnection': function () {
|
||||
if (this._currentStaticConnection == null) {
|
||||
this._currentStaticConnection = {};
|
||||
}
|
||||
|
||||
return this._currentStaticConnection;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'getConnectionForRequest': function (aFunctionName, someParameters) {
|
||||
var result;
|
||||
|
||||
if (this.shouldPayTolls()) {
|
||||
if ((typeof(someParameters['toll']) != 'undefined') && (typeof(someParameters['toll']['targetValue']) != 'undefined')) {
|
||||
result = this.tolls()[someParameters['toll']['targetValue']]['connection'];
|
||||
if (typeof(result) == 'undefined') {
|
||||
result = {};
|
||||
}
|
||||
} else {
|
||||
result = {};
|
||||
}
|
||||
} else {
|
||||
result = this.currentStaticConnection();
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'storeConnectionForRequestWithConnectionAndResponse': function (aFunctionName, someParameters, aConnection, aResponse) {
|
||||
if (this.shouldPayTolls()) {
|
||||
if ((typeof(aResponse['toll']) != 'undefined')
|
||||
&& (typeof(aResponse['toll']['targetValue']) != 'undefined')
|
||||
&& (typeof(this.tolls()[aResponse['toll']['targetValue']]) != 'undefined')
|
||||
) {
|
||||
this.tolls()[aResponse['toll']['targetValue']]['connection'] = aConnection;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'processMessage': function (aFunctionName, someParameters) {
|
||||
var result;
|
||||
var connection;
|
||||
|
||||
connection = this.getConnectionForRequest(aFunctionName, someParameters);
|
||||
|
||||
switch(aFunctionName) {
|
||||
case 'knock':
|
||||
result = this._knock(connection, someParameters);
|
||||
break;
|
||||
case 'registration':
|
||||
this.checkToll(aFunctionName, someParameters);
|
||||
result = this._registration(connection, someParameters.parameters);
|
||||
break;
|
||||
case 'handshake':
|
||||
this.checkToll(aFunctionName, someParameters);
|
||||
result = this._handshake(connection, someParameters.parameters);
|
||||
break;
|
||||
case 'message':
|
||||
this.checkToll(aFunctionName, someParameters);
|
||||
result = this._message(connection, someParameters.parameters);
|
||||
break;
|
||||
case 'logout':
|
||||
this._currentStaticConnection = null;
|
||||
result = this._logout(connection, someParameters.parameters);
|
||||
break;
|
||||
}
|
||||
|
||||
this.storeConnectionForRequestWithConnectionAndResponse(aFunctionName, someParameters, connection, result);
|
||||
|
||||
return MochiKit.Async.succeed(result);
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'_knock': function(aConnection, someParameters) {
|
||||
var result;
|
||||
|
||||
result = {
|
||||
toll: this.getTollForRequestType(someParameters['requestType'])
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'_registration': function(aConnection, someParameters) {
|
||||
if (this.isReadOnly() == false) {
|
||||
if (typeof(this.data()['users'][someParameters['credentials']['C']]) == 'undefined') {
|
||||
this.data()['users'][someParameters['credentials']['C']] = {
|
||||
's': someParameters['credentials']['s'],
|
||||
'v': someParameters['credentials']['v'],
|
||||
'version': someParameters['credentials']['version'],
|
||||
// 'lock': Clipperz.Crypto.Base.generateRandomSeed(),
|
||||
'userDetails': someParameters['user']['header'],
|
||||
'statistics': someParameters['user']['statistics'],
|
||||
'userDetailsVersion': someParameters['user']['version'],
|
||||
'records': {}
|
||||
}
|
||||
} else {
|
||||
throw "user already exists";
|
||||
}
|
||||
} else {
|
||||
throw Clipperz.PM.Proxy.Offline.DataStore.exception.ReadOnly;
|
||||
}
|
||||
|
||||
result = {
|
||||
result: {
|
||||
'lock': this.data()['users'][someParameters['credentials']['C']]['lock'],
|
||||
'result': 'done'
|
||||
},
|
||||
toll: this.getTollForRequestType('CONNECT')
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'_handshake': function(aConnection, someParameters) {
|
||||
var result;
|
||||
var nextTollRequestType;
|
||||
|
||||
result = {};
|
||||
if (someParameters.message == "connect") {
|
||||
var userData;
|
||||
var randomBytes;
|
||||
var v;
|
||||
|
||||
userData = this.data()['users'][someParameters.parameters.C];
|
||||
|
||||
if ((typeof(userData) != 'undefined') && (userData['version'] == someParameters.version)) {
|
||||
aConnection['userData'] = userData;
|
||||
aConnection['C'] = someParameters.parameters.C;
|
||||
} else {
|
||||
aConnection['userData'] = this.data()['users']['catchAllUser'];
|
||||
}
|
||||
|
||||
randomBytes = Clipperz.Crypto.Base.generateRandomSeed();
|
||||
aConnection['b'] = new Clipperz.Crypto.BigInt(randomBytes, 16);
|
||||
v = new Clipperz.Crypto.BigInt(aConnection['userData']['v'], 16);
|
||||
aConnection['B'] = v.add(Clipperz.Crypto.SRP.g().powerModule(aConnection['b'], Clipperz.Crypto.SRP.n()));
|
||||
|
||||
aConnection['A'] = someParameters.parameters.A;
|
||||
|
||||
result['s'] = aConnection['userData']['s'];
|
||||
result['B'] = aConnection['B'].asString(16);
|
||||
|
||||
nextTollRequestType = 'CONNECT';
|
||||
} else if (someParameters.message == "credentialCheck") {
|
||||
var v, u, S, A, K, M1;
|
||||
|
||||
v = new Clipperz.Crypto.BigInt(aConnection['userData']['v'], 16);
|
||||
u = new Clipperz.Crypto.BigInt(Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(aConnection['B'].asString(10))).toHexString(), 16);
|
||||
A = new Clipperz.Crypto.BigInt(aConnection['A'], 16);
|
||||
S = (A.multiply(v.powerModule(u, Clipperz.Crypto.SRP.n()))).powerModule(aConnection['b'], Clipperz.Crypto.SRP.n());
|
||||
|
||||
K = Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(S.asString(10))).toHexString().slice(2);
|
||||
|
||||
M1 = Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(A.asString(10) + aConnection['B'].asString(10) + K)).toHexString().slice(2);
|
||||
if (someParameters.parameters.M1 == M1) {
|
||||
var M2;
|
||||
|
||||
M2 = Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(A.asString(10) + someParameters.parameters.M1 + K)).toHexString().slice(2);
|
||||
result['M2'] = M2;
|
||||
} else {
|
||||
throw new Error("Client checksum verification failed! Expected <" + M1 + ">, received <" + someParameters.parameters.M1 + ">.", "Error");
|
||||
}
|
||||
|
||||
nextTollRequestType = 'MESSAGE';
|
||||
} else if (someParameters.message == "oneTimePassword") {
|
||||
var otpData;
|
||||
|
||||
otpData = this.data()['onetimePasswords'][someParameters.parameters.oneTimePasswordKey];
|
||||
|
||||
try {
|
||||
if (typeof(otpData) != 'undefined') {
|
||||
if (otpData['status'] == 'ACTIVE') {
|
||||
if (otpData['key_checksum'] == someParameters.parameters.oneTimePasswordKeyChecksum) {
|
||||
result = {
|
||||
'data': otpData['data'],
|
||||
'version': otpData['version']
|
||||
}
|
||||
|
||||
otpData['status'] = 'REQUESTED';
|
||||
} else {
|
||||
otpData['status'] = 'DISABLED';
|
||||
throw "The requested One Time Password has been disabled, due to a wrong keyChecksum";
|
||||
}
|
||||
} else {
|
||||
throw "The requested One Time Password was not active";
|
||||
}
|
||||
} else {
|
||||
throw "The requested One Time Password has not been found"
|
||||
}
|
||||
} catch (exception) {
|
||||
result = {
|
||||
'data': Clipperz.PM.Crypto.randomKey(),
|
||||
'version': Clipperz.PM.Connection.communicationProtocol.currentVersion
|
||||
}
|
||||
}
|
||||
nextTollRequestType = 'CONNECT';
|
||||
} else {
|
||||
Clipperz.logError("Clipperz.PM.Proxy.Test.handshake - unhandled message: " + someParameters.message);
|
||||
}
|
||||
|
||||
result = {
|
||||
result: result,
|
||||
toll: this.getTollForRequestType(nextTollRequestType)
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'_message': function(aConnection, someParameters) {
|
||||
var result;
|
||||
|
||||
result = {};
|
||||
|
||||
//=====================================================================
|
||||
//
|
||||
// R E A D - O N L Y M e t h o d s
|
||||
//
|
||||
//=====================================================================
|
||||
if (someParameters.message == 'getUserDetails') {
|
||||
var recordsStats;
|
||||
var recordReference;
|
||||
|
||||
recordsStats = {};
|
||||
for (recordReference in aConnection['userData']['records']) {
|
||||
recordsStats[recordReference] = {
|
||||
'updateDate': aConnection['userData']['records'][recordReference]['updateDate']
|
||||
}
|
||||
}
|
||||
|
||||
result['header'] = this.userDetails(aConnection);
|
||||
result['statistics'] = this.statistics(aConnection);
|
||||
result['maxNumberOfRecords'] = aConnection['userData']['maxNumberOfRecords'];
|
||||
result['version'] = aConnection['userData']['userDetailsVersion'];
|
||||
result['recordsStats'] = recordsStats;
|
||||
|
||||
if (this.isReadOnly() == false) {
|
||||
var lock;
|
||||
|
||||
if (typeof(aConnection['userData']['lock']) == 'undefined') {
|
||||
aConnection['userData']['lock'] = "<<LOCK>>";
|
||||
}
|
||||
|
||||
result['lock'] = aConnection['userData']['lock'];
|
||||
}
|
||||
|
||||
//=====================================================================
|
||||
} else if (someParameters.message == 'getRecordDetail') {
|
||||
/*
|
||||
var recordData;
|
||||
var currentVersionData;
|
||||
|
||||
recordData = this.userData()['records'][someParameters['parameters']['reference']];
|
||||
result['reference'] = someParameters['parameters']['reference'];
|
||||
result['data'] = recordData['data'];
|
||||
result['version'] = recordData['version'];
|
||||
result['creationData'] = recordData['creationDate'];
|
||||
result['updateDate'] = recordData['updateDate'];
|
||||
result['accessDate'] = recordData['accessDate'];
|
||||
|
||||
currentVersionData = recordData['versions'][recordData['currentVersion']];
|
||||
|
||||
result['currentVersion'] = {};
|
||||
result['currentVersion']['reference'] = recordData['currentVersion'];
|
||||
result['currentVersion']['version'] = currentVersionData['version'];
|
||||
result['currentVersion']['header'] = currentVersionData['header'];
|
||||
result['currentVersion']['data'] = currentVersionData['data'];
|
||||
result['currentVersion']['creationData'] = currentVersionData['creationDate'];
|
||||
result['currentVersion']['updateDate'] = currentVersionData['updateDate'];
|
||||
result['currentVersion']['accessDate'] = currentVersionData['accessDate'];
|
||||
if (typeof(currentVersionData['previousVersion']) != 'undefined') {
|
||||
result['currentVersion']['previousVersionKey'] = currentVersionData['previousVersionKey'];
|
||||
result['currentVersion']['previousVersion'] = currentVersionData['previousVersion'];
|
||||
}
|
||||
*/
|
||||
MochiKit.Base.update(result, aConnection['userData']['records'][someParameters['parameters']['reference']]);
|
||||
result['reference'] = someParameters['parameters']['reference'];
|
||||
|
||||
//=====================================================================
|
||||
//
|
||||
// R E A D - W R I T E M e t h o d s
|
||||
//
|
||||
//=====================================================================
|
||||
} else if (someParameters.message == 'upgradeUserCredentials') {
|
||||
if (this.isReadOnly() == false) {
|
||||
var parameters;
|
||||
var credentials;
|
||||
|
||||
parameters = someParameters['parameters'];
|
||||
credentials = parameters['credentials'];
|
||||
|
||||
if ((credentials['C'] == null)
|
||||
|| (credentials['s'] == null)
|
||||
|| (credentials['v'] == null)
|
||||
|| (credentials['version'] != Clipperz.PM.Connection.communicationProtocol.currentVersion)
|
||||
) {
|
||||
result = Clipperz.PM.DataModel.User.exception.CredentialUpgradeFailed;
|
||||
} else {
|
||||
var oldCValue;
|
||||
oldCValue = aConnection['C'];
|
||||
|
||||
this.data()['users'][credentials['C']] = aConnection['userData'];
|
||||
aConnection['C'] = credentials['C'];
|
||||
|
||||
aConnection['userData']['s'] = credentials['s'];
|
||||
aConnection['userData']['v'] = credentials['v'];
|
||||
aConnection['userData']['version'] = credentials['version'];
|
||||
|
||||
aConnection['userData']['userDetails'] = parameters['user']['header'];
|
||||
aConnection['userData']['userDetailsVersion'] = parameters['user']['version'];
|
||||
aConnection['userData']['statistics'] = parameters['user']['statistics'];
|
||||
|
||||
aConnection['userData']['lock'] = parameters['user']['lock'];
|
||||
|
||||
delete this.data()['users'][oldCValue];
|
||||
|
||||
result = {result:"done", parameters:parameters};
|
||||
}
|
||||
} else {
|
||||
throw Clipperz.PM.Proxy.Offline.DataStore.exception.ReadOnly;
|
||||
}
|
||||
|
||||
//=====================================================================
|
||||
|
||||
} else if (someParameters.message == 'saveChanges') {
|
||||
if (this.isReadOnly() == false) {
|
||||
var i, c;
|
||||
|
||||
if (aConnection['userData']['lock'] != someParameters['parameters']['user']['lock']) {
|
||||
throw "the lock attribute is not processed correctly"
|
||||
}
|
||||
|
||||
aConnection['userData']['userDetails'] = someParameters['parameters']['user']['header'];
|
||||
aConnection['userData']['statistics'] = someParameters['parameters']['user']['statistics'];
|
||||
aConnection['userData']['userDetailsVersion'] = someParameters['parameters']['user']['version'];
|
||||
|
||||
c = someParameters['parameters']['records']['updated'].length;
|
||||
for (i=0; i<c; i++) {
|
||||
var currentRecord;
|
||||
var currentRecordData;
|
||||
|
||||
currentRecordData = someParameters['parameters']['records']['updated'][i];
|
||||
currentRecord = aConnection['userData']['records'][currentRecordData['record']['reference']];
|
||||
|
||||
if (
|
||||
(typeof(aConnection['userData']['records'][currentRecordData['record']['reference']]) == 'undefined')
|
||||
&&
|
||||
(typeof(currentRecordData['currentRecordVersion']) == 'undefined')
|
||||
) {
|
||||
throw "Record added without a recordVersion";
|
||||
}
|
||||
|
||||
if (currentRecord == null) {
|
||||
currentRecord = {};
|
||||
currentRecord['versions'] = {};
|
||||
currentRecord['creationDate'] = Clipperz.PM.Date.formatDateWithUTCFormat(new Date());
|
||||
currentRecord['accessDate'] = Clipperz.PM.Date.formatDateWithUTCFormat(new Date());
|
||||
|
||||
aConnection['userData']['records'][currentRecordData['record']['reference']] = currentRecord;
|
||||
}
|
||||
|
||||
currentRecord['data'] = currentRecordData['record']['data'];
|
||||
currentRecord['version'] = currentRecordData['record']['version'];
|
||||
currentRecord['updateDate'] = Clipperz.PM.Date.formatDateWithUTCFormat(new Date());
|
||||
|
||||
if (typeof(currentRecordData['currentRecordVersion']) != 'undefined') {
|
||||
currentRecord['currentVersion'] = currentRecordData['currentRecordVersion']['reference'];
|
||||
currentRecord['versions'][currentRecordData['currentRecordVersion']['reference']] = {
|
||||
'data': currentRecordData['currentRecordVersion']['data'],
|
||||
'version': currentRecordData['currentRecordVersion']['version'],
|
||||
'previousVersion': currentRecordData['currentRecordVersion']['previousVersion'],
|
||||
'previousVersionKey': currentRecordData['currentRecordVersion']['previousVersionKey'],
|
||||
'creationDate': Clipperz.PM.Date.formatDateWithUTCFormat(new Date()),
|
||||
'updateDate': Clipperz.PM.Date.formatDateWithUTCFormat(new Date()),
|
||||
'accessDate': Clipperz.PM.Date.formatDateWithUTCFormat(new Date())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
c = someParameters['parameters']['records']['deleted'].length;
|
||||
for (i=0; i<c; i++) {
|
||||
var currentRecordReference;
|
||||
|
||||
currentRecordReference = someParameters['parameters']['records']['deleted'][i];
|
||||
delete aConnection['userData']['records'][currentRecordReference];
|
||||
}
|
||||
|
||||
aConnection['userData']['lock'] = Clipperz.PM.Crypto.randomKey();
|
||||
result['lock'] = aConnection['userData']['lock'];
|
||||
result['result'] = 'done';
|
||||
} else {
|
||||
throw Clipperz.PM.Proxy.Offline.DataStore.exception.ReadOnly;
|
||||
}
|
||||
|
||||
//=====================================================================
|
||||
//
|
||||
// U N H A N D L E D M e t h o d
|
||||
//
|
||||
//=====================================================================
|
||||
} else {
|
||||
Clipperz.logError("Clipperz.PM.Proxy.Test.message - unhandled message: " + someParameters.message);
|
||||
}
|
||||
|
||||
result = {
|
||||
result: result,
|
||||
toll: this.getTollForRequestType('MESSAGE')
|
||||
}
|
||||
|
||||
// return MochiKit.Async.succeed(result);
|
||||
return result;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'_logout': function(someParameters) {
|
||||
// return MochiKit.Async.succeed({result: 'done'});
|
||||
return {result: 'done'};
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
//#########################################################################
|
||||
|
||||
'isTestData': function(aConnection) {
|
||||
return (typeof(aConnection['userData']['__masterkey_test_value__']) != 'undefined');
|
||||
},
|
||||
|
||||
'userDetails': function(aConnection) {
|
||||
var result;
|
||||
|
||||
if (this.isTestData(aConnection)) {
|
||||
var serializedHeader;
|
||||
var version;
|
||||
|
||||
//Clipperz.logDebug("### test data");
|
||||
version = aConnection['userData']['userDetailsVersion'];
|
||||
serializedHeader = Clipperz.Base.serializeJSON(aConnection['userData']['userDetails']);
|
||||
result = Clipperz.PM.Crypto.encryptingFunctions.versions[version].encrypt(aConnection['userData']['__masterkey_test_value__'], serializedHeader);
|
||||
} else {
|
||||
//Clipperz.logDebug("### NOT test data");
|
||||
result = aConnection['userData']['userDetails'];
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
'statistics': function(aConnection) {
|
||||
var result;
|
||||
|
||||
if (aConnection['userData']['statistics'] != null) {
|
||||
if (this.isTestData(aConnection)) {
|
||||
var serializedStatistics;
|
||||
var version;
|
||||
|
||||
version = aConnection['userData']['userDetailsVersion'];
|
||||
serializedStatistics = Clipperz.Base.serializeJSON(aConnection['userData']['statistics']);
|
||||
result = Clipperz.PM.Crypto.encryptingFunctions.versions[version].encrypt(aConnection['userData']['__masterkey_test_value__'], serializedStatistics);
|
||||
} else {
|
||||
result = aConnection['userData']['statistics'];
|
||||
}
|
||||
} else {
|
||||
result = null;
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
__syntaxFix__: "syntax fix"
|
||||
});
|
||||
|
||||
72
frontend/delta/js/Clipperz/PM/Proxy/Proxy.Offline.js
Normal file
72
frontend/delta/js/Clipperz/PM/Proxy/Proxy.Offline.js
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
|
||||
if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
|
||||
|
||||
//=============================================================================
|
||||
|
||||
Clipperz.PM.Proxy.Offline = function(args) {
|
||||
args = args || {};
|
||||
|
||||
Clipperz.PM.Proxy.Offline.superclass.constructor.call(this, args);
|
||||
|
||||
this._dataStore = args.dataStore || new Clipperz.PM.Proxy.Offline.DataStore(args);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
Clipperz.Base.extend(Clipperz.PM.Proxy.Offline, Clipperz.PM.Proxy, {
|
||||
|
||||
'toString': function () {
|
||||
return "Clipperz.PM.Proxy.Offline";
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'dataStore': function () {
|
||||
return this._dataStore;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'_sendMessage': function(aFunctionName, aVersion, someParameters) {
|
||||
return this.dataStore().processMessage(aFunctionName, someParameters);
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'isReadOnly': function () {
|
||||
return this.dataStore().isReadOnly();
|
||||
},
|
||||
|
||||
'canRegisterNewUsers': function () {
|
||||
return this.dataStore().canRegisterNewUsers();
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
__syntaxFix__: "syntax fix"
|
||||
|
||||
});
|
||||
|
||||
161
frontend/delta/js/Clipperz/PM/Proxy/Proxy.Test.js
Normal file
161
frontend/delta/js/Clipperz/PM/Proxy/Proxy.Test.js
Normal file
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
|
||||
if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
|
||||
if (typeof(Clipperz.PM.Proxy) == 'undefined') { Clipperz.PM.Proxy = {}; }
|
||||
|
||||
//=============================================================================
|
||||
|
||||
Clipperz.PM.Proxy.Test = function(args) {
|
||||
Clipperz.PM.Proxy.Test.superclass.constructor.call(this, args);
|
||||
|
||||
args = args || {};
|
||||
|
||||
this._expectedRequests = (args.shouldCheckExpectedRequests === true) ? [] : null;
|
||||
this._isExpectingRequests = true;
|
||||
this._unexpectedRequests = [];
|
||||
|
||||
this.dataStore().resetData();
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
Clipperz.Base.extend(Clipperz.PM.Proxy.Test, Clipperz.PM.Proxy.Offline, {
|
||||
|
||||
'toString': function() {
|
||||
return "Clipperz.PM.Proxy.Test";
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'expectedRequests': function () {
|
||||
return this._expectedRequests;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'shouldCheckExpectedRequests': function () {
|
||||
return (this._expectedRequests != null);
|
||||
},
|
||||
|
||||
'setShouldCheckExpectedRequests': function(aValue) {
|
||||
if (aValue) {
|
||||
this._expectedRequests = aValue;
|
||||
} else {
|
||||
this._expectedRequests = null;
|
||||
}
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'shouldNotReceiveAnyFurtherRequest': function () {
|
||||
this._isExpectingRequests = false;
|
||||
},
|
||||
|
||||
'mayReceiveMoreRequests': function () {
|
||||
this._isExpectingRequests = true;
|
||||
this.resetUnexpectedRequests();
|
||||
},
|
||||
|
||||
'isExpectingRequests': function () {
|
||||
return this._isExpectingRequests;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'unexpectedRequests': function () {
|
||||
return this._unexpectedRequests;
|
||||
},
|
||||
|
||||
'resetUnexpectedRequests': function () {
|
||||
this._unexpectedRequests = [];
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'testExpectedRequestParameters': function (aPath, anActualRequest, anExpectedRequest) {
|
||||
var aKey;
|
||||
for (aKey in anExpectedRequest) {
|
||||
if (typeof(anActualRequest[aKey]) == 'undefined') {
|
||||
throw "the expected paramter [" + aKey + "] is missing from the actual request";
|
||||
}
|
||||
if (typeof(anExpectedRequest[aKey]) == 'object') {
|
||||
this.testExpectedRequestParameters(aPath + "." + aKey, anActualRequest[aKey], anExpectedRequest[aKey])
|
||||
} else {
|
||||
if (! anExpectedRequest[aKey](anActualRequest[aKey])) {
|
||||
throw "wrong value for paramter [" + aKey + "]; got '" + anActualRequest[aKey] + "'";
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'checkRequest': function(aFunctionName, someParameters) {
|
||||
if (this.shouldCheckExpectedRequests()) {
|
||||
var expectedRequest;
|
||||
|
||||
expectedRequest = this.expectedRequests().pop();
|
||||
if (expectedRequest == null) {
|
||||
throw "Proxy.Test.sentMessage: no expected result specified. Got request '" + aFunctionName + "': " + someParameters;
|
||||
}
|
||||
|
||||
try {
|
||||
if (aFunctionName != expectedRequest.functionName) {
|
||||
throw "wrong function name. Got '" + aFunctionName + "', expected '" + expectedRequest.request.functionName + "'";
|
||||
}
|
||||
|
||||
this.testExpectedRequestParameters("parameters", someParameters, expectedRequest.parameters);
|
||||
} catch(exception) {
|
||||
throw "Proxy.Test.sentMessage[" + expectedRequest.name + "]: " + exception;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'_sendMessage': function(aFunctionName, aVersion, someParameters) {
|
||||
var result;
|
||||
|
||||
if (this.isExpectingRequests() == false) {
|
||||
// throw Clipperz.PM.Connection.exception.UnexpectedRequest;
|
||||
Clipperz.log("UNEXPECTED REQUEST " + aFunctionName /* + ": " + Clipperz.Base.serializeJSON(someParameters) */);
|
||||
this.unexpectedRequests().push({'functionName':aFunctionName, 'someParameters': someParameters});
|
||||
};
|
||||
//if (aFunctionName == 'knock') {
|
||||
// console.log(">>> send message - " + aFunctionName, someParameters);
|
||||
//} else {
|
||||
// console.log(">>> SEND MESSAGE - " + aFunctionName + " [" + someParameters['parameters']['message'] + "]", someParameters['parameters']['parameters']);
|
||||
//}
|
||||
this.checkRequest(aFunctionName, someParameters);
|
||||
result = Clipperz.PM.Proxy.Test.superclass._sendMessage.call(this, aFunctionName, aVersion, someParameters);
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
__syntaxFix__: "syntax fix"
|
||||
|
||||
});
|
||||
|
||||
285
frontend/delta/js/Clipperz/PM/Strings.js
Normal file
285
frontend/delta/js/Clipperz/PM/Strings.js
Normal file
@@ -0,0 +1,285 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
|
||||
if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
|
||||
if (typeof(Clipperz.PM.Strings) == 'undefined') { Clipperz.PM.Strings = {}; }
|
||||
if (typeof(Clipperz.PM.Strings.Languages) == 'undefined') { Clipperz.PM.Strings.Languages = {}; }
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/*
|
||||
Clipperz.PM.Strings.standardStrings = {
|
||||
'loginPanelSwitchLanguageSelectOptions': [
|
||||
/ *
|
||||
{tag:'option', html:"Arabic (Oman) (العربية)", value:'ar-OM', disabled:true},
|
||||
{tag:'option', html:"Arabic (Syria) (العربية)", value:'ar-SY', disabled:true},
|
||||
{tag:'option', html:"Bahasa Indonesia", value:'id-ID', disabled:true},
|
||||
{tag:'option', html:"Bulgarian (Български)", value:'bg-BG', disabled:true},
|
||||
{tag:'option', html:"Català", value:'ca-ES', disabled:true},
|
||||
{tag:'option', html:"Chinese (Simplified) (简体中文)", value:'zh-CN', disabled:true},
|
||||
{tag:'option', html:"Chinese (Traditional) (正體中文)", value:'zh-TW', disabled:true},
|
||||
{tag:'option', html:"Czech (Česky)", value:'cs-CZ', disabled:true},
|
||||
{tag:'option', html:"Dansk", value:'da-DK', disabled:true},
|
||||
{tag:'option', html:"Deutsch", value:'de-DE'/ *, disabled:true* /},
|
||||
{tag:'option', html:"English (American)", value:'en-US'/ *, disabled:true* /},
|
||||
{tag:'option', html:"English (British)", value:'en-GB'/ *, disabled:true* /},
|
||||
{tag:'option', html:"English (Canadian)", value:'en-CA'/ *, disabled:true* /},
|
||||
{tag:'option', html:"Español", value:'es-ES', disabled:true},
|
||||
{tag:'option', html:"Eesti", value:'et-EE', disabled:true},
|
||||
{tag:'option', html:"Français", value:'fr-FR', disabled:true},
|
||||
{tag:'option', html:"Galego", value:'gl-ES', disabled:true},
|
||||
{tag:'option', html:"Greek (Ελληνικά)", value:'el-GR', disabled:true},
|
||||
{tag:'option', html:"Íslenska", value:'is-IS', disabled:true},
|
||||
{tag:'option', html:"Italiano", value:'it-IT'/ *, disabled:true* /},
|
||||
{tag:'option', html:"Japanese (日本語)", value:'ja-JP', disabled:true},
|
||||
{tag:'option', html:"Korean (한국어)", value:'ko-KR', disabled:true},
|
||||
{tag:'option', html:"Latviešu", value:'lv-LV', disabled:true},
|
||||
{tag:'option', html:"Lietuvių", value:'lt-LT', disabled:true},
|
||||
{tag:'option', html:"Macedonian (Македонски)", value:'mk-MK', disabled:true},
|
||||
{tag:'option', html:"Magyar", value:'hu-HU', disabled:true},
|
||||
{tag:'option', html:"Nederlands", value:'nl-NL', disabled:true},
|
||||
{tag:'option', html:"Norsk bokmål", value:'nb-NO', disabled:true},
|
||||
{tag:'option', html:"Norsk nynorsk", value:'nn-NO', disabled:true},
|
||||
{tag:'option', html:"Persian (Western) (فارسى)", value:'fa-IR', disabled:true},
|
||||
{tag:'option', html:"Polski", value:'pl-PL', disabled:true},
|
||||
{tag:'option', html:"Português", value:'pt-PT'/ *, disabled:true* /},
|
||||
{tag:'option', html:"Português Brasileiro", value:'pt-BR'/ *, disabled:true* /},
|
||||
{tag:'option', html:"Românä", value:'ro-RO', disabled:true},
|
||||
{tag:'option', html:"Russian (Русский)", value:'ru-RU', disabled:true},
|
||||
{tag:'option', html:"Slovak (Slovenčina)", value:'sk-SK', disabled:true},
|
||||
{tag:'option', html:"Slovenian (Slovenščina)", value:'sl-SI', disabled:true},
|
||||
{tag:'option', html:"Suomi", value:'fi-FI', disabled:true},
|
||||
{tag:'option', html:"Svenska", value:'sv-SE', disabled:true},
|
||||
{tag:'option', html:"Thai (ไทย)", value:'th-TH', disabled:true},
|
||||
{tag:'option', html:"Türkçe", value:'tr-TR', disabled:true},
|
||||
{tag:'option', html:"Ukrainian (Українська)", value:'uk-UA', disabled:true}
|
||||
* /
|
||||
{tag:'option', html:"Arabic (العربية)", value:"ar", disabled:true, cls:'disabledOption'},
|
||||
// {tag:'option', html:"Chinese (中文)", value:"zh", disabled:true},
|
||||
{tag:'option', html:"Chinese (Simplified) (简体中文)", value:'zh-CN'},
|
||||
{tag:'option', html:"Dutch (Nederlands)", value:"nl-NL", disabled:true, cls:'disabledOption'},
|
||||
{tag:'option', html:"English", value:"en-US"},
|
||||
{tag:'option', html:"French (Français)", value:"fr-FR"},
|
||||
{tag:'option', html:"German (Deutsch)", value:"de-DE", disabled:true, cls:'disabledOption'},
|
||||
{tag:'option', html:"Greek (Ελληνικά)", value:"el-GR", disabled:true, cls:'disabledOption'},
|
||||
{tag:'option', html:"Hebrew (עברית)", value:"he-IL", disabled:true, cls:'disabledOption'},
|
||||
{tag:'option', html:"Italian (Italiano)", value:"it-IT"},
|
||||
{tag:'option', html:"Japanese (日本語)", value:"ja-JP"},
|
||||
{tag:'option', html:"Korean (한국어)", value:"ko-KR", disabled:true, cls:'disabledOption'},
|
||||
{tag:'option', html:"Norwegian (Norsk)", value:"no", disabled:true, cls:'disabledOption'},
|
||||
{tag:'option', html:"Persian (فارسی)", value:"fa-IR", disabled:true, cls:'disabledOption'},
|
||||
{tag:'option', html:"Polish (Polski)", value:"pl-PL", disabled:true, cls:'disabledOption'},
|
||||
{tag:'option', html:"Portuguese (Português)", value:"pt-BR"},
|
||||
{tag:'option', html:"Russian (Русский)", value:"ru-RU", disabled:true, cls:'disabledOption'},
|
||||
{tag:'option', html:"Spanish (Español)", value:"es-ES"},
|
||||
{tag:'option', html:"Swedish (Svenska)", value:"sv-SE", disabled:true, cls:'disabledOption'},
|
||||
{tag:'option', html:"Turkish (Türkçe)", value:"tr-TR", disabled:true, cls:'disabledOption'},
|
||||
{tag:'option', html:"Vietnamese (Tiếng Việt)", value:"vi-VN", disabled:true, cls:'disabledOption'}
|
||||
]
|
||||
}
|
||||
*/
|
||||
|
||||
Clipperz.PM.Strings.GeneralSettings = {
|
||||
'defaults': {
|
||||
// 'loginFormAarghThatsBadUrl': "http://www.clipperz.com/support/faq/account_faq",
|
||||
// 'loginFormVerifyTheCodeUrl': "http://www.clipperz.com/learn_more/reviewing_the_code",
|
||||
|
||||
// 'donateHeaderLinkUrl': "http://www.clipperz.com/donations",
|
||||
// 'creditsHeaderLinkUrl': "http://www.clipperz.com/credits",
|
||||
// 'feedbackHeaderLinkUrl': "http://www.clipperz.com/contact",
|
||||
// 'helpHeaderLinkUrl': "http://www.clipperz.com/support/user_guide",
|
||||
// 'forumHeaderLinkUrl': "http://www.clipperz.com/forum",
|
||||
|
||||
// 'httpAuthBookmarkletConfiguration': {tag:'textarea', id:'httpAuthDefaultConfiguration', html:"" +
|
||||
// "{ \"page\":{\"title\":\"HTTP authentication\"}," + "\n" +
|
||||
// " \"form\":{\"attributes\": {" + "\n" +
|
||||
// " \"action\":\"\"," + "\n" +
|
||||
// " \"type\":\"http_auth\"" + "\n" +
|
||||
// " }, \"inputs\": [" + "\n" +
|
||||
// " {\"type\":\"text\",\"name\":\"url\",\"value\":\"\"}," + "\n" +
|
||||
// " {\"type\":\"text\",\"name\":\"username\",\"value\":\"\"}," + "\n" +
|
||||
// " {\"type\":\"password\",\"name\":\"password\",\"value\":\"\"}" + "\n" +
|
||||
// " ]}, \"version\":\"0.2.3\"}"
|
||||
// },
|
||||
|
||||
'directLoginJumpPageUrl': "",
|
||||
'defaultFaviconUrl': "data:application/octet-stream;charset=utf-8;base64,AAABAAEAFxcAAAEAGAD8BgAAFgAAACgAAAAXAAAALgAAAAEAGAAAAAAAAAAAABIXAAASFwAAAAAAAAAAAAD///////////////////////////////////////////////////////////////////////////////////////////9zAC////////////////////////////////////////////////////////////////////////////////////////////9pAG////////////////////////////////////////////////////////////////////////////////////////////9rAC////////////////////////////////////////////////////////////////////////////////////////////9yAHP////////////////////////IyMizs7O6urrq6ur////////////Ozs6zs7Ozs7Pq6ur///////////////////////8AAAD////////////////////V1dWXl5eXl5eXl5elpaX4+Pj////Ozs6Xl5eXl5eXl5eenp7///////////////////////8AAAD////////////////////Ozs6Xl5eXl5eXl5eXl5fBwcHq6uqenp6Xl5eXl5eXl5eXl5f///////////////////////8AAAD////////////////////j4+OXl5eXl5eXl5eXl5eXl5elpaWXl5eXl5eXl5eXl5ezs7P///////////////////////8AAAD////////////////////////IyMiXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eenp7x8fH////////////////////////////////////////////////////4+PilpaWXl5eXl5eXl5eXl5eXl5eXl5eXl5fOzs7////////////////////////////////////////////////////////q6uq6urqXl5eXl5eXl5eXl5eXl5eXl5eenp7V1dX4+Pj///////////////////////8AAAD////////////4+PjOzs6lpaWXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5e6urrj4+P///////////////8AAAD////////////BwcGXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5fx8fH///////////8AAAD///////////+zs7OXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5fj4+P///////////8AAAD////////////IyMiXl5eXl5eXl5eXl5e6urqXl5eXl5eXl5eXl5esrKylpaWXl5eXl5eXl5eenp7x8fH///////////8AAAD////////////////Ozs7Ozs7V1dX4+Pj///+Xl5eXl5eXl5eXl5fOzs7////q6urOzs7Ozs7q6ur///////////////8AAAD///////////////////////////////////+Xl5eXl5eXl5eXl5fOzs7///////////////////////////////////8AAAD///////////////////////////////////+Xl5eXl5eXl5eXl5fOzs7///////////////////////////////////8AAAD///////////////////////////////////+Xl5eXl5eXl5eXl5fOzs7///////////////////////////////////8AAAD////////////////////////////////////IyMiXl5eXl5eenp7x8fH///////////////////////////////////8AAAD////////////////////////////////////////j4+Pj4+Px8fH///////////////////////////////////////8AAAD///////////////////////////////////////////////////////////////////////////////////////////8AAAD///////////////////////////////////////////////////////////////////////////////////////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAo=",
|
||||
'defaultFaviconUrl_IE': "https://www.clipperz.com/images/icons/misc/favicon.ico",
|
||||
|
||||
// 'icons_baseUrl': "https://www.clipperz.com/images/icons",
|
||||
|
||||
// 'passwordGeneratorLowercaseCharset': "abcdefghijklmnopqrstuvwxyz",
|
||||
// 'passwordGeneratorUppercaseCharset': "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
|
||||
// 'passwordGeneratorNumberCharset': "0123456789",
|
||||
// 'passwordGeneratorSymbolCharset': "!@#$%^&*+?[]{}/|\\<>,.;:~=-_",
|
||||
|
||||
// 'passwordGenerator': {
|
||||
// 'lowercaseCharset': "abcdefghijklmnopqrstuvwxyz",
|
||||
// 'uppercaseCharset': "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
|
||||
// 'numberCharset': "0123456789",
|
||||
// 'symbolCharset': "!@#$%^&*+?[]{}/|\\<>,.;:~=-_",
|
||||
// },
|
||||
|
||||
'_': ""
|
||||
}
|
||||
}
|
||||
|
||||
Clipperz.PM.Strings.defaultLanguages = {
|
||||
'default': "en-us",
|
||||
|
||||
// 'de': "de-de",
|
||||
// 'el': "el-gr",
|
||||
// 'he': "he-il",
|
||||
// 'ru': "ru-ru",
|
||||
|
||||
'fr': "fr-fr",
|
||||
'es': "es-es",
|
||||
'zh': "zh-cn",
|
||||
'ja': "ja-jp",
|
||||
'pt': "pt-br",
|
||||
'it': "it-it",
|
||||
'en': "en-us"
|
||||
}
|
||||
|
||||
Clipperz.PM.Strings.inputTypeToRecordFieldType = {
|
||||
'text': 'TXT',
|
||||
'password': 'PWD',
|
||||
'checkbox': 'CHECK',
|
||||
'radio': 'RADIO',
|
||||
'select': 'SELECT'
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
Clipperz.PM.Strings.translateBookmarklet = function (aBookmarkletString) {
|
||||
var result;
|
||||
|
||||
result = aBookmarkletString;
|
||||
|
||||
result = result.replace(/@BOOKMARKLET_NO_EXCEPTION_MESSAGE@/, Clipperz.PM.Strings.getValue('bookmarkletCopy.noExceptionMessage'));
|
||||
result = result.replace(/@BOOKMARKLET_EXCEPTION_MESSAGE@/, Clipperz.PM.Strings.getValue('bookmarkletCopy.exceptionMessage'));
|
||||
result = result.replace(/@BOOKMARKLET_COPY@/, Clipperz.PM.Strings.getValue('bookmarkletCopy.copy'));
|
||||
result = result.replace(/@BOOKMARKLET_SUCCESSFUL_MESSAGE@/, Clipperz.PM.Strings.getValue('bookmarkletCopy.successfulMessage'));
|
||||
result = result.replace(/@BOOKMARKLET_FAIL_MESSAGE@/, Clipperz.PM.Strings.getValue('bookmarkletCopy.failMessage'));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
Clipperz.PM.Strings.Languages.setSelectedLanguage = function(aLanguage) {
|
||||
var language;
|
||||
var selectedLanguage;
|
||||
|
||||
language = (aLanguage || Clipperz.PM.Strings.preferredLanguage || 'default').toLowerCase();
|
||||
if (typeof(Clipperz.PM.Strings.defaultLanguages[language]) != 'undefined') {
|
||||
language = Clipperz.PM.Strings.defaultLanguages[language];
|
||||
}
|
||||
|
||||
if (typeof(Clipperz.PM.Strings.Languages[language]) != 'undefined') {
|
||||
selectedLanguage = language;
|
||||
} else if (typeof(Clipperz.PM.Strings.defaultLanguages[language.substr(0,2)]) != 'undefined') {
|
||||
selectedLanguage = Clipperz.PM.Strings.defaultLanguages[language.substr(0,2)];
|
||||
} else {
|
||||
selectedLanguage = Clipperz.PM.Strings.defaultLanguages['default'];
|
||||
}
|
||||
|
||||
if (selectedLanguage != Clipperz.PM.Strings.selectedLanguage) {
|
||||
var translations;
|
||||
|
||||
Clipperz.PM.Strings.selectedLanguage = selectedLanguage;
|
||||
|
||||
translations = {};
|
||||
// MochiKit.Base.update(translations, Clipperz.PM.Strings.standardStrings)
|
||||
|
||||
MochiKit.Base.updatetree(translations, Clipperz.PM.Strings.Languages['defaults']);
|
||||
MochiKit.Base.updatetree(translations, Clipperz.PM.Strings.GeneralSettings['defaults']);
|
||||
|
||||
MochiKit.Base.updatetree(translations, Clipperz.PM.Strings.Languages[Clipperz.PM.Strings.defaultLanguages['default']]);
|
||||
MochiKit.Base.updatetree(translations, Clipperz.PM.Strings.GeneralSettings[Clipperz.PM.Strings.defaultLanguages['default']]);
|
||||
|
||||
MochiKit.Base.updatetree(translations, Clipperz.PM.Strings.Languages[selectedLanguage]);
|
||||
MochiKit.Base.updatetree(translations, Clipperz.PM.Strings.GeneralSettings[selectedLanguage]);
|
||||
|
||||
Clipperz.PM.Strings.stringsObjectStore = new Clipperz.KeyValueObjectStore(/*{'name':'String.stringsObjectStore [1]'}*/);
|
||||
Clipperz.PM.Strings.stringsObjectStore.initWithValues(translations);
|
||||
|
||||
if (typeof(bookmarklet) != 'undefined') {
|
||||
Clipperz.PM.Strings.stringsObjectStore.setValue('bookmarklet', Clipperz.PM.Strings.translateBookmarklet(bookmarklet));
|
||||
}
|
||||
|
||||
MochiKit.Signal.signal(Clipperz.PM.Strings.Languages, 'switchLanguage', selectedLanguage);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
Clipperz.PM.Strings.getValue = function (aKeyPath, someKeyValues) {
|
||||
var result;
|
||||
|
||||
result = Clipperz.PM.Strings.stringsObjectStore.getValue(aKeyPath);
|
||||
|
||||
if (typeof(result) == 'string') {
|
||||
if (typeof (someKeyValues) != 'undefined') {
|
||||
var key;
|
||||
|
||||
for (key in someKeyValues) {
|
||||
result = result.replace( new RegExp(key), someKeyValues[key]);
|
||||
}
|
||||
}
|
||||
|
||||
result = result.replace(new RegExp('\n'), '<br>');
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Clipperz.PM.Strings.errorDescriptionForException = function (anException) {
|
||||
var result;
|
||||
|
||||
result = Clipperz.PM.Strings.getValue('exceptionsMessages' + '.' + anException.name);
|
||||
|
||||
if (result == null) {
|
||||
result = anException.message;
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
Clipperz.PM.Strings.Languages.initSetup = function() {
|
||||
var language;
|
||||
var languageParser;
|
||||
|
||||
language = navigator.language || navigator.userLanguage; // en, en-US, .... "de", "nb-no"
|
||||
languageParser = new RegExp("language=([a-z]{2}(?:\-[a-z]{2})?)(\&|$)", "i");
|
||||
if (languageParser.test(window.location.search)) {
|
||||
language = RegExp.$1;
|
||||
}
|
||||
|
||||
Clipperz.PM.Strings.preferredLanguage = language.toLowerCase();
|
||||
Clipperz.PM.Strings.Languages.setSelectedLanguage(Clipperz.PM.Strings.preferredLanguage);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -0,0 +1,384 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
|
||||
if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
|
||||
if (typeof(Clipperz.PM.Strings) == 'undefined') { Clipperz.PM.Strings = {}; }
|
||||
|
||||
Clipperz.PM.Strings.messagePanelConfigurations = {
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Registration - connection
|
||||
//
|
||||
'registration_verify': function() {
|
||||
return {
|
||||
'title': null,
|
||||
'text': Clipperz.PM.Strings['connectionRegistrationSendingRequestMessageText']
|
||||
}
|
||||
},
|
||||
|
||||
'registration_sendingCredentials': function() {
|
||||
return {
|
||||
'title': null,
|
||||
'text': Clipperz.PM.Strings['connectionRegistrationSendingCredentialsMessageText']
|
||||
}
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// One Time Password login message panel
|
||||
//
|
||||
|
||||
'OTP_login_start': function() {
|
||||
return {
|
||||
'title': Clipperz.PM.Strings['OTPloginMessagePanelInitialTitle'],
|
||||
'text': Clipperz.PM.Strings['OTPloginMessagePanelInitialText'],
|
||||
'steps': '+3',
|
||||
'buttons': {}
|
||||
}
|
||||
},
|
||||
|
||||
'OTP_login_loadingOTP': function() {
|
||||
return {
|
||||
'title': Clipperz.PM.Strings['OTPloginMessagePanelLoadingTitle'],
|
||||
'text': Clipperz.PM.Strings['OTPloginMessagePanelLoadingText']
|
||||
}
|
||||
},
|
||||
|
||||
'OTP_login_extractingPassphrase': function() {
|
||||
return {
|
||||
'title': Clipperz.PM.Strings['OTPloginMessagePanelProcessingTitle'],
|
||||
'text': Clipperz.PM.Strings['OTPloginMessagePanelProcessingText']
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Login message panel
|
||||
//
|
||||
'login_start': function() {
|
||||
return {
|
||||
'title': Clipperz.PM.Strings['loginMessagePanelInitialTitle'],
|
||||
'text': Clipperz.PM.Strings['loginMessagePanelInitialText'],
|
||||
'steps': '+7',
|
||||
'buttons': {
|
||||
'ok': Clipperz.PM.Strings['loginMessagePanelInitialButtonLabel']
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
'login_connected': function() {
|
||||
return {
|
||||
'title': Clipperz.PM.Strings['loginMessagePanelConnectedTitle'],
|
||||
'text': Clipperz.PM.Strings['loginMessagePanelConnectedText'],
|
||||
'buttons': {}
|
||||
}
|
||||
},
|
||||
|
||||
'login_failed': function() {
|
||||
return {
|
||||
'title': Clipperz.PM.Strings['loginMessagePanelFailureTitle'],
|
||||
'text': Clipperz.PM.Strings['loginMessagePanelFailureText'],
|
||||
'button': Clipperz.PM.Strings['loginMessagePanelFailureButtonLabel']
|
||||
}
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Login message panel - connection
|
||||
//
|
||||
'connection_sendingCredentials': function() {
|
||||
return {
|
||||
'title': Clipperz.PM.Strings['connectionLoginSendingCredentialsMessageTitle'],
|
||||
'text': Clipperz.PM.Strings['connectionLoginSendingCredentialsMessageText']
|
||||
}
|
||||
},
|
||||
|
||||
'connection_credentialVerification': function() {
|
||||
return {
|
||||
'title': Clipperz.PM.Strings['connectionLoginCredentialsVerificationMessageTitle'],
|
||||
'text': Clipperz.PM.Strings['connectionLoginCredentialsVerificationMessageText']
|
||||
}
|
||||
},
|
||||
|
||||
'connection_loggedIn': function() {
|
||||
return {
|
||||
'title': Clipperz.PM.Strings['connectionLoginDoneMessageTitle'],
|
||||
'text': Clipperz.PM.Strings['connectionLoginDoneMessageText']
|
||||
}
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Login message panel - user
|
||||
//
|
||||
'connection_upgrading': function() {
|
||||
return {
|
||||
'title': Clipperz.PM.Strings['userLoginPanelUpgradingUserCredentialsMessageTitle'],
|
||||
'text': Clipperz.PM.Strings['userLoginPanelUpgradingUserCredentialsMessageText'],
|
||||
'steps': '+1'
|
||||
}
|
||||
},
|
||||
|
||||
'connection_done': function() {
|
||||
return {
|
||||
'title': Clipperz.PM.Strings['userLoginPanelConnectedMessageTitle'],
|
||||
'text': Clipperz.PM.Strings['userLoginPanelConnectedMessageText']
|
||||
}
|
||||
},
|
||||
|
||||
'connection_tryOlderSchema': function() {
|
||||
return {
|
||||
'title': Clipperz.PM.Strings['userLoginPanelTryingAnOlderConnectionSchemaMessageTitle'],
|
||||
'text': Clipperz.PM.Strings['userLoginPanelTryingAnOlderConnectionSchemaMessageText'],
|
||||
'steps': '+4'
|
||||
}
|
||||
},
|
||||
|
||||
'connection_loadingUserData': function() {
|
||||
return {
|
||||
'title': Clipperz.PM.Strings['userLoginPanelLoadingUserDataMessageTitle'],
|
||||
'text': Clipperz.PM.Strings['userLoginPanelLoadingUserDataMessageText']
|
||||
}
|
||||
},
|
||||
|
||||
'connection_decryptingUserData': function() {
|
||||
return {
|
||||
'title': Clipperz.PM.Strings['userLoginPanelDecryptingUserDataMessageTitle'],
|
||||
'text': Clipperz.PM.Strings['userLoginPanelDecryptingUserDataMessageText'],
|
||||
'steps': '+1'
|
||||
}
|
||||
},
|
||||
|
||||
'connection_decryptingUserStatistics': function() {
|
||||
return {
|
||||
'title': Clipperz.PM.Strings['userLoginPanelDecryptingUserStatisticsMessageTitle'],
|
||||
'text': Clipperz.PM.Strings['userLoginPanelDecryptingUserStatisticsMessageText']
|
||||
}
|
||||
},
|
||||
|
||||
'collectingEntropy': function() {
|
||||
return {
|
||||
'text': Clipperz.PM.Strings['panelCollectingEntryopyMessageText'],
|
||||
'steps': '+1'
|
||||
}
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Cards block - delete card panel
|
||||
//
|
||||
'deleteRecord_collectData': function() {
|
||||
return {
|
||||
'title': Clipperz.PM.Strings['deleteRecordPanelCollectRecordDataMessageTitle'],
|
||||
'text': Clipperz.PM.Strings['deleteRecordPanelCollectRecordDataMessageText']
|
||||
}
|
||||
},
|
||||
|
||||
'deleteRecord_encryptData': function() {
|
||||
return {
|
||||
'title': Clipperz.PM.Strings['deleteRecordPanelEncryptUserDataMessageTitle'],
|
||||
'text': Clipperz.PM.Strings['deleteRecordPanelEncryptUserDataMessageText']
|
||||
}
|
||||
},
|
||||
|
||||
'deleteRecord_sendingData': function() {
|
||||
return {
|
||||
'title': Clipperz.PM.Strings['deleteRecordPanelSendingDataToTheServerMessageTitle'],
|
||||
'text': Clipperz.PM.Strings['deleteRecordPanelSendingDataToTheServerMessageText']
|
||||
}
|
||||
},
|
||||
|
||||
'deleteRecord_updatingInterface': function() {
|
||||
return {
|
||||
'title': Clipperz.PM.Strings['deleteRecordPanelUpdatingTheInterfaceMessageTitle'],
|
||||
'text': Clipperz.PM.Strings['deleteRecordPanelUpdatingTheInterfaceMessageText']
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Cards block - save card panel
|
||||
//
|
||||
'saveCard_collectRecordInfo': function() {
|
||||
return {
|
||||
'title': Clipperz.PM.Strings['recordSaveChangesPanelCollectRecordInfoMessageTitle'],
|
||||
'text': Clipperz.PM.Strings['recordSaveChangesPanelCollectRecordInfoMessageText']
|
||||
}
|
||||
},
|
||||
|
||||
'saveCard_encryptUserData': function() {
|
||||
return {
|
||||
'title': Clipperz.PM.Strings['recordSaveChangesPanelEncryptUserDataMessageTitle'],
|
||||
'text': Clipperz.PM.Strings['recordSaveChangesPanelEncryptUserDataMessageText']
|
||||
}
|
||||
},
|
||||
|
||||
'saveCard_encryptRecordData': function() {
|
||||
return {
|
||||
'title': Clipperz.PM.Strings['recordSaveChangesPanelEncryptRecordDataMessageTitle'],
|
||||
'text': Clipperz.PM.Strings['recordSaveChangesPanelEncryptRecordDataMessageText']
|
||||
}
|
||||
},
|
||||
|
||||
'saveCard_encryptRecordVersions': function() {
|
||||
return {
|
||||
'title': Clipperz.PM.Strings['recordSaveChangesPanelEncryptRecordVersionDataMessageTitle'],
|
||||
'text': Clipperz.PM.Strings['recordSaveChangesPanelEncryptRecordVersionDataMessageText']
|
||||
}
|
||||
},
|
||||
|
||||
'saveCard_sendingData': function() {
|
||||
return {
|
||||
'title': Clipperz.PM.Strings['recordSaveChangesPanelSendingDataToTheServerMessageTitle'],
|
||||
'text': Clipperz.PM.Strings['recordSaveChangesPanelSendingDataToTheServerMessageText']
|
||||
}
|
||||
},
|
||||
|
||||
'saveCard_updatingInterface': function() {
|
||||
return {
|
||||
'title': Clipperz.PM.Strings['recordSaveChangesPanelUpdatingTheInterfaceMessageTitle'],
|
||||
'text': Clipperz.PM.Strings['recordSaveChangesPanelUpdatingTheInterfaceMessageText']
|
||||
}
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Account panel - user preferences
|
||||
//
|
||||
'account_savingPreferences_1': function() {
|
||||
return {
|
||||
'title': Clipperz.PM.Strings['accountPreferencesSavingPanelTitle_Step1'],
|
||||
'text': Clipperz.PM.Strings['accountPreferencesSavingPanelText_Step1'],
|
||||
'steps': '+3'
|
||||
}
|
||||
},
|
||||
|
||||
'account_savingPreferences_2': function() {
|
||||
return {
|
||||
'title': Clipperz.PM.Strings['accountPreferencesSavingPanelTitle_Step2'],
|
||||
'text': Clipperz.PM.Strings['accountPreferencesSavingPanelText_Step2']
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Account panel - change credentials
|
||||
//
|
||||
'changeCredentials_encryptingData': function() {
|
||||
return {
|
||||
'title': Clipperz.PM.Strings['changeCredentialsPanelEncryptingDataMessageTitle'],
|
||||
'text': Clipperz.PM.Strings['changeCredentialsPanelEncryptingDataMessageText']
|
||||
}
|
||||
},
|
||||
|
||||
'changeCredentials_creatingNewCredentials': function() {
|
||||
return {
|
||||
'title': Clipperz.PM.Strings['changeCredentialsPanelCreatingNewCredentialsMessageTitle'],
|
||||
'text': Clipperz.PM.Strings['changeCredentialsPanelCreatingNewCredentialsMessageText']
|
||||
}
|
||||
},
|
||||
|
||||
'changeCredentials_sendingCredentials': function() {
|
||||
return {
|
||||
'title': Clipperz.PM.Strings['changeCredentialsPanelSendingNewCredentialsToTheServerMessageTitle'],
|
||||
'text': Clipperz.PM.Strings['changeCredentialsPanelSendingNewCredentialsToTheServerMessageText']
|
||||
}
|
||||
},
|
||||
|
||||
'changeCredentials_done': function() {
|
||||
return {
|
||||
'title': Clipperz.PM.Strings['changeCredentialsPanelDoneMessageTitle'],
|
||||
'text': Clipperz.PM.Strings['changeCredentialsPanelDoneMessageText']
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Account panel - change credentials
|
||||
//
|
||||
'saveOTP_encryptUserData': function() {
|
||||
return {
|
||||
'title': Clipperz.PM.Strings['saveOTP_encryptUserDataTitle'],
|
||||
'text': Clipperz.PM.Strings['saveOTP_encryptUserDataText'],
|
||||
'steps': '+4'
|
||||
}
|
||||
},
|
||||
|
||||
'saveOTP_encryptOTPData': function() {
|
||||
return {
|
||||
'title': Clipperz.PM.Strings['saveOTP_encryptOTPDataTitle'],
|
||||
'text': Clipperz.PM.Strings['saveOTP_encryptOTPDataText']
|
||||
}
|
||||
},
|
||||
|
||||
'saveOTP_sendingData': function() {
|
||||
return {
|
||||
'title': Clipperz.PM.Strings['saveOTP_sendingDataTitle'],
|
||||
'text': Clipperz.PM.Strings['saveOTP_sendingDataText']
|
||||
}
|
||||
},
|
||||
|
||||
'saveOTP_updatingInterface': function() {
|
||||
return {
|
||||
'title': Clipperz.PM.Strings['saveOTP_updatingInterfaceTitle'],
|
||||
'text': Clipperz.PM.Strings['saveOTP_updatingInterfaceText']
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Data panel - processingImportData
|
||||
//
|
||||
'parseImportData': function() {
|
||||
return {
|
||||
'title': Clipperz.PM.Strings['importData_parsingDataTitle'],
|
||||
'text': Clipperz.PM.Strings['importData_parsingDataText']
|
||||
}
|
||||
},
|
||||
|
||||
'previewImportData': function() {
|
||||
return {
|
||||
'title': Clipperz.PM.Strings['importData_previewingDataTitle'],
|
||||
'text': Clipperz.PM.Strings['importData_previewingDataText']
|
||||
}
|
||||
},
|
||||
|
||||
'processingImportData': function() {
|
||||
return {
|
||||
'title': Clipperz.PM.Strings['importData_processingDataTitle'],
|
||||
'text': Clipperz.PM.Strings['importData_processingDataText']
|
||||
}
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
__syntaxFix__: "syntax fix"
|
||||
|
||||
}
|
||||
385
frontend/delta/js/Clipperz/PM/Strings/Strings_defaults.js
Normal file
385
frontend/delta/js/Clipperz/PM/Strings/Strings_defaults.js
Normal file
@@ -0,0 +1,385 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
|
||||
if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
|
||||
if (typeof(Clipperz.PM.Strings) == 'undefined') { Clipperz.PM.Strings = {}; }
|
||||
if (typeof(Clipperz.PM.Strings.Languages) == 'undefined') { Clipperz.PM.Strings.Languages = {}; }
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// D E F A U L T S ( defaults )
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
Clipperz.PM.Strings.Languages['defaults'] = {
|
||||
|
||||
'elapsedTimeDescriptions': {
|
||||
'MORE_THAN_A_MONTH_AGO': "more than a month ago",
|
||||
'MORE_THAN_A_WEEK_AGO': "more than a week ago",
|
||||
'MORE_THAN_*_WEEKS_AGO': "more than __elapsed__ weeks ago",
|
||||
'YESTERDAY': "yesterday",
|
||||
'*_DAYS_AGO': "__elapsed__ days ago",
|
||||
'ABOUT_AN_HOUR_AGO': "about an hour ago",
|
||||
'*_HOURS_AGO': "__elapsed__ hours ago",
|
||||
'JUST_A_FEW_MINUTES_AGO': "just a few minutes ago",
|
||||
'ABOUT_*_MINUTES_AGO': "about __elapsed__ minutes ago"
|
||||
},
|
||||
/*
|
||||
'unknown_ip': "unknown",
|
||||
|
||||
'countries': {
|
||||
'--': "unknown",
|
||||
'AD': "Andorra",
|
||||
'AE': "United Arab Emirates",
|
||||
'AF': "Afghanistan",
|
||||
'AG': "Antigua and Barbuda",
|
||||
'AI': "Anguilla",
|
||||
'AL': "Albania",
|
||||
'AM': "Armenia",
|
||||
'AN': "Netherlands Antilles",
|
||||
'AO': "Angola",
|
||||
'AP': "Non-Spec Asia Pas Location",
|
||||
'AR': "Argentina",
|
||||
'AS': "American Samoa",
|
||||
'AT': "Austria",
|
||||
'AU': "Australia",
|
||||
'AW': "Aruba",
|
||||
'AX': "Aland Islands",
|
||||
'AZ': "Azerbaijan",
|
||||
'BA': "Bosnia and Herzegowina",
|
||||
'BB': "Barbados",
|
||||
'BD': "Bangladesh",
|
||||
'BE': "Belgium",
|
||||
'BF': "Burkina Faso",
|
||||
'BG': "Bulgaria",
|
||||
'BH': "Bahrain",
|
||||
'BI': "Burundi",
|
||||
'BJ': "Benin",
|
||||
'BM': "Bermuda",
|
||||
'BN': "Brunei Darussalam",
|
||||
'BO': "Bolivia",
|
||||
'BR': "Brazil",
|
||||
'BS': "Bahamas",
|
||||
'BT': "Bhutan",
|
||||
'BW': "Botswana",
|
||||
'BY': "Belarus",
|
||||
'BZ': "Belize",
|
||||
'CA': "Canada",
|
||||
'CD': "Congo the Democratic Republic of the",
|
||||
'CF': "Central African Republic",
|
||||
'CH': "Switzerland",
|
||||
'CI': "Cote D'ivoire",
|
||||
'CK': "Cook Islands",
|
||||
'CL': "Chile",
|
||||
'CM': "Cameroon",
|
||||
'CN': "China",
|
||||
'CO': "Colombia",
|
||||
'CR': "Costa Rica",
|
||||
'CS': "Serbia and Montenegro",
|
||||
'CU': "Cuba",
|
||||
'CY': "Cyprus",
|
||||
'CZ': "Czech Republic",
|
||||
'DE': "Germany",
|
||||
'DJ': "Djibouti",
|
||||
'DK': "Denmark",
|
||||
'DO': "Dominican Republic",
|
||||
'DZ': "Algeria",
|
||||
'EC': "Ecuador",
|
||||
'EE': "Estonia",
|
||||
'EG': "Egypt",
|
||||
'ER': "Eritrea",
|
||||
'ES': "Spain",
|
||||
'ET': "Ethiopia",
|
||||
'EU': "European Union",
|
||||
'FI': "Finland",
|
||||
'FJ': "Fiji",
|
||||
'FM': "Micronesia Federated States of",
|
||||
'FO': "Faroe Islands",
|
||||
'FR': "France",
|
||||
'GA': "Gabon",
|
||||
'GB': "United Kingdom",
|
||||
'GD': "Grenada",
|
||||
'GE': "Georgia",
|
||||
'GF': "French Guiana",
|
||||
'GG': "Guernsey",
|
||||
'GH': "Ghana",
|
||||
'GI': "Gibraltar",
|
||||
'GL': "Greenland",
|
||||
'GM': "Gambia",
|
||||
'GP': "Guadeloupe",
|
||||
'GR': "Greece",
|
||||
'GT': "Guatemala",
|
||||
'GU': "Guam",
|
||||
'GW': "Guinea-Bissau",
|
||||
'GY': "Guyana",
|
||||
'HK': "Hong Kong",
|
||||
'HN': "Honduras",
|
||||
'HR': "Croatia (Local Name: Hrvatska)",
|
||||
'HT': "Haiti",
|
||||
'HU': "Hungary",
|
||||
'ID': "Indonesia",
|
||||
'IE': "Ireland",
|
||||
'IL': "Israel",
|
||||
'IM': "Isle of Man",
|
||||
'IN': "India",
|
||||
'IO': "British Indian Ocean Territory",
|
||||
'IQ': "Iraq",
|
||||
'IR': "Iran (Islamic Republic of)",
|
||||
'IS': "Iceland",
|
||||
'IT': "Italy",
|
||||
'JE': "Jersey",
|
||||
'JM': "Jamaica",
|
||||
'JO': "Jordan",
|
||||
'JP': "Japan",
|
||||
'KE': "Kenya",
|
||||
'KG': "Kyrgyzstan",
|
||||
'KH': "Cambodia",
|
||||
'KI': "Kiribati",
|
||||
'KN': "Saint Kitts and Nevis",
|
||||
'KR': "Korea Republic of",
|
||||
'KW': "Kuwait",
|
||||
'KY': "Cayman Islands",
|
||||
'KZ': "Kazakhstan",
|
||||
'LA': "Lao People's Democratic Republic",
|
||||
'LB': "Lebanon",
|
||||
'LC': "Saint Lucia",
|
||||
'LI': "Liechtenstein",
|
||||
'LK': "Sri Lanka",
|
||||
'LR': "Liberia",
|
||||
'LS': "Lesotho",
|
||||
'LT': "Lithuania",
|
||||
'LU': "Luxembourg",
|
||||
'LV': "Latvia",
|
||||
'LY': "Libyan Arab Jamahiriya",
|
||||
'MA': "Morocco",
|
||||
'MC': "Monaco",
|
||||
'MD': "Moldova Republic of",
|
||||
'MG': "Madagascar",
|
||||
'MH': "Marshall Islands",
|
||||
'MK': "Macedonia the Former Yugoslav Republic of",
|
||||
'ML': "Mali",
|
||||
'MM': "Myanmar",
|
||||
'MN': "Mongolia",
|
||||
'MO': "Macau",
|
||||
'MP': "Northern Mariana Islands",
|
||||
'MR': "Mauritania",
|
||||
'MS': "Montserrat",
|
||||
'MT': "Malta",
|
||||
'MU': "Mauritius",
|
||||
'MV': "Maldives",
|
||||
'MW': "Malawi",
|
||||
'MX': "Mexico",
|
||||
'MY': "Malaysia",
|
||||
'MZ': "Mozambique",
|
||||
'NA': "Namibia",
|
||||
'NC': "New Caledonia",
|
||||
'NF': "Norfolk Island",
|
||||
'NG': "Nigeria",
|
||||
'NI': "Nicaragua",
|
||||
'NL': "Netherlands",
|
||||
'NO': "Norway",
|
||||
'NP': "Nepal",
|
||||
'NR': "Nauru",
|
||||
'NU': "Niue",
|
||||
'NZ': "New Zealand",
|
||||
'OM': "Oman",
|
||||
'PA': "Panama",
|
||||
'PE': "Peru",
|
||||
'PF': "French Polynesia",
|
||||
'PG': "Papua New Guinea",
|
||||
'PH': "Philippines",
|
||||
'PK': "Pakistan",
|
||||
'PL': "Poland",
|
||||
'PR': "Puerto Rico",
|
||||
'PS': "Palestinian Territory Occupied",
|
||||
'PT': "Portugal",
|
||||
'PW': "Palau",
|
||||
'PY': "Paraguay",
|
||||
'QA': "Qatar",
|
||||
'RO': "Romania",
|
||||
'RS': "Serbia",
|
||||
'RU': "Russian Federation",
|
||||
'RW': "Rwanda",
|
||||
'SA': "Saudi Arabia",
|
||||
'SB': "Solomon Islands",
|
||||
'SC': "Seychelles",
|
||||
'SD': "Sudan",
|
||||
'SE': "Sweden",
|
||||
'SG': "Singapore",
|
||||
'SI': "Slovenia",
|
||||
'SK': "Slovakia (Slovak Republic)",
|
||||
'SL': "Sierra Leone",
|
||||
'SM': "San Marino",
|
||||
'SN': "Senegal",
|
||||
'SR': "Suriname",
|
||||
'SV': "El Salvador",
|
||||
'SY': "Syrian Arab Republic",
|
||||
'SZ': "Swaziland",
|
||||
'TC': "Turks and Caicos Islands",
|
||||
'TG': "Togo",
|
||||
'TH': "Thailand",
|
||||
'TJ': "Tajikistan",
|
||||
'TM': "Turkmenistan",
|
||||
'TN': "Tunisia",
|
||||
'TO': "Tonga",
|
||||
'TR': "Turkey",
|
||||
'TT': "Trinidad and Tobago",
|
||||
'TV': "Tuvalu",
|
||||
'TW': "Taiwan Province of China",
|
||||
'TZ': "Tanzania United Republic of",
|
||||
'UA': "Ukraine",
|
||||
'UG': "Uganda",
|
||||
'US': "United States",
|
||||
'UY': "Uruguay",
|
||||
'UZ': "Uzbekistan",
|
||||
'VA': "Holy See (Vatican City State)",
|
||||
'VE': "Venezuela",
|
||||
'VG': "Virgin Islands (British)",
|
||||
'VI': "Virgin Islands (U.S.)",
|
||||
'VN': "Viet Nam",
|
||||
'VU': "Vanuatu",
|
||||
'WF': "Wallis and Futuna Islands",
|
||||
'WS': "Samoa",
|
||||
'YE': "Yemen",
|
||||
'ZA': "South Africa",
|
||||
'ZM': "Zambia",
|
||||
'ZW': "Zimbabwe",
|
||||
'ZZ': "Reserved"
|
||||
},
|
||||
|
||||
'browsers': {
|
||||
'UNKNOWN': "Unknown",
|
||||
'MSIE': "Internet Explorer",
|
||||
'FIREFOX': "Firefox",
|
||||
'OPERA': "Opera",
|
||||
'SAFARI': "Safari",
|
||||
'OMNIWEB': "OmniWeb",
|
||||
'CAMINO': "Camino",
|
||||
'CHROME': "Chrome"
|
||||
},
|
||||
|
||||
'operatingSystems': {
|
||||
'UNKNOWN': "Unknown",
|
||||
'WINDOWS': "Windows",
|
||||
'MAC': "Mac",
|
||||
'LINUX': "Linux",
|
||||
'IPHONE': "iPhone",
|
||||
'MOBILE': "Mobile",
|
||||
'OPENBSD': "OpenBSD",
|
||||
'FREEBSD': "FreeBSD",
|
||||
'NETBSD': "NetBSD"
|
||||
},
|
||||
*/
|
||||
|
||||
// Calendar texts
|
||||
'calendarStrings': {
|
||||
'months': {
|
||||
'0': "January",
|
||||
'1': "February",
|
||||
'2': "March",
|
||||
'3': "April",
|
||||
'4': "May",
|
||||
'5': "June",
|
||||
'6': "July",
|
||||
'7': "August",
|
||||
'8': "September",
|
||||
'9': "October",
|
||||
'10': "November",
|
||||
'11': "December"
|
||||
},
|
||||
'shortMonths': {
|
||||
'0': "Jan",
|
||||
'1': "Feb",
|
||||
'2': "Mar",
|
||||
'3': "Apr",
|
||||
'4': "May",
|
||||
'5': "Jun",
|
||||
'6': "Jul",
|
||||
'7': "Aug",
|
||||
'8': "Sep",
|
||||
'9': "Oct",
|
||||
'10': "Nov",
|
||||
'11': "Dec"
|
||||
},
|
||||
|
||||
'days': {
|
||||
'0': "Sunday",
|
||||
'1': "Monday",
|
||||
'2': "Tuesday",
|
||||
'3': "Wednesday",
|
||||
'4': "Thursday",
|
||||
'5': "Friday",
|
||||
'6': "Saturday"
|
||||
},
|
||||
|
||||
'shortDays': {
|
||||
'0': "Sun",
|
||||
'1': "Mon",
|
||||
'2': "Tue",
|
||||
'3': "Wed",
|
||||
'4': "Thu",
|
||||
'5': "Fri",
|
||||
'6': "Sat"
|
||||
},
|
||||
|
||||
'veryShortDays': {
|
||||
'0': "Su",
|
||||
'1': "Mo",
|
||||
'2': "Tu",
|
||||
'3': "We",
|
||||
'4': "Th",
|
||||
'5': "Fr",
|
||||
'6': "Sa"
|
||||
},
|
||||
|
||||
'amDesignation': "am",
|
||||
'pmDesignation': "pm"
|
||||
|
||||
},
|
||||
|
||||
// Date format
|
||||
'fullDate_format': "l, F d, Y H:i:s",
|
||||
|
||||
//################################################################################
|
||||
|
||||
'pageHeader': {
|
||||
'donation': "donate",
|
||||
'forum': "forum",
|
||||
'credits': "credits",
|
||||
'feedback': "feedback",
|
||||
'help': "help"
|
||||
},
|
||||
|
||||
'bookmarkletCopy': {
|
||||
'noExceptionMessage': "The direct login configuration has been collected.",
|
||||
'exceptionMessage': "Sorry! There was an error while processing the page.",
|
||||
'copy': "copy",
|
||||
'successfulMessage': "DONE!",
|
||||
'failMessage': "Failed! :("
|
||||
},
|
||||
|
||||
//################################################################################
|
||||
|
||||
__syntaxFix__: "syntax fix"
|
||||
}
|
||||
1336
frontend/delta/js/Clipperz/PM/Strings/Strings_en-US.js
Normal file
1336
frontend/delta/js/Clipperz/PM/Strings/Strings_en-US.js
Normal file
File diff suppressed because it is too large
Load Diff
189
frontend/delta/js/Clipperz/PM/Toll.js
Normal file
189
frontend/delta/js/Clipperz/PM/Toll.js
Normal file
@@ -0,0 +1,189 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
|
||||
if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
|
||||
|
||||
//=============================================================================
|
||||
|
||||
Clipperz.PM.Toll = function(args) {
|
||||
args = args || {};
|
||||
|
||||
this._requestType = args.requestType;
|
||||
this._targetValue = args.targetValue;
|
||||
this._cost = args.cost;
|
||||
this._toll = null;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
Clipperz.PM.Toll.prototype = MochiKit.Base.update(null, {
|
||||
|
||||
'toString': function() {
|
||||
return "Clipperz.PM.Toll (" + this.requestType() + ": " + this.cost() + " - " + ((this.toll() == null)? 'UNPAID' : 'PAID') + ")";
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'requestType': function() {
|
||||
return this._requestType;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'targetValue': function() {
|
||||
return this._targetValue;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'cost': function() {
|
||||
return this._cost;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'toll': function() {
|
||||
return this._toll;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
'__pay': function() {
|
||||
var result;
|
||||
var targetData;
|
||||
var targetMatchSize;
|
||||
var prefixMatchingBits;
|
||||
var payment;
|
||||
var i;
|
||||
|
||||
if (this.toll() == null) {
|
||||
i = 0;
|
||||
targetData = new Clipperz.ByteArray("0x" + this.targetValue());
|
||||
targetMatchSize = this.cost();
|
||||
|
||||
payment = Clipperz.Crypto.PRNG.defaultRandomGenerator().getRandomBytes(32);
|
||||
|
||||
do {
|
||||
var paymentData;
|
||||
|
||||
//payment = Clipperz.Crypto.PRNG.defaultRandomGenerator().getRandomBytes(32);
|
||||
payment.increment();
|
||||
paymentData = Clipperz.Crypto.SHA.sha256(payment);
|
||||
// prefixMatchingBits = this.prefixMatchingBits(targetData, paymentData);
|
||||
prefixMatchingBits = Clipperz.ByteArray.prefixMatchingBits(targetData, paymentData);
|
||||
i++;
|
||||
} while (prefixMatchingBits < targetMatchSize);
|
||||
|
||||
this._toll = payment.toHexString().substring(2)
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'innerDeferredPay': function (aTargetValue, aCost, aPayment) {
|
||||
var deferredResult;
|
||||
var result;
|
||||
var payment;
|
||||
var i;
|
||||
|
||||
result = null;
|
||||
payment = aPayment;
|
||||
i = 0;
|
||||
|
||||
while ((result == null) && (i < Clipperz.PM.Toll.numberOfCloseLoopIterations)) {
|
||||
if (Clipperz.ByteArray.prefixMatchingBits(aTargetValue, Clipperz.Crypto.SHA.sha256(payment)) > aCost) {
|
||||
result = payment;
|
||||
} else {
|
||||
payment.increment();
|
||||
}
|
||||
|
||||
i ++;
|
||||
}
|
||||
|
||||
if (result == null) {
|
||||
deferredResult = MochiKit.Async.callLater(Clipperz.PM.Toll.pauseBetweenEachCloseLoop, MochiKit.Base.method(this, 'innerDeferredPay', aTargetValue, aCost, aPayment));
|
||||
} else {
|
||||
deferredResult = MochiKit.Async.succeed(result);
|
||||
}
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
'deferredPay': function () {
|
||||
var deferredResult;
|
||||
var toll;
|
||||
|
||||
toll = this;
|
||||
deferredResult = new Clipperz.Async.Deferred("Toll.deferredPay");
|
||||
//deferredResult.addLog("--->>> deferredPay - " + this.cost());
|
||||
deferredResult.addMethod(Clipperz.Crypto.PRNG.defaultRandomGenerator(), 'getRandomBytes', 32);
|
||||
deferredResult.addMethod(toll, 'innerDeferredPay', new Clipperz.ByteArray("0x" + this.targetValue()), this.cost());
|
||||
deferredResult.addCallback(MochiKit.Base.bind(function(aPayment) {
|
||||
var result;
|
||||
|
||||
result = {
|
||||
targetValue: this.targetValue(),
|
||||
toll: aPayment.toHexString().substr(2)
|
||||
};
|
||||
|
||||
return result;
|
||||
}, this));
|
||||
//deferredResult.addLog("<<<--- deferredPay - " + this.cost());
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
__syntaxFix__: "syntax fix"
|
||||
|
||||
});
|
||||
|
||||
|
||||
Clipperz.PM.Toll.validate = function(aTargetValue, aToll, aCost) {
|
||||
var result;
|
||||
var tollValue;
|
||||
var targetValue;
|
||||
var hashedTollValue;
|
||||
var payedToll;
|
||||
|
||||
tollValue = new Clipperz.ByteArray("0x" + aToll);
|
||||
targetValue = new Clipperz.ByteArray("0x" + aTargetValue);
|
||||
hashedTollValue = Clipperz.Crypto.SHA.sha256(tollValue);
|
||||
|
||||
payedToll = Clipperz.ByteArray.prefixMatchingBits(targetValue, hashedTollValue);
|
||||
|
||||
if (payedToll < aCost) {
|
||||
result = false;
|
||||
} else {
|
||||
result = true;
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
Clipperz.PM.Toll.numberOfCloseLoopIterations = 50;
|
||||
Clipperz.PM.Toll.pauseBetweenEachCloseLoop = 0.5;
|
||||
142
frontend/delta/js/Clipperz/PM/UI/Components/CardDetail.js
Normal file
142
frontend/delta/js/Clipperz/PM/UI/Components/CardDetail.js
Normal file
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
Clipperz.PM.UI.Components.CardDetail = React.createClass({
|
||||
|
||||
getDefaultProps: function () {
|
||||
return {
|
||||
// searchDelay: 0.3
|
||||
}
|
||||
},
|
||||
|
||||
propTypes: {
|
||||
card: React.PropTypes.object.isRequired
|
||||
},
|
||||
|
||||
getInitialState: function () {
|
||||
return {
|
||||
// showSearch: false,
|
||||
// searchTimer: null,
|
||||
starred: false
|
||||
};
|
||||
},
|
||||
|
||||
handleDirectLoginClick: function (aDirectLoginReference, anEvent) {
|
||||
MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'runDirectLogin', {record:this.props.card['reference'], directLogin:aDirectLoginReference});
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
normalizeFieldValue: function (aValue) {
|
||||
var result = [];
|
||||
var rows = aValue.split('\n');
|
||||
|
||||
for (var i = 0; i < rows.length; i++) {
|
||||
if (i > 0) {
|
||||
result.push(React.DOM.br());
|
||||
}
|
||||
result.push(rows[i].replace(/[\s]/g, '\u00A0'));
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
renderField: function (aField) {
|
||||
//console.log("FIELD", aField);
|
||||
var actionLabel;
|
||||
|
||||
if (aField['actionType'] == 'URL') {
|
||||
actionLabel = "go";
|
||||
} else if (aField['actionType'] == 'PASSWORD') {
|
||||
actionLabel = "locked";
|
||||
} else if (aField['actionType'] == 'EMAIL') {
|
||||
actionLabel = "email";
|
||||
} else {
|
||||
actionLabel = "";
|
||||
}
|
||||
|
||||
return React.DOM.div({className:'listItem ' + aField['actionType']}, [
|
||||
React.DOM.div({className:'fieldWrapper'}, [
|
||||
React.DOM.div({className:'fieldInnerWrapper'}, [
|
||||
React.DOM.div({className:'labelWrapper'}, React.DOM.span({className:'label'}, aField['label'])),
|
||||
React.DOM.div({className:'valueWrapper'}, React.DOM.span({className:'value ' + aField['actionType']}, this.normalizeFieldValue(aField['value'])))
|
||||
])
|
||||
]),
|
||||
React.DOM.div({className:'actionWrapper'}, [
|
||||
React.DOM.div({className:aField['actionType']}, actionLabel)
|
||||
])
|
||||
]);
|
||||
},
|
||||
|
||||
renderDirectLogin: function (aDirectLogin) {
|
||||
//console.log("DIRECT LOGIN", aDirectLogin);
|
||||
return React.DOM.div({className:'listItem', onClick:MochiKit.Base.method(this, 'handleDirectLoginClick', aDirectLogin['reference'])}, [
|
||||
React.DOM.div({className:'labelWrapper'}, React.DOM.span({className:'label'}, aDirectLogin['label'])),
|
||||
React.DOM.div({className:'faviconWrapper'}, React.DOM.img({className:'favicon', src:aDirectLogin['favicon']})),
|
||||
React.DOM.div({className:'directLoginLinkWrapper'}, React.DOM.span({className:'directLoginLink'}, "go"))
|
||||
]);
|
||||
},
|
||||
|
||||
handleBackClick: function (anEvent) {
|
||||
window.history.back();
|
||||
},
|
||||
|
||||
handleStarClick: function (anEvent) {
|
||||
this.setState({starred: !this.state['starred']});
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
render: function () {
|
||||
var card = this.props.card;
|
||||
var starredStatus = (this.state['starred'] ? "starred" : "unstarred");
|
||||
|
||||
if ((typeof(card['fields']) != 'undefined') && (card['notes'] != '')) {
|
||||
card['fields'].push({ 'actionType': 'NOTES', 'isHidden': false, 'label': "notes", 'reference': "notes", 'value': card['notes'] })
|
||||
}
|
||||
|
||||
return React.DOM.div({className:'cardDetail'}, [
|
||||
React.DOM.div({className:'header'}, [
|
||||
React.DOM.div({className:'titleWrapper'}, React.DOM.div({className:'title'}, card.title)),
|
||||
// React.DOM.div({className:'titleWrapper'}, React.DOM.div({className:'title'}, card.title + ' ' + card.title + ' ' + card.title + ' ' + card.title)),
|
||||
React.DOM.div({className:'backWrapper'}, React.DOM.a({className:'button back', onClick:this.handleBackClick}, "back")),
|
||||
React.DOM.div({className:'starWrapper'}, React.DOM.a({className:'star', onClick:this.handleStarClick}, starredStatus))
|
||||
]),
|
||||
React.DOM.div({className:'content'}, [
|
||||
card.fields ? React.DOM.div({className:'fields'}, MochiKit.Base.map(this.renderField, card.fields)) : null,
|
||||
card.directLogins ? React.DOM.div({className:'directLogins'}, MochiKit.Base.map(this.renderDirectLogin, card.directLogins)): null
|
||||
]),
|
||||
React.DOM.div({className:'footer'}, [
|
||||
/*
|
||||
// React.DOM.a({className:'cancel'}, "cancel"),
|
||||
// React.DOM.a({className:'save'}, "save")
|
||||
|
||||
React.DOM.a({className:'cancel button'}, "failed"),
|
||||
React.DOM.a({className:'save button'}, "done")
|
||||
*/
|
||||
])
|
||||
]);
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
});
|
||||
161
frontend/delta/js/Clipperz/PM/UI/Components/CardList.js
Normal file
161
frontend/delta/js/Clipperz/PM/UI/Components/CardList.js
Normal file
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
Clipperz.PM.UI.Components.CardList = React.createClass({
|
||||
|
||||
getDefaultProps: function () {
|
||||
return {
|
||||
selectedCard: null,
|
||||
searchDelay: 0.3
|
||||
}
|
||||
},
|
||||
|
||||
propTypes: {
|
||||
searchDelay: React.PropTypes.number
|
||||
},
|
||||
|
||||
getInitialState: function () {
|
||||
return {
|
||||
showSearch: false,
|
||||
searchTimer: null,
|
||||
searchText: '',
|
||||
// passphrase: '',
|
||||
// pin: ''
|
||||
};
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
toggleSearch: function (anEvent) {
|
||||
var showSearchBox;
|
||||
|
||||
showSearchBox = !this.state.showSearch;
|
||||
|
||||
this.setState({showSearch: showSearchBox});
|
||||
|
||||
if (showSearchBox) {
|
||||
MochiKit.Async.callLater(0.1, MochiKit.Base.method(this, 'focusOnSearchField'));
|
||||
}
|
||||
},
|
||||
|
||||
updateSearchText: function (anEvent) {
|
||||
var searchText;
|
||||
|
||||
searchText = anEvent.target.value;
|
||||
//console.log(">>> updateSearchText", searchText);
|
||||
|
||||
if ((this.state['searchTimer'] != null) && (searchText != this.state['searchText'])) {
|
||||
this.state['searchTimer'].cancel();
|
||||
}
|
||||
|
||||
if (searchText != this.state['searchText']) {
|
||||
this.state['searchText'] = searchText;
|
||||
this.state['searchTimer'] = MochiKit.Async.callLater(this.props['searchDelay'], MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'searchCards', searchText);
|
||||
}
|
||||
},
|
||||
|
||||
focusOnSearchField: function () {
|
||||
console.log("focusOnSearchField", this.refs['searchField']);
|
||||
this.refs['searchField'].getDOMNode.focus();
|
||||
},
|
||||
|
||||
searchBox: function () {
|
||||
var result;
|
||||
|
||||
if (this.state.showSearch) {
|
||||
result = React.DOM.div({className:'searchBox'}, [
|
||||
React.DOM.div(null, [
|
||||
React.DOM.input({type:'search', placeholder:"search", ref:'searchField', onChange:this.updateSearchText})
|
||||
])
|
||||
]);
|
||||
} else {
|
||||
result = null;
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
cardItem: function (aRecordReference) {
|
||||
var reference = aRecordReference['_reference'];
|
||||
var selectedCard = (reference == this.props.selectedCard);
|
||||
|
||||
return React.DOM.div({className:'listItem', onClick:MochiKit.Base.method(this, 'handleClickOnCardDetail', reference)}, [
|
||||
React.DOM.div({className:'labelWrapper'}, React.DOM.span({className:'label'}, aRecordReference.label)),
|
||||
// React.DOM.div({className:'labelWrapper'}, React.DOM.span({className:'label'}, aRecordReference.label + ' ' + aRecordReference.label + ' ' + aRecordReference.label + ' ' + aRecordReference.label + ' ' + aRecordReference.label)),
|
||||
React.DOM.div({className:'faviconWrapper'}, aRecordReference.favicon ? React.DOM.img({className:'favicon', src:aRecordReference.favicon}) : React.DOM.div({className:'favicon'}, '\u00A0')),
|
||||
React.DOM.div({className:'detailLinkWrapper'}, React.DOM.span({className:'detailLink ' + (selectedCard ? 'icon-spin' : '')}, (selectedCard ? "loading" : "detail")))
|
||||
]);
|
||||
},
|
||||
|
||||
handleClickOnCardDetail: function (aRecordReference, anEvent) {
|
||||
MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'showRecord', aRecordReference);
|
||||
},
|
||||
|
||||
cardListItems: function () {
|
||||
var list;
|
||||
var result;
|
||||
|
||||
list = this.props['cardList'];
|
||||
|
||||
if (typeof(list) != 'undefined') {
|
||||
result = MochiKit.Base.map(MochiKit.Base.method(this, 'cardItem'), list);
|
||||
} else {
|
||||
result = null;
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
handleChange: function (anEvent) {
|
||||
// var refs = this.refs;
|
||||
// var refName = MochiKit.Base.filter(function (aRefName) { return refs[aRefName].getDOMNode() == anEvent.target}, MochiKit.Base.keys(this.refs))[0];
|
||||
// var newState = {};
|
||||
//
|
||||
// newState[refName] = event.target.value;
|
||||
// this.setState(newState);
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
render: function() {
|
||||
return React.DOM.div(null, [
|
||||
React.DOM.div({className:'header'}, [
|
||||
React.DOM.a({className:'account'}, 'clipperz'),
|
||||
React.DOM.div({className:'features'}, [
|
||||
React.DOM.a({className:'addCard'}, 'add'),
|
||||
React.DOM.a({className:'search ' + (this.state.showSearch ? 'selected' : ''), onClick:this.toggleSearch}, 'search'),
|
||||
React.DOM.a({className:'settings'}, 'settings')
|
||||
]),
|
||||
// this.searchBox()
|
||||
]),
|
||||
this.searchBox(),
|
||||
React.DOM.div({className:'content cardList'}, this.cardListItems()),
|
||||
]);
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
});
|
||||
46
frontend/delta/js/Clipperz/PM/UI/Components/ErrorPage.js
Normal file
46
frontend/delta/js/Clipperz/PM/UI/Components/ErrorPage.js
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
Clipperz.PM.UI.Components.ErrorPage = React.createClass({
|
||||
|
||||
getDefaultProps: function () {
|
||||
return {
|
||||
template: Clipperz.PM.UI.Components.PageTemplate
|
||||
}
|
||||
},
|
||||
|
||||
'propTypes': {
|
||||
// type: React.PropTypes.oneOf(['PERMANENT', 'TEMPORARY']),
|
||||
message: React.PropTypes.string.isRequired,
|
||||
template: React.PropTypes.func
|
||||
},
|
||||
|
||||
|
||||
_render: function () {
|
||||
return React.DOM.div({className:'error-message'}, this.props.message);
|
||||
},
|
||||
|
||||
render: function () {
|
||||
return new this.props.template({'innerComponent': this._render()});
|
||||
}
|
||||
});
|
||||
150
frontend/delta/js/Clipperz/PM/UI/Components/LoginForm.js
Normal file
150
frontend/delta/js/Clipperz/PM/UI/Components/LoginForm.js
Normal file
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
Clipperz.PM.UI.Components.LoginForm = React.createClass({
|
||||
|
||||
getDefaultProps: function () {
|
||||
return {
|
||||
mode: 'CREDENTIALS',
|
||||
isNewUserRegistrationAvailable: false,
|
||||
disabled: false,
|
||||
template: Clipperz.PM.UI.Components.PageTemplate
|
||||
}
|
||||
},
|
||||
|
||||
propTypes: {
|
||||
mode: React.PropTypes.oneOf(['CREDENTIALS','PIN']),
|
||||
isNewUserRegistrationAvailable: React.PropTypes.bool,
|
||||
disabled: React.PropTypes.bool,
|
||||
template: React.PropTypes.func
|
||||
},
|
||||
|
||||
getInitialState: function () {
|
||||
return {
|
||||
username: '',
|
||||
passphrase: '',
|
||||
pin: ''
|
||||
};
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
handleChange: function (anEvent) {
|
||||
var refs = this.refs;
|
||||
var refName = MochiKit.Base.filter(function (aRefName) { return refs[aRefName].getDOMNode() == anEvent.target}, MochiKit.Base.keys(this.refs))[0];
|
||||
var newState = {};
|
||||
|
||||
newState[refName] = event.target.value;
|
||||
this.setState(newState);
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
handleCredentialSubmit: function (event) {
|
||||
event.preventDefault();
|
||||
|
||||
this.refs['passphrase'].getDOMNode().blur();
|
||||
|
||||
var credentials = {
|
||||
'username': this.refs['username'].getDOMNode().value,
|
||||
'passphrase': this.refs['passphrase'].getDOMNode().value
|
||||
}
|
||||
MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'doLogin', credentials);
|
||||
},
|
||||
|
||||
handleRegistrationLinkClick: function (event) {
|
||||
event.preventDefault();
|
||||
MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'showRegistrationForm');
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
shouldEnableLoginButton: function () {
|
||||
var result;
|
||||
|
||||
return (
|
||||
((this.state['username'] != '') && (this.state['passphrase'] != ''))
|
||||
||
|
||||
(this.state['pin'] != '')
|
||||
) && !this.props['disabled'];
|
||||
},
|
||||
|
||||
|
||||
loginForm: function () {
|
||||
registrationLink = React.DOM.div({'className':'registrationLink'}, [
|
||||
React.DOM.a({'onClick':this.handleRegistrationLinkClick}, "Need an account")
|
||||
]);
|
||||
return React.DOM.div({'className':'loginForm credentials'},[
|
||||
React.DOM.form({onChange: this.handleChange, onSubmit:this.handleCredentialSubmit}, [
|
||||
React.DOM.div(null,[
|
||||
React.DOM.label({'for':'name'}, "username"),
|
||||
React.DOM.input({'type':'text', 'name':'name', 'ref':'username', 'placeholder':"username", 'key':'username', 'autoCapitalize':'none'}),
|
||||
React.DOM.label({'for':'passphrase'}, "passphrase"),
|
||||
React.DOM.input({'type':'password', 'name':'passphrase', 'ref':'passphrase', 'placeholder':"passphrase", 'key':'passphrase'})
|
||||
]),
|
||||
React.DOM.button({'type':'submit', 'disabled':!this.shouldEnableLoginButton(), 'className':'button'}, "login")
|
||||
]),
|
||||
this.props.isNewUserRegistrationAvailable ? registrationLink : null
|
||||
]);
|
||||
},
|
||||
|
||||
handlePINSubmit: function (event) {
|
||||
event.preventDefault();
|
||||
|
||||
this.refs['pin'].getDOMNode().blur();
|
||||
|
||||
var credentials = {
|
||||
pin: this.refs['pin'].getDOMNode().value
|
||||
}
|
||||
|
||||
MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'doLogin', credentials);
|
||||
},
|
||||
|
||||
pinForm: function () {
|
||||
return React.DOM.div({'className':'loginForm pin'},[
|
||||
React.DOM.form({onChange: this.handleChange, onSubmit:this.handlePINSubmit}, [
|
||||
React.DOM.div(null,[
|
||||
React.DOM.label({'for':'pin'}, "pin"),
|
||||
React.DOM.input({'type':'text', 'name':'pin', 'ref':'pin', placeholder:"PIN", 'key':'pin', 'autocapitalize':'none'})
|
||||
]),
|
||||
React.DOM.button({'type':'submit', 'disabled':this.props.disabled, 'className':'button'}, "login")
|
||||
])
|
||||
]);
|
||||
},
|
||||
|
||||
setInitialFocus: function () {
|
||||
if (this.props.mode == 'PIN') {
|
||||
this.refs['pin'].getDOMNode().select();
|
||||
} else {
|
||||
if (this.refs['username'].getDOMNode().value == '') {
|
||||
this.refs['username'].getDOMNode().focus();
|
||||
} else{
|
||||
this.refs['passphrase'].getDOMNode().select();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return new this.props.template({'innerComponent': this.props.mode == 'PIN' ? this.pinForm() : this.loginForm()});
|
||||
}
|
||||
});
|
||||
122
frontend/delta/js/Clipperz/PM/UI/Components/Overlay.js
Normal file
122
frontend/delta/js/Clipperz/PM/UI/Components/Overlay.js
Normal file
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
Clipperz.Base.module('Clipperz.PM.UI.Components');
|
||||
|
||||
Clipperz.PM.UI.Components.Overlay = function(args) {
|
||||
args = args || {};
|
||||
|
||||
this._defaultDelay = 2;
|
||||
this._element = MochiKit.DOM.getElement('overlay');
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
||||
Clipperz.Base.extend(Clipperz.PM.UI.Components.Overlay, Object, {
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'toString': function () {
|
||||
return "Clipperz.PM.UI.Components.Overlay component";
|
||||
},
|
||||
|
||||
'element': function () {
|
||||
// return MochiKit.DOM.getElement('overlay');
|
||||
return this._element;
|
||||
},
|
||||
|
||||
'getElement': function (aClass) {
|
||||
return MochiKit.Selector.findChildElements(this.element(), ['.'+aClass])[0];
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'show': function (aMessage) {
|
||||
this.resetStatus();
|
||||
this.setMessage(aMessage);
|
||||
MochiKit.DOM.removeElementClass(this.element(), 'ios-overlay-hide');
|
||||
MochiKit.DOM.addElementClass(this.element(), 'ios-overlay-show');
|
||||
},
|
||||
|
||||
'done': function (aMessage, aDelayBeforeHiding) {
|
||||
this.completed(this.showDoneIcon, aMessage, aDelayBeforeHiding);
|
||||
},
|
||||
|
||||
'failed': function (aMessage, aDelayBeforeHiding) {
|
||||
this.completed(this.showFailIcon, aMessage, aDelayBeforeHiding);
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'resetStatus': function () {
|
||||
MochiKit.Style.showElement(this.element());
|
||||
MochiKit.Style.showElement(this.getElement('spinner'));
|
||||
MochiKit.Style.hideElement(this.getElement('done'));
|
||||
MochiKit.Style.hideElement(this.getElement('failed'));
|
||||
},
|
||||
|
||||
'setMessage': function (aMessage) {
|
||||
if (typeof(aMessage) != 'undefined') {
|
||||
this.getElement('title').innerHTML = aMessage;
|
||||
}
|
||||
},
|
||||
|
||||
'completed': function (aFunctionToShowResult, aMessage, aDelayBeforeHiding) {
|
||||
var delay = aDelayBeforeHiding || this.defaultDelay();
|
||||
|
||||
this.hideSpinner();
|
||||
MochiKit.Base.bind(aFunctionToShowResult, this)();
|
||||
this.setMessage(aMessage);
|
||||
|
||||
MochiKit.Async.callLater(delay, MochiKit.Base.bind(this.hide, this))
|
||||
},
|
||||
|
||||
'hide': function () {
|
||||
MochiKit.DOM.removeElementClass(this.element(), 'ios-overlay-show');
|
||||
MochiKit.DOM.addElementClass(this.element(), 'ios-overlay-hide');
|
||||
MochiKit.Async.callLater(1, MochiKit.Style.hideElement, this.element());
|
||||
},
|
||||
|
||||
'hideSpinner': function () {
|
||||
MochiKit.Style.hideElement(this.getElement('spinner'));
|
||||
},
|
||||
|
||||
'showDoneIcon': function () {
|
||||
MochiKit.Style.showElement(this.getElement('done'));
|
||||
},
|
||||
|
||||
'showFailIcon': function () {
|
||||
MochiKit.Style.showElement(this.getElement('failed'));
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'defaultDelay': function () {
|
||||
return this._defaultDelay;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
__syntaxFix__: "syntax fix"
|
||||
});
|
||||
33
frontend/delta/js/Clipperz/PM/UI/Components/PageTemplate.js
Normal file
33
frontend/delta/js/Clipperz/PM/UI/Components/PageTemplate.js
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
Clipperz.PM.UI.Components.PageTemplate = React.createClass({
|
||||
render: function() {
|
||||
return React.DOM.div(null, [
|
||||
React.DOM.div({'className': 'header'}, [
|
||||
React.DOM.h1(null, "clipperz")
|
||||
]),
|
||||
React.DOM.div({'className': 'content'}, this.props.innerComponent)
|
||||
])
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,240 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
Clipperz.PM.UI.Components.RegistrationWizard = React.createClass({
|
||||
|
||||
getDefaultProps: function () {
|
||||
return {
|
||||
steps: [
|
||||
{name:'CREDENTIALS', label:'registration', _label:'credentials', description:"Choose your credentails"},
|
||||
{name:'PASSWORD_VERIFICATION', label:'registration', _label:'verify', description:"Verify your passphrase"},
|
||||
{name:'TERMS_OF_SERVICE', label:'registration', _label:'terms', description:"Check our terms of service"}
|
||||
],
|
||||
disabled: false,
|
||||
template: Clipperz.PM.UI.Components.PageTemplate
|
||||
}
|
||||
},
|
||||
|
||||
getInitialState: function () {
|
||||
return {
|
||||
currentStep: this.props['steps'][0]['name'],
|
||||
username: '',
|
||||
passphrase: '',
|
||||
verify_passphrase: '',
|
||||
no_password_recovery: false,
|
||||
agree_terms_of_service: false
|
||||
};
|
||||
},
|
||||
|
||||
'propTypes': {
|
||||
// steps: React.PropTypes.array,
|
||||
disabled: React.PropTypes.bool,
|
||||
template: React.PropTypes.func
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
currentStepIndex: function () {
|
||||
return this.indexOfStepNamed(this.state['currentStep']);
|
||||
},
|
||||
|
||||
indexOfStepNamed: function (aStepName) {
|
||||
var stepConfiguration;
|
||||
var result;
|
||||
|
||||
stepConfiguration = this.props['steps'].filter(function (aConfig) { return aConfig['name'] == aStepName})[0];
|
||||
result = this.props['steps'].indexOf(stepConfiguration);
|
||||
return result;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
statusClassForStep: function (aStep) {
|
||||
var currentStepIndex = this.currentStepIndex();
|
||||
var stepIndex = this.indexOfStepNamed(aStep['name']);
|
||||
var result;
|
||||
|
||||
if (stepIndex < currentStepIndex) {
|
||||
result = 'left';
|
||||
} else if (stepIndex == currentStepIndex) {
|
||||
result = 'center';
|
||||
} else {
|
||||
result = 'right';
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
handleBackClick: function (anEvent) {
|
||||
var nextStep;
|
||||
anEvent.preventDefault();
|
||||
|
||||
if (this.currentStepIndex() > 0) {
|
||||
nextStep = this.props['steps'][this.currentStepIndex() - 1];
|
||||
this.setState({currentStep: nextStep['name']});
|
||||
} else {
|
||||
MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'goBack');
|
||||
}
|
||||
},
|
||||
|
||||
handleForwardClick: function (anEvent) {
|
||||
var nextStep;
|
||||
anEvent.preventDefault();
|
||||
|
||||
if (this.canMoveForward()) {
|
||||
|
||||
if (this.currentStepIndex() < this.props['steps'].length - 1) {
|
||||
nextStep = this.props['steps'][this.currentStepIndex() + 1];
|
||||
this.setState({currentStep: nextStep['name']});
|
||||
} else {
|
||||
MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'registerNewUser', {
|
||||
username: this.state['username'],
|
||||
passphrase: this.state['passphrase']
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
canMoveForward: function () {
|
||||
var result;
|
||||
var currentStep;
|
||||
|
||||
result = false;
|
||||
currentStep = this.state['currentStep'];
|
||||
if (currentStep == 'CREDENTIALS') {
|
||||
result = ((this.state['username'] != '') && (this.state['passphrase'] != ''));
|
||||
} else if (currentStep == 'PASSWORD_VERIFICATION') {
|
||||
result = (this.state['passphrase'] == this.state['verify_passphrase']);
|
||||
} else if (currentStep == 'TERMS_OF_SERVICE') {
|
||||
result = (this.state['no_password_recovery'] && this.state['agree_terms_of_service']);
|
||||
}
|
||||
|
||||
return result && !this.props['disabled'];
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
handleChange: function (anEvent) {
|
||||
var refs = this.refs;
|
||||
var refName = MochiKit.Base.filter(function (aRefName) { return refs[aRefName].getDOMNode() == anEvent.target}, MochiKit.Base.keys(this.refs))[0];
|
||||
var newState = {};
|
||||
|
||||
if ((event.target.type == 'checkbox') || (event.target.type == 'radio')) {
|
||||
newState[refName] = event.target.checked;
|
||||
} else {
|
||||
newState[refName] = event.target.value;
|
||||
}
|
||||
this.setState(newState);
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
renderIndexStep: function (aStep) {
|
||||
return React.DOM.div({'className':'stepIndexItem ' + this.statusClassForStep(aStep)}, '.');
|
||||
},
|
||||
|
||||
renderButtons: function () {
|
||||
return [
|
||||
React.DOM.a({className:'back button step_' + (this.currentStepIndex() - 1), onClick:this.handleBackClick}, '<<'),
|
||||
React.DOM.a({className:'forward button step_' + (this.currentStepIndex() + 1) + ' ' + (this.canMoveForward() ? 'enabled' : 'disabled'), onClick:this.handleForwardClick}, '>>')
|
||||
];
|
||||
},
|
||||
|
||||
render_CREDENTIALS: function () {
|
||||
return React.DOM.div(null,[
|
||||
React.DOM.label({'for':'name'}, "username"),
|
||||
React.DOM.input({'type':'text', 'name':'name', 'ref':'username', 'placeholder':"username", 'key':'username', 'autoCapitalize':'none'/*, value:this.state.username*/}),
|
||||
React.DOM.label({'for':'passphrase'}, "passphrase"),
|
||||
React.DOM.input({'type':'password', 'name':'passphrase', 'ref':'passphrase', 'placeholder':"passphrase", 'key':'passphrase'/*, value:this.state.passphrase*/})
|
||||
]);
|
||||
},
|
||||
|
||||
render_PASSWORD_VERIFICATION: function () {
|
||||
return React.DOM.div(null,[
|
||||
React.DOM.label({'for':'verify_passphrase'}, "passphrase"),
|
||||
React.DOM.input({'type':'password', 'name':'verify_passphrase', 'ref':'verify_passphrase', 'placeholder':"verify passphrase", 'key':'verify_passphrase'})
|
||||
]);
|
||||
},
|
||||
|
||||
render_TERMS_OF_SERVICE: function () {
|
||||
return React.DOM.div(null, [
|
||||
React.DOM.div({className:'checkboxBlock'}, [
|
||||
React.DOM.label({'for':'no_password_recovery'}, "I understand that Clipperz will not be able to recover a lost passphrase."),
|
||||
React.DOM.input({'type':'checkbox', 'name':'no_password_recovery', 'ref':'no_password_recovery', 'key':'no_password_recovery'}),
|
||||
React.DOM.p(null, "I understand that Clipperz will not be able to recover a lost passphrase.")
|
||||
]),
|
||||
React.DOM.div({className:'checkboxBlock'}, [
|
||||
React.DOM.label({'for':'agree_terms_of_service'}, "I have read and agreed to the Terms of Service."),
|
||||
React.DOM.input({'type':'checkbox', 'name':'agree_terms_of_service', 'ref':'agree_terms_of_service', 'key':'agree_terms_of_service'}),
|
||||
React.DOM.p(null, [
|
||||
"I have read and agreed to the ",
|
||||
React.DOM.a({href:'https://clipperz.com/terms_service/', target:'_blank'}, "Terms of Service.")
|
||||
])
|
||||
])
|
||||
]);
|
||||
},
|
||||
|
||||
renderStep: function (aStep) {
|
||||
return React.DOM.div({'className':'step' + ' ' + aStep['name'] + ' ' + this.statusClassForStep(aStep) + ' step_' + this.currentStepIndex()}, [
|
||||
React.DOM.h1(null, aStep['label']),
|
||||
React.DOM.p(null, aStep['description']),
|
||||
this['render_' + aStep['name']].apply(),
|
||||
React.DOM.div({'className':'stepIndex'}, MochiKit.Base.map(this.renderIndexStep, this.props['steps'])),
|
||||
React.DOM.div({'className':'buttons'}, this.renderButtons())
|
||||
]);
|
||||
},
|
||||
|
||||
_render: function () {
|
||||
return React.DOM.div({'className':'registrationForm'},[
|
||||
React.DOM.form({onChange: this.handleChange}, [
|
||||
React.DOM.div({'className':'steps'}, MochiKit.Base.map(this.renderStep, this.props['steps']))
|
||||
])
|
||||
]);
|
||||
},
|
||||
|
||||
render: function () {
|
||||
return new this.props.template({'innerComponent': this._render()});
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
setInitialFocus: function () {
|
||||
this.refs['username'].getDOMNode().focus();
|
||||
},
|
||||
|
||||
componentDidUpdate: function (prevProps, prevState, rootNode) {
|
||||
if (prevState['currentStep'] != this.state['currentStep']) {
|
||||
if (this.state['currentStep'] == 'CREDENTIALS') {
|
||||
this.refs['passphrase'].getDOMNode().select();
|
||||
} else if (this.state['currentStep'] == 'PASSWORD_VERIFICATION') {
|
||||
this.refs['verify_passphrase'].getDOMNode().select();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
});
|
||||
256
frontend/delta/js/Clipperz/PM/UI/DirectLoginController.js
Normal file
256
frontend/delta/js/Clipperz/PM/UI/DirectLoginController.js
Normal file
@@ -0,0 +1,256 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
Clipperz.Base.module('Clipperz.PM.UI');
|
||||
|
||||
Clipperz.PM.UI.DirectLoginRunner = function(args) {
|
||||
this._directLogin = args['directLogin'] || Clipperz.Base.exception.raise('MandatoryParameter');
|
||||
this._target = Clipperz.PM.Crypto.randomKey();
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
MochiKit.Base.update(Clipperz.PM.UI.DirectLoginRunner.prototype, {
|
||||
|
||||
'toString': function() {
|
||||
return "Clipperz.PM.UI.DirectLoginRunner";
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'directLogin': function () {
|
||||
return this._directLogin;
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'target': function () {
|
||||
return this._target;
|
||||
},
|
||||
|
||||
//=============================================================================
|
||||
|
||||
'setWindowTitle': function (aWindow, aTitle) {
|
||||
aWindow.document.title = aTitle;
|
||||
},
|
||||
|
||||
'setWindowBody': function (aWindow, anHTML) {
|
||||
aWindow.document.body.innerHTML = anHTML;
|
||||
},
|
||||
|
||||
//=============================================================================
|
||||
|
||||
'initialWindowSetup': function (aWindow) {
|
||||
this.setWindowTitle(aWindow, "Loading Clipperz Direct Login");
|
||||
this.setWindowBody (aWindow, MochiKit.DOM.toHTML(MochiKit.DOM.H3("Loading Clipperz Direct Login ...")));
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'updateWindowWithDirectLoginLabel': function (aWindow, aLabel) {
|
||||
var titleText;
|
||||
var bodyText;
|
||||
|
||||
titleText = "Loading '__label__' Direct Login".replace(/__label__/, aLabel)
|
||||
bodyText = "Loading '__label__' Direct Login... ".replace(/__label__/, aLabel)
|
||||
|
||||
this.setWindowTitle(aWindow, titleText);
|
||||
this.setWindowBody (aWindow, MochiKit.DOM.toHTML(MochiKit.DOM.H3(bodyText)));
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
'updateWindowWithHTMLContent': function (aWindow, anHtml) {
|
||||
this.setWindowBody(aWindow, anHtml);
|
||||
},
|
||||
|
||||
//=============================================================================
|
||||
|
||||
'submitLoginForm': function(aWindow, aSubmitFunction) {
|
||||
MochiKit.DOM.withWindow(aWindow, MochiKit.Base.bind(function () {
|
||||
var formElement;
|
||||
var submitButtons;
|
||||
|
||||
formElement = MochiKit.DOM.getElement('directLoginForm');
|
||||
|
||||
submitButtons = MochiKit.Base.filter(function(anInputElement) {
|
||||
return ((anInputElement.tagName.toLowerCase() == 'input') && (anInputElement.getAttribute('type').toLowerCase() == 'submit'));
|
||||
}, formElement.elements);
|
||||
|
||||
if (submitButtons.length == 0) {
|
||||
if (typeof(formElement.submit) == 'function') {
|
||||
formElement.submit();
|
||||
} else {
|
||||
aSubmitFunction.apply(formElement);
|
||||
}
|
||||
/*
|
||||
var formSubmitFunction;
|
||||
|
||||
formSubmitFunction = MochiKit.Base.method(formElement, 'submit');
|
||||
if (Clipperz_IEisBroken == true) {
|
||||
formElement.submit();
|
||||
} else {
|
||||
formSubmitFunction();
|
||||
}
|
||||
*/
|
||||
} else {
|
||||
submitButtons[0].click();
|
||||
}
|
||||
}, this));
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'runSubmitFormDirectLogin': function (aWindow, someAttributes) {
|
||||
var html;
|
||||
var formElement;
|
||||
var submitFunction;
|
||||
|
||||
formElement = MochiKit.DOM.FORM({
|
||||
'id':'directLoginForm',
|
||||
'method':someAttributes['formAttributes']['method'],
|
||||
'action':someAttributes['formAttributes']['action']
|
||||
});
|
||||
|
||||
submitFunction = formElement.submit;
|
||||
|
||||
MochiKit.DOM.appendChildNodes(formElement, MochiKit.Base.map(function (anInputAttributes) {
|
||||
return MochiKit.DOM.INPUT({'type':'hidden', 'name':anInputAttributes[0], 'value':anInputAttributes[1]});
|
||||
}, MochiKit.Base.items(someAttributes['inputValues'])));
|
||||
|
||||
html = '';
|
||||
html += '<h3>Loading ' + someAttributes['label'] + ' ...</h3>';
|
||||
html += MochiKit.DOM.appendChildNodes(MochiKit.DOM.DIV(), MochiKit.DOM.appendChildNodes(MochiKit.DOM.DIV({style:'display:none; visibility:hidden;'}), formElement)).innerHTML;
|
||||
|
||||
this.updateWindowWithHTMLContent(aWindow, html);
|
||||
this.submitLoginForm(aWindow, submitFunction);
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'runHttpAuthDirectLogin': function(aWindow, someAttributes) {
|
||||
var completeUrl;
|
||||
var url;
|
||||
|
||||
url = someAttributes['inputValues']['url'];
|
||||
|
||||
if (/^https?\:\/\//.test(url) == false) {
|
||||
url = 'http://' + url;
|
||||
}
|
||||
|
||||
if (Clipperz_IEisBroken === true) {
|
||||
completeUrl = url;
|
||||
} else {
|
||||
var username;
|
||||
var password;
|
||||
|
||||
username = someAttributes['inputValues']['username'];
|
||||
password = someAttributes['inputValues']['password'];
|
||||
/(^https?\:\/\/)?(.*)/.test(url);
|
||||
|
||||
completeUrl = RegExp.$1 + username + ':' + password + '@' + RegExp.$2;
|
||||
}
|
||||
|
||||
window.open(completeUrl, this.target());
|
||||
},
|
||||
|
||||
//=============================================================================
|
||||
|
||||
'runDirectLogin': function (aWindow) {
|
||||
var deferredResult;
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("DirectLoginRunner.openDirectLogin", {trace:false});
|
||||
deferredResult.addMethod(this, 'initialWindowSetup', aWindow);
|
||||
deferredResult.addMethod(this.directLogin(), 'label');
|
||||
deferredResult.addMethod(this, 'updateWindowWithDirectLoginLabel', aWindow);
|
||||
deferredResult.collectResults({
|
||||
'type': MochiKit.Base.method(this.directLogin(), 'type'),
|
||||
'label': MochiKit.Base.method(this.directLogin(), 'label'),
|
||||
'formAttributes': MochiKit.Base.method(this.directLogin(), 'formAttributes'),
|
||||
'inputValues': MochiKit.Base.method(this.directLogin(), 'inputValues')
|
||||
});
|
||||
deferredResult.addCallback(MochiKit.Base.bind(function (someAttributes) {
|
||||
switch (someAttributes['type']) {
|
||||
case 'http_auth':
|
||||
this.runHttpAuthDirectLogin(aWindow, someAttributes);
|
||||
break;
|
||||
case 'simple_url':
|
||||
this.runSimpleUrlDirectLogin(aWindow, someAttributes);
|
||||
break;
|
||||
default:
|
||||
this.runSubmitFormDirectLogin(aWindow, someAttributes);
|
||||
break;
|
||||
}
|
||||
}, this));
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//=============================================================================
|
||||
|
||||
'run': function () {
|
||||
var newWindow;
|
||||
|
||||
newWindow = window.open(Clipperz.PM.Strings.getValue('directLoginJumpPageUrl'), this.target());
|
||||
|
||||
return this.runDirectLogin(newWindow);
|
||||
},
|
||||
|
||||
//=============================================================================
|
||||
|
||||
'test': function () {
|
||||
var iFrame;
|
||||
var newWindow;
|
||||
|
||||
iFrame = MochiKit.DOM.createDOM('iframe');
|
||||
MochiKit.DOM.appendChildNodes(MochiKit.DOM.currentDocument().body, iFrame);
|
||||
|
||||
newWindow = iFrame.contentWindow;
|
||||
|
||||
return this.runDirectLogin(newWindow);
|
||||
},
|
||||
|
||||
//=============================================================================
|
||||
__syntaxFix__: "syntax fix"
|
||||
});
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
Clipperz.PM.UI.DirectLoginRunner.openDirectLogin = function (aDirectLogin) {
|
||||
var runner;
|
||||
|
||||
runner = new Clipperz.PM.UI.DirectLoginRunner({directLogin:aDirectLogin});
|
||||
return runner.run();
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
Clipperz.PM.UI.DirectLoginRunner.testDirectLogin = function (aDirectLogin) {
|
||||
var runner;
|
||||
|
||||
runner = new Clipperz.PM.UI.DirectLoginRunner({directLogin:aDirectLogin});
|
||||
return runner.test();
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
491
frontend/delta/js/Clipperz/PM/UI/MainController.js
Normal file
491
frontend/delta/js/Clipperz/PM/UI/MainController.js
Normal file
@@ -0,0 +1,491 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
Clipperz.Base.module('Clipperz.PM.UI');
|
||||
|
||||
Clipperz.PM.UI.MainController = function() {
|
||||
var pages;
|
||||
|
||||
this._proxy = null;
|
||||
this._user = null;
|
||||
this._filter = '';
|
||||
|
||||
// this._currentPage = 'loadingPage';
|
||||
|
||||
this._pageStack = ['loadingPage'];
|
||||
this._overlay = new Clipperz.PM.UI.Components.Overlay();
|
||||
pages = {
|
||||
'loginPage': new Clipperz.PM.UI.Components.LoginForm(),
|
||||
'registrationPage': new Clipperz.PM.UI.Components.RegistrationWizard(),
|
||||
'cardListPage': new Clipperz.PM.UI.Components.CardList(),
|
||||
'cardDetailPage': new Clipperz.PM.UI.Components.CardDetail({card: {}}),
|
||||
'errorPage': new Clipperz.PM.UI.Components.ErrorPage({message:''})
|
||||
};
|
||||
|
||||
MochiKit.Base.map(function (anId) {React.renderComponent(pages[anId], MochiKit.DOM.getElement(anId))}, MochiKit.Base.keys(pages));
|
||||
this._pages = pages;
|
||||
this.registerForNotificationCenterEvents();
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
MochiKit.Base.update(Clipperz.PM.UI.MainController.prototype, {
|
||||
|
||||
toString: function () {
|
||||
return "Clipperz.PM.UI.MainController";
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
overlay: function () {
|
||||
return this._overlay;
|
||||
},
|
||||
|
||||
loginForm: function () {
|
||||
return this._loginForm;
|
||||
},
|
||||
|
||||
registrationWizard: function () {
|
||||
return this._registrationWizard;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
isOnline: function() {
|
||||
return navigator.onLine;
|
||||
},
|
||||
|
||||
hasLocalData: function() {
|
||||
return false;
|
||||
},
|
||||
|
||||
loginMode: function () {
|
||||
// PIN is set using this command:
|
||||
// Clipperz.PM.PIN.setCredentialsWithPIN('1234', {'username':'joe', 'passphrase':'clipperz'});
|
||||
|
||||
return Clipperz.PM.PIN.isSet() ? 'PIN' : 'CREDENTIALS';
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
pages: function () {
|
||||
return this._pages;
|
||||
},
|
||||
|
||||
pageStack: function () {
|
||||
return this._pageStack;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
selectInitialProxy: function () {
|
||||
if (this.isOnline()) {
|
||||
this._proxy = Clipperz.PM.Proxy.defaultProxy;
|
||||
} else {
|
||||
if (this.hasLocalData()) {
|
||||
this._proxy = new Clipperz.PM.Proxy.Offline({dataStore: new Clipperz.PM.Proxy.Offline.LocalStorageDataStore(), shouldPayTolls:false});
|
||||
} else {
|
||||
this.showOfflineError();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
proxy: function () {
|
||||
return this._proxy;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
registerForNotificationCenterEvents: function () {
|
||||
var events = ['doLogin', 'registerNewUser', 'showRegistrationForm', 'goBack', 'showRecord', 'searchCards', 'runDirectLogin'];
|
||||
var self = this;
|
||||
|
||||
MochiKit.Base.map(function (anEvent) {
|
||||
MochiKit.Signal.connect(Clipperz.Signal.NotificationCenter, anEvent, MochiKit.Base.method(self, anEvent));
|
||||
}, events);
|
||||
|
||||
// MochiKit.Signal.connect(window, 'onpopstate', MochiKit.Base.method(this, 'historyGoBack'));
|
||||
MochiKit.Signal.connect(window, 'onbeforeunload', MochiKit.Base.method(this, 'shouldExitApp'));
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
run: function (parameters) {
|
||||
var shouldShowRegistrationForm;
|
||||
|
||||
this.selectInitialProxy();
|
||||
shouldShowRegistrationForm = parameters['shouldShowRegistrationForm'] && this.proxy().canRegisterNewUsers();
|
||||
this.pages()['loginPage'].setProps({'mode':this.loginMode(), 'isNewUserRegistrationAvailable': this.proxy().canRegisterNewUsers()});
|
||||
|
||||
if (shouldShowRegistrationForm) {
|
||||
this.showRegistrationForm();
|
||||
} else {
|
||||
this.showLoginForm();
|
||||
}
|
||||
this.overlay().done("", 0.5);
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
showLoginForm: function () {
|
||||
var loginFormPage;
|
||||
|
||||
loginFormPage = this.pages()['loginPage'];
|
||||
loginFormPage.setProps({'mode':this.loginMode(), 'isNewUserRegistrationAvailable': this.proxy().canRegisterNewUsers()});
|
||||
this.moveInPage(this.currentPage(), 'loginPage');
|
||||
MochiKit.Async.callLater(0.5, MochiKit.Base.method(loginFormPage, 'setInitialFocus'));
|
||||
},
|
||||
|
||||
showRegistrationForm: function () {
|
||||
var currentPage;
|
||||
var registrationPage;
|
||||
|
||||
currentPage = this.currentPage();
|
||||
registrationPage = this.pages()['registrationPage'];
|
||||
this.setCurrentPage('loginPage');
|
||||
registrationPage.setProps({});
|
||||
this.moveInPage(currentPage, 'registrationPage');
|
||||
MochiKit.Async.callLater(0.5, MochiKit.Base.method(registrationPage, 'setInitialFocus'));
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
doLogin: function (event) {
|
||||
var credentials;
|
||||
var getPassphraseDelegate;
|
||||
var user;
|
||||
|
||||
user = null;
|
||||
|
||||
this.overlay().show("logging in");
|
||||
this.pages()['loginPage'].setProps({disabled:true});
|
||||
|
||||
if ('pin' in event) {
|
||||
credentials = Clipperz.PM.PIN.credentialsWithPIN(event['pin']);
|
||||
} else {
|
||||
credentials = event;
|
||||
}
|
||||
getPassphraseDelegate = MochiKit.Base.partial(MochiKit.Async.succeed, credentials.passphrase);
|
||||
user = new Clipperz.PM.DataModel.User({'username':credentials.username, 'getPassphraseFunction':getPassphraseDelegate});
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred('MainController.doLogin', {trace:false});
|
||||
deferredResult.addCallback(MochiKit.Async.wait, 0.1);
|
||||
deferredResult.addMethod(Clipperz.Crypto.PRNG.defaultRandomGenerator(), 'deferredEntropyCollection');
|
||||
deferredResult.addMethod(user, 'login');
|
||||
deferredResult.addMethod(Clipperz.PM.PIN, 'resetFailedAttemptCount');
|
||||
deferredResult.addMethod(this, 'setUser', user);
|
||||
|
||||
// deferredResult.addMethod(this, 'setupApplication');
|
||||
deferredResult.addMethod(this, 'runApplication');
|
||||
deferredResult.addMethod(this.overlay(), 'done', "", 1);
|
||||
deferredResult.addErrback(MochiKit.Base.method(this, 'genericErrorHandler', event));
|
||||
deferredResult.addErrback(MochiKit.Base.bind(function (anEvent, anError) {
|
||||
if (anError['isPermanent'] != true) {
|
||||
this.pages()['loginPage'].setProps({disabled:false, 'mode':this.loginMode()});
|
||||
this.pages()['loginPage'].setInitialFocus();
|
||||
}
|
||||
return anError;
|
||||
}, this, event))
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
registerNewUser: function (credentials) {
|
||||
var deferredResult;
|
||||
|
||||
this.overlay().show("creating user");
|
||||
|
||||
this.pages()['registrationPage'].setProps({disabled:true});
|
||||
deferredResult = new Clipperz.Async.Deferred('MainController.registerNewUser', {trace:false});
|
||||
deferredResult.addCallback(Clipperz.PM.DataModel.User.registerNewAccount,
|
||||
credentials['username'],
|
||||
MochiKit.Base.partial(MochiKit.Async.succeed, credentials['passphrase'])
|
||||
);
|
||||
deferredResult.addMethod(this, 'doLogin', credentials);
|
||||
deferredResult.addErrback(MochiKit.Base.method(this, 'genericErrorHandler', event));
|
||||
deferredResult.addErrback(MochiKit.Base.bind(function (anError) {
|
||||
if (anError['isPermanent'] != true) {
|
||||
this.pages()['registrationPage'].setProps({disabled:false});
|
||||
this.pages()['registrationPage'].setInitialFocus();
|
||||
}
|
||||
return anError;
|
||||
}, this));
|
||||
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
user: function () {
|
||||
return this._user;
|
||||
},
|
||||
|
||||
setUser: function (aUser) {
|
||||
this._user = aUser;
|
||||
return this._user;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
allCardInfo: function () {
|
||||
var deferredResult;
|
||||
var cardInfo;
|
||||
|
||||
cardInfo = {
|
||||
'_rowObject': MochiKit.Async.succeed,
|
||||
'_reference': MochiKit.Base.methodcaller('reference'),
|
||||
'_searchableContent': MochiKit.Base.methodcaller('searchableContent'),
|
||||
'label': MochiKit.Base.methodcaller('label'),
|
||||
'favicon': MochiKit.Base.methodcaller('favicon')
|
||||
};
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred('MainController.allCardInfo', {trace:false});
|
||||
deferredResult.addMethod(this.user(), 'getRecords');
|
||||
deferredResult.addCallback(MochiKit.Base.map, Clipperz.Async.collectResults("CardList.value - collectResults", cardInfo, {trace:false}));
|
||||
deferredResult.addCallback(Clipperz.Async.collectAll);
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
filterCards: function (someCardInfo) {
|
||||
var filter;
|
||||
var filterRegExp;
|
||||
var result;
|
||||
|
||||
filter = this.filter().replace(/[^A-Za-z0-9]/g, "\\$&");
|
||||
filterRegExp = new RegExp(filter, "i");
|
||||
result = MochiKit.Base.filter(function (aCardInfo) { return filterRegExp.test(aCardInfo['_searchableContent'])}, someCardInfo);
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
sortCards: function (someCardInfo) {
|
||||
return someCardInfo.sort(Clipperz.Base.caseInsensitiveKeyComparator('label'));
|
||||
},
|
||||
|
||||
showRecordList: function () {
|
||||
var deferredResult;
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred('MainController.showRecordList', {trace:false});
|
||||
deferredResult.addMethod(this, 'allCardInfo');
|
||||
deferredResult.addMethod(this, 'filterCards');
|
||||
deferredResult.addMethod(this, 'sortCards');
|
||||
deferredResult.addCallback(MochiKit.Base.bind(function (someRecordInfo) {
|
||||
this.pages()['cardListPage'].setProps({cardList: someRecordInfo});
|
||||
}, this));
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
filter: function () {
|
||||
return this._filter;
|
||||
},
|
||||
|
||||
setFilter: function (aValue) {
|
||||
this._filter = aValue;
|
||||
},
|
||||
|
||||
searchCards: function (someParameters) {
|
||||
//console.log("SEARCH CARDS", someParameters);
|
||||
this.setFilter(someParameters);
|
||||
this.showRecordList();
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
runApplication: function () {
|
||||
MochiKit.Signal.connect(window, 'onpopstate', MochiKit.Base.method(this, 'historyGoBack'));
|
||||
this.moveInPage(this.currentPage(), 'cardListPage');
|
||||
return this.showRecordList();
|
||||
},
|
||||
|
||||
showRecord: function (aRecordReference) {
|
||||
//console.log("Show Record", aRecordReference);
|
||||
var deferredResult;
|
||||
|
||||
this.pages()['cardListPage'].setProps({selectedCard:aRecordReference});
|
||||
deferredResult = new Clipperz.Async.Deferred('MainController.runApplication', {trace:false});
|
||||
// deferredResult.addMethod(this.user(), 'getRecord', aRecordReference['_reference']);
|
||||
deferredResult.addMethod(this.user(), 'getRecord', aRecordReference);
|
||||
deferredResult.addMethodcaller('content');
|
||||
deferredResult.addCallback(MochiKit.Base.bind(function (aCard) {
|
||||
//console.log("CARD DETAILS", aCard);
|
||||
this.pages()['cardDetailPage'].setProps({card: aCard});
|
||||
this.pages()['cardListPage'].setProps({selectedCard: null});
|
||||
}, this));
|
||||
deferredResult.addMethod(this, 'moveInPage', this.currentPage(), 'cardDetailPage', true);
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
runDirectLogin: function (someParameters) {
|
||||
console.log("RUN DIRECT LOGIN", someParameters);
|
||||
var deferredResult;
|
||||
|
||||
// this.pages()['cardListPage'].setProps({selectedCard:aRecordReference});
|
||||
deferredResult = new Clipperz.Async.Deferred('MainController.runDirectLogin', {trace:false});
|
||||
// deferredResult.addMethod(this.user(), 'getRecord', aRecordReference['_reference']);
|
||||
deferredResult.addMethod(this.user(), 'getRecord', someParameters['record']);
|
||||
deferredResult.addMethodcaller('directLoginWithReference', someParameters['directLogin']);
|
||||
deferredResult.addCallback(Clipperz.PM.UI.DirectLoginRunner.openDirectLogin);
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
shouldExitApp: function (anEvent) {
|
||||
console.log("SHOULD EXIT APP");
|
||||
anEvent.preventDefault();
|
||||
anEvent.stopPropagation();
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
genericErrorHandler: function (anEvent, anError) {
|
||||
var errorMessage;
|
||||
var result;
|
||||
|
||||
result = anError;
|
||||
errorMessage = "login failed";
|
||||
|
||||
if (anError['isPermanent'] === true) {
|
||||
this.pages()['errorPage'].setProps({message:anError.message});
|
||||
this.moveInPage(this.currentPage(), 'errorPage');
|
||||
errorMessage = "failure";
|
||||
} else {
|
||||
if ('pin' in anEvent) {
|
||||
errorCount = Clipperz.PM.PIN.recordFailedAttempt();
|
||||
if (errorCount == -1) {
|
||||
errorMessage = "PIN resetted";
|
||||
}
|
||||
}
|
||||
}
|
||||
this.overlay().failed(errorMessage, 1);
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
slidePage: function (fromPage, toPage, direction) {
|
||||
var fromPosition;
|
||||
var toPosition;
|
||||
|
||||
if (direction == "LEFT") {
|
||||
fromPosition = 'right';
|
||||
toPosition = 'left'
|
||||
} else {
|
||||
fromPosition = 'left';
|
||||
toPosition = 'right'
|
||||
}
|
||||
|
||||
MochiKit.DOM.addElementClass(fromPage, toPosition + ' transition');
|
||||
|
||||
MochiKit.DOM.addElementClass(toPage, fromPosition);
|
||||
MochiKit.DOM.removeElementClass(toPage, toPosition);
|
||||
MochiKit.DOM.addElementClass(toPage, 'transition');
|
||||
MochiKit.Async.callLater(0.1, function () {
|
||||
MochiKit.DOM.removeElementClass(toPage, fromPosition);
|
||||
})
|
||||
|
||||
MochiKit.Async.callLater(0.5, function () {
|
||||
MochiKit.DOM.removeElementClass(fromPage, 'transition');
|
||||
MochiKit.DOM.removeElementClass(toPage, 'transition');
|
||||
})
|
||||
},
|
||||
|
||||
rotateInPage: function (fromPage, toPage) {
|
||||
// Broken! :(
|
||||
MochiKit.DOM.addElementClass(MochiKit.DOM.getElement('mainDiv'), 'show-right');
|
||||
},
|
||||
|
||||
//.........................................................................
|
||||
|
||||
goBack: function () {
|
||||
var fromPage;
|
||||
var toPage;
|
||||
|
||||
fromPage = this.pageStack().shift();
|
||||
toPage = this.currentPage();
|
||||
this.pages()[toPage].setProps({});
|
||||
this.moveOutPage(fromPage, toPage);
|
||||
},
|
||||
|
||||
historyGoBack: function (anEvent) {
|
||||
anEvent.preventDefault();
|
||||
anEvent.stopPropagation();
|
||||
this.goBack();
|
||||
},
|
||||
|
||||
currentPage: function () {
|
||||
return this.pageStack()[0];
|
||||
},
|
||||
|
||||
setCurrentPage: function (aPage) {
|
||||
this.pageStack().unshift(aPage);
|
||||
},
|
||||
|
||||
moveInPage: function (fromPage, toPage, addToHistory) {
|
||||
var shouldAddItemToHistory;
|
||||
|
||||
shouldAddItemToHistory = typeof(addToHistory) == 'undefined' ? false : addToHistory;
|
||||
|
||||
this.slidePage(MochiKit.DOM.getElement(fromPage), MochiKit.DOM.getElement(toPage), 'LEFT');
|
||||
this.setCurrentPage(toPage);
|
||||
|
||||
if (shouldAddItemToHistory) {
|
||||
//console.log("ADD ITEM TO HISTORY");
|
||||
//console.log("ADD ITEM TO HISTORY - window", window);
|
||||
//console.log("ADD ITEM TO HISTORY - window.history", window.history);
|
||||
window.history.pushState({'fromPage': fromPage, 'toPage': toPage});
|
||||
//# window.history.pushState();
|
||||
//console.log("ADDED ITEM TO HISTORY");
|
||||
} else {
|
||||
//console.log("Skip HISTORY");
|
||||
}
|
||||
},
|
||||
|
||||
moveOutPage: function (fromPage, toPage) {
|
||||
this.slidePage(MochiKit.DOM.getElement(fromPage), MochiKit.DOM.getElement(toPage), 'RIGHT');
|
||||
this.setCurrentPage(toPage);
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
/*
|
||||
wrongAppVersion: function (anError) {
|
||||
// this.pages()['errorPage'].setProps({message:anError.message});
|
||||
// this.moveInPage('errorPage', this.currentPage());
|
||||
},
|
||||
*/
|
||||
//=========================================================================
|
||||
__syntaxFix__: "syntax fix"
|
||||
});
|
||||
162
frontend/delta/js/Clipperz/Set.js
Normal file
162
frontend/delta/js/Clipperz/Set.js
Normal file
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
if (typeof(Clipperz) == 'undefined') {
|
||||
Clipperz = {};
|
||||
}
|
||||
|
||||
//#############################################################################
|
||||
|
||||
Clipperz.Set = function(args) {
|
||||
args = args || {};
|
||||
// MochiKit.Base.bindMethods(this);
|
||||
|
||||
if (args.items != null) {
|
||||
this._items = args.items.slice();
|
||||
} else {
|
||||
this._items = [];
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
||||
Clipperz.Set.prototype = MochiKit.Base.update(null, {
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'toString': function() {
|
||||
return "Clipperz.Set";
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'items': function() {
|
||||
return this._items;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'popAnItem': function() {
|
||||
var result;
|
||||
|
||||
if (this.size() > 0) {
|
||||
result = this.items().pop();
|
||||
} else {
|
||||
result = null;
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'allItems': function() {
|
||||
return this.items();
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'contains': function(anItem) {
|
||||
return (this.indexOf(anItem) != -1);
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'indexOf': function(anItem) {
|
||||
var result;
|
||||
var i, c;
|
||||
|
||||
result = -1;
|
||||
|
||||
c = this.items().length;
|
||||
for (i=0; (i<c) && (result == -1); i++) {
|
||||
if (this.items()[i] === anItem) {
|
||||
result = i;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'add': function(anItem) {
|
||||
if (anItem.constructor == Array) {
|
||||
MochiKit.Base.map(MochiKit.Base.bind(this,add, this), anItem);
|
||||
} else {
|
||||
if (! this.contains(anItem)) {
|
||||
this.items().push(anItem);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'debug': function() {
|
||||
var i, c;
|
||||
|
||||
result = -1;
|
||||
|
||||
c = this.items().length;
|
||||
for (i=0; i<c; i++) {
|
||||
alert("[" + i + "] " + this.items()[i].label);
|
||||
}
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'remove': function(anItem) {
|
||||
if (anItem.constructor == Array) {
|
||||
MochiKit.Base.map(MochiKit.Base.bind(this.remove, this), anItem);
|
||||
} else {
|
||||
var itemIndex;
|
||||
|
||||
itemIndex = this.indexOf(anItem);
|
||||
if (itemIndex != -1) {
|
||||
this.items().splice(itemIndex, 1);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'size': function() {
|
||||
return this.items().length;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'empty': function() {
|
||||
this.items().splice(0, this.items().length);
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
__syntaxFix__: "syntax fix"
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
});
|
||||
|
||||
66
frontend/delta/js/Clipperz/Signal.js
Normal file
66
frontend/delta/js/Clipperz/Signal.js
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
|
||||
if (typeof(Clipperz.Signal) == 'undefined') { Clipperz.Signal = {}; }
|
||||
|
||||
Clipperz.Signal.VERSION = "0.1";
|
||||
Clipperz.Signal.NAME = "Clipperz.Signal";
|
||||
|
||||
MochiKit.Base.update(Clipperz.Signal, {
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'__repr__': function () {
|
||||
return "[" + this.NAME + " " + this.VERSION + "]";
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'toString': function () {
|
||||
return this.__repr__();
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'fireNativeEvent': function(element, eventName) {
|
||||
if (element.fireEvent) {
|
||||
// MSIE
|
||||
element.fireEvent(eventName);
|
||||
} else {
|
||||
// W3C
|
||||
var event;
|
||||
|
||||
event = document.createEvent("HTMLEvents");
|
||||
event.initEvent(eventName.replace(/^on/, ""), true, true);
|
||||
element.dispatchEvent(event);
|
||||
}
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
__syntaxFix__: "syntax fix"
|
||||
|
||||
});
|
||||
|
||||
Clipperz.Signal.NotificationCenter = {};
|
||||
|
||||
89
frontend/delta/js/Clipperz/Style.js
Normal file
89
frontend/delta/js/Clipperz/Style.js
Normal file
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
|
||||
if (typeof(Clipperz.Style) == 'undefined') { Clipperz.Style = {}; }
|
||||
|
||||
Clipperz.Style.VERSION = "0.1";
|
||||
Clipperz.Style.NAME = "Clipperz.DOM";
|
||||
|
||||
MochiKit.Base.update(Clipperz.Style, {
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'__repr__': function () {
|
||||
return "[" + this.NAME + " " + this.VERSION + "]";
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'toString': function () {
|
||||
return this.__repr__();
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'applyZebraStylesToTable': function(aTable) {
|
||||
var tbody;
|
||||
var tbodyRows;
|
||||
var i,c;
|
||||
|
||||
tbody = MochiKit.DOM.getFirstElementByTagAndClassName('tbody', null, aTable);
|
||||
tbodyRows = tbody.childNodes;
|
||||
// tbodyRows = MochiKit.DOM.getElementsByTagAndClassName('tr', null, tbody)
|
||||
c = tbodyRows.length;
|
||||
for (i=0; i<c; i++) {
|
||||
var element;
|
||||
|
||||
element = YAHOO.Element.get(tbodyRows[i]);
|
||||
element.addClass(((i%2 == 0) ? "zebra_odd": "zebra_even"));
|
||||
element.removeClass(((i%2 == 1) ? "zebra_odd": "zebra_even"));
|
||||
}
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'getSizeAndPosition': function (anElement) {
|
||||
var result;
|
||||
|
||||
if (anElement != null) {
|
||||
result = { dimensions:MochiKit.Style.getElementDimensions(anElement), position:MochiKit.Style.getElementPosition(anElement)};
|
||||
} else {
|
||||
result = { dimensions:MochiKit.Style.getViewportDimensions(), position:MochiKit.Style.getViewportPosition()};
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
'setBackgroundGradient': function (anElement, someParameters) {
|
||||
// background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#ff9955), to(#ff6622), color-stop(1,#333333));
|
||||
// background: -moz-linear-gradient(0% 100% 90deg,#ff6622, #ff9955);
|
||||
MochiKit.Style.setStyle(anElement, {'background': '-webkit-gradient(linear, 0% 0%, 0% 100%, from(' + someParameters['from'] + '), to(' + someParameters['to'] + '), color-stop(1,#333333))'});
|
||||
MochiKit.Style.setStyle(anElement, {'background': '-moz-linear-gradient(0% 100% 90deg,' + someParameters['to'] + ', ' + someParameters['from'] + ')'});
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
__syntaxFix__: "syntax fix"
|
||||
|
||||
});
|
||||
|
||||
363
frontend/delta/js/Clipperz/Visual.js
Normal file
363
frontend/delta/js/Clipperz/Visual.js
Normal file
@@ -0,0 +1,363 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
|
||||
if (typeof(Clipperz.Visual) == 'undefined') { Clipperz.Visual = {}; }
|
||||
|
||||
Clipperz.Visual.VERSION = "0.1";
|
||||
Clipperz.Visual.NAME = "Clipperz.Visual";
|
||||
|
||||
MochiKit.Base.update(Clipperz.Visual, {
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'__repr__': function () {
|
||||
return "[" + this.NAME + " " + this.VERSION + "]";
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'toString': function () {
|
||||
return this.__repr__();
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'deferredResize': function (anElement, someOptions) {
|
||||
var deferredResult;
|
||||
var moveTransition;
|
||||
var scaleTransition;
|
||||
var duration;
|
||||
|
||||
duration = someOptions.duration || 0.5;
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("Visual.deferredResize", {trace:false});
|
||||
deferredResult.addCallback(MochiKit.Async.succeed, arguments[arguments.length - 1]);
|
||||
|
||||
moveTransition = MochiKit.Visual.Transitions.linear; //MochiKit.Visual.Transitions.sinoidal;
|
||||
scaleTransition = MochiKit.Visual.Transitions.linear; //MochiKit.Visual.Transitions.sinoidal;
|
||||
|
||||
MochiKit.Style.setElementPosition(anElement, {x:someOptions.from.position.x, y:someOptions.from.position.y }, 'px');
|
||||
|
||||
new MochiKit.Visual.Parallel([
|
||||
new MochiKit.Visual.Move(anElement, {x:someOptions.to.position.x, y:someOptions.to.position.y, mode:'absolute', transition:moveTransition, sync:true}),
|
||||
new Clipperz.Visual.Resize(anElement, {fromSize:{h:someOptions.from.dimensions.h, w:someOptions.from.dimensions.w}, toSize:{h:someOptions.to.dimensions.h, w:someOptions.to.dimensions.w}, transition:scaleTransition, scaleContent:false, scaleFromCenter:false, restoreAfterFinish:true, sync:true})
|
||||
], {duration:duration, afterFinish:MochiKit.Base.method(deferredResult, 'callback')})
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'deferredAnimation': function (anAnimation, someParameters, someOptions) {
|
||||
var deferredResult;
|
||||
var afterFinishCallback;
|
||||
var options;
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("Clipperz.Visual.deferredAnimation", {trace:false});
|
||||
deferredResult.addCallback(MochiKit.Async.succeed, arguments[arguments.length - 1]);
|
||||
|
||||
if (MochiKit.Base.isUndefinedOrNull(someOptions)) {
|
||||
options = {}
|
||||
} else {
|
||||
options = someOptions;
|
||||
}
|
||||
|
||||
if (MochiKit.Base.isUndefinedOrNull(someOptions['afterFinish'])) {
|
||||
options['afterFinish'] = MochiKit.Base.noop;
|
||||
}
|
||||
|
||||
MochiKit.Base.update(options, {
|
||||
'afterFinish': MochiKit.Base.compose(options['afterFinish'], MochiKit.Base.method(deferredResult, 'callback'))
|
||||
});
|
||||
|
||||
new anAnimation(someParameters, options);
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'deferredAnimations': function (aSinchronizationType, someAnimations, someOptions) {
|
||||
var deferredResult;
|
||||
var options;
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("Visual.deferredParallelAnimations", {trace:false});
|
||||
deferredResult.addCallback(MochiKit.Async.succeed, arguments[arguments.length - 1]);
|
||||
|
||||
options = someOptions;
|
||||
if (MochiKit.Base.isUndefinedOrNull(someOptions['afterFinish'])) {
|
||||
options['afterFinish'] = MochiKit.Base.noop;
|
||||
}
|
||||
MochiKit.Base.update(options, {
|
||||
'afterFinish': MochiKit.Base.compose(options['afterFinish'], MochiKit.Base.method(deferredResult, 'callback'))
|
||||
});
|
||||
|
||||
new aSinchronizationType(someAnimations, options)
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
__syntaxFix__: "syntax fix"
|
||||
|
||||
});
|
||||
|
||||
//#############################################################################
|
||||
|
||||
/** @id Clipperz.Visual.Resize */
|
||||
Clipperz.Visual.Resize = function (element, percent, options) {
|
||||
var cls = arguments.callee;
|
||||
if (!(this instanceof cls)) {
|
||||
return new cls(element, percent, options);
|
||||
}
|
||||
this.__init__(element, percent, options);
|
||||
};
|
||||
|
||||
Clipperz.Visual.Resize.prototype = new MochiKit.Visual.Base();
|
||||
|
||||
MochiKit.Base.update(Clipperz.Visual.Resize.prototype, {
|
||||
__class__ : Clipperz.Visual.Resize,
|
||||
|
||||
__init__: function (element, options) {
|
||||
this.element = MochiKit.DOM.getElement(element);
|
||||
options = MochiKit.Base.update({
|
||||
scaleX: true,
|
||||
scaleY: true,
|
||||
scaleContent: true,
|
||||
scaleFromCenter: false,
|
||||
scaleMode: 'box', // 'box' or 'contents' or {} with provided values
|
||||
syntax_fix: 'syntax fix'
|
||||
}, options);
|
||||
|
||||
this.start(options);
|
||||
},
|
||||
|
||||
setup: function () {
|
||||
this.restoreAfterFinish = this.options.restoreAfterFinish || false;
|
||||
this.elementPositioning = MochiKit.Style.getStyle(this.element, 'position');
|
||||
|
||||
var ma = MochiKit.Base.map;
|
||||
var b = MochiKit.Base.bind;
|
||||
this.originalStyle = {};
|
||||
ma(b(function (k) { this.originalStyle[k] = this.element.style[k]; }, this), ['top', 'left', 'width', 'height', 'fontSize']);
|
||||
|
||||
this.originalTop = this.element.offsetTop;
|
||||
this.originalLeft = this.element.offsetLeft;
|
||||
|
||||
var fontSize = MochiKit.Style.getStyle(this.element, 'font-size') || '100%';
|
||||
ma(b(function (fontSizeType) {
|
||||
if (fontSize.indexOf(fontSizeType) > 0) {
|
||||
this.fontSize = parseFloat(fontSize);
|
||||
this.fontSizeType = fontSizeType;
|
||||
}
|
||||
}, this), ['em', 'px', '%']);
|
||||
|
||||
this.factor = 1;
|
||||
|
||||
this.dims = [this.options.fromSize.h, this.options.fromSize.w];
|
||||
},
|
||||
|
||||
update: function (position) {
|
||||
this.setDimensions( (this.options.toSize.h - this.options.fromSize.h) * position + this.options.fromSize.h,
|
||||
(this.options.toSize.w - this.options.fromSize.w) * position + this.options.fromSize.w);
|
||||
},
|
||||
|
||||
finish: function () {
|
||||
if (this.restoreAfterFinish) {
|
||||
MochiKit.Style.setStyle(this.element, this.originalStyle);
|
||||
}
|
||||
},
|
||||
|
||||
setDimensions: function (height, width) {
|
||||
var d = {};
|
||||
var r = Math.round;
|
||||
if (/MSIE/.test(navigator.userAgent)) {
|
||||
r = Math.ceil;
|
||||
}
|
||||
if (this.options.scaleX) {
|
||||
d.width = r(width) + 'px';
|
||||
}
|
||||
if (this.options.scaleY) {
|
||||
d.height = r(height) + 'px';
|
||||
}
|
||||
if (this.options.scaleFromCenter) {
|
||||
var topd = (height - this.dims[0])/2;
|
||||
var leftd = (width - this.dims[1])/2;
|
||||
if (this.elementPositioning == 'absolute') {
|
||||
if (this.options.scaleY) {
|
||||
d.top = this.originalTop - topd + 'px';
|
||||
}
|
||||
if (this.options.scaleX) {
|
||||
d.left = this.originalLeft - leftd + 'px';
|
||||
}
|
||||
} else {
|
||||
if (this.options.scaleY) {
|
||||
d.top = -topd + 'px';
|
||||
}
|
||||
if (this.options.scaleX) {
|
||||
d.left = -leftd + 'px';
|
||||
}
|
||||
}
|
||||
}
|
||||
MochiKit.Style.setStyle(this.element, d);
|
||||
}
|
||||
});
|
||||
|
||||
//=============================================================================
|
||||
|
||||
Clipperz.Visual.squize = function (element, /* optional */ options) {
|
||||
var d = MochiKit.DOM;
|
||||
var v = MochiKit.Visual;
|
||||
var s = MochiKit.Style;
|
||||
|
||||
element = d.getElement(element);
|
||||
options = MochiKit.Base.update({
|
||||
moveTransition: v.Transitions.sinoidal,
|
||||
scaleTransition: v.Transitions.sinoidal,
|
||||
opacityTransition: v.Transitions.none,
|
||||
scaleContent: true,
|
||||
scaleFromCenter: false,
|
||||
scaleX: true,
|
||||
scaleY: true
|
||||
}, options);
|
||||
var oldStyle = {
|
||||
top: element.style.top,
|
||||
left: element.style.left,
|
||||
height: element.style.height,
|
||||
width: element.style.width,
|
||||
opacity: s.getStyle(element, 'opacity')
|
||||
};
|
||||
|
||||
var dims = s.getElementDimensions(element, true);
|
||||
var moveX, moveY;
|
||||
|
||||
moveX = options.scaleX ? dims.w/2 : 0;
|
||||
moveY = options.scaleY ? dims.h/2 : 0;
|
||||
|
||||
var elemClip;
|
||||
|
||||
var optionsParallel = MochiKit.Base.update({
|
||||
beforeStartInternal: function (effect) {
|
||||
s.makePositioned(effect.effects[0].element);
|
||||
elemClip = s.makeClipping(effect.effects[0].element);
|
||||
},
|
||||
afterFinishInternal: function (effect) {
|
||||
s.hideElement(effect.effects[0].element);
|
||||
s.undoClipping(effect.effects[0].element, elemClip);
|
||||
s.undoPositioned(effect.effects[0].element);
|
||||
s.setStyle(effect.effects[0].element, oldStyle);
|
||||
}
|
||||
}, options);
|
||||
|
||||
return new v.Parallel(
|
||||
[new v.Opacity(element, {
|
||||
sync: true, to: 0.0, from: 1.0,
|
||||
transition: options.opacityTransition
|
||||
}),
|
||||
new v.Scale(element, /Opera/.test(navigator.userAgent) ? 1 : 0, {
|
||||
scaleMode: {originalHeight: dims.h, originalWidth: dims.w},
|
||||
sync: true, transition: options.scaleTransition,
|
||||
scaleContent: options.scaleContent,
|
||||
scaleFromCenter: options.scaleFromCenter,
|
||||
restoreAfterFinish: true,
|
||||
scaleX: options.scaleX,
|
||||
scaleY: options.scaleY
|
||||
}),
|
||||
new v.Move(element, {
|
||||
x: moveX, y: moveY, sync: true, transition: options.moveTransition
|
||||
})
|
||||
], optionsParallel
|
||||
);
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
Clipperz.Visual.expand = function (element, /* optional */ options) {
|
||||
var d = MochiKit.DOM;
|
||||
var v = MochiKit.Visual;
|
||||
var s = MochiKit.Style;
|
||||
|
||||
element = d.getElement(element);
|
||||
options = MochiKit.Base.update({
|
||||
// direction: 'center',
|
||||
moveTransition: v.Transitions.sinoidal,
|
||||
scaleTransition: v.Transitions.sinoidal,
|
||||
opacityTransition: v.Transitions.none,
|
||||
scaleContent: true,
|
||||
scaleFromCenter: false,
|
||||
scaleX: true,
|
||||
scaleY: true
|
||||
}, options);
|
||||
var oldStyle = {
|
||||
top: element.style.top,
|
||||
left: element.style.left,
|
||||
height: element.style.height,
|
||||
width: element.style.width,
|
||||
opacity: s.getStyle(element, 'opacity')
|
||||
};
|
||||
|
||||
var dims = s.getElementDimensions(element, true);
|
||||
var moveX, moveY;
|
||||
|
||||
moveX = options.scaleX ? dims.w/2 : 0;
|
||||
moveY = options.scaleY ? dims.h/2 : 0;
|
||||
|
||||
var elemClip;
|
||||
|
||||
var optionsParallel = MochiKit.Base.update({
|
||||
beforeStartInternal: function (effect) {
|
||||
s.makePositioned(effect.effects[0].element);
|
||||
elemClip = s.makeClipping(effect.effects[0].element);
|
||||
},
|
||||
afterFinishInternal: function (effect) {
|
||||
s.hideElement(effect.effects[0].element);
|
||||
s.undoClipping(effect.effects[0].element, elemClip);
|
||||
s.undoPositioned(effect.effects[0].element);
|
||||
s.setStyle(effect.effects[0].element, oldStyle);
|
||||
}
|
||||
}, options);
|
||||
|
||||
return new v.Parallel(
|
||||
[new v.Opacity(element, {
|
||||
sync: true, to: 0.0, from: 1.0,
|
||||
transition: options.opacityTransition
|
||||
}),
|
||||
new v.Scale(element, /Opera/.test(navigator.userAgent) ? 1 : 0, {
|
||||
scaleMode: {originalHeight: dims.h, originalWidth: dims.w},
|
||||
sync: true, transition: options.scaleTransition,
|
||||
scaleContent: options.scaleContent,
|
||||
scaleFromCenter: options.scaleFromCenter,
|
||||
restoreAfterFinish: true,
|
||||
scaleX: options.scaleX,
|
||||
scaleY: options.scaleY
|
||||
}),
|
||||
new v.Move(element, {
|
||||
x: moveX, y: moveY, sync: true, transition: options.moveTransition
|
||||
})
|
||||
], optionsParallel
|
||||
);
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
|
||||
471
frontend/delta/js/Clipperz/YUI/DomHelper.js
Normal file
471
frontend/delta/js/Clipperz/YUI/DomHelper.js
Normal file
@@ -0,0 +1,471 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
|
||||
if (typeof(Clipperz.YUI) == 'undefined') { Clipperz.YUI = {}; }
|
||||
|
||||
|
||||
/**
|
||||
* @class Clipperz.ext.DomHelper
|
||||
* Utility class for working with DOM and/or Templates. It transparently supports using HTML fragments or DOM.
|
||||
* For more information see <a href="http://www.jackslocum.com/yui/2006/10/06/domhelper-create-elements-using-dom-html-fragments-or-templates/">this blog post with examples</a>.
|
||||
* @singleton
|
||||
*/
|
||||
Clipperz.YUI.DomHelper = new function(){
|
||||
/**@private*/
|
||||
var d = document;
|
||||
var tempTableEl = null;
|
||||
/** True to force the use of DOM instead of html fragments @type Boolean */
|
||||
this.useDom = false;
|
||||
var emptyTags = /^(?:base|basefont|br|frame|hr|img|input|isindex|link|meta|nextid|range|spacer|wbr|audioscope|area|param|keygen|col|limittext|spot|tab|over|right|left|choose|atop|of)$/i;
|
||||
/**
|
||||
* Applies a style specification to an element
|
||||
* @param {String/HTMLElement} el The element to apply styles to
|
||||
* @param {String/Object/Function} styles A style specification string eg "width:100px", or object in the form {width:"100px"}, or
|
||||
* a function which returns such a specification.
|
||||
*/
|
||||
this.applyStyles = function(el, styles){
|
||||
if(styles){
|
||||
var D = YAHOO.util.Dom;
|
||||
if (typeof styles == "string"){
|
||||
var re = /\s?([a-z\-]*)\:([^;]*);?/gi;
|
||||
var matches;
|
||||
while ((matches = re.exec(styles)) != null){
|
||||
D.setStyle(el, matches[1], matches[2]);
|
||||
}
|
||||
}else if (typeof styles == "object"){
|
||||
for (var style in styles){
|
||||
D.setStyle(el, style, styles[style]);
|
||||
}
|
||||
}else if (typeof styles == "function"){
|
||||
Clipperz.YUI.DomHelper.applyStyles(el, styles.call());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// build as innerHTML where available
|
||||
/** @ignore */
|
||||
var createHtml = function(o){
|
||||
var b = '';
|
||||
|
||||
if(typeof(o['html']) != 'undefined') {
|
||||
o['html'] = Clipperz.Base.sanitizeString(o['html']);
|
||||
} else if (typeof(o['htmlString']) != 'undefined') {
|
||||
o['html'] = o['htmlString'];
|
||||
delete o.htmlString;
|
||||
}
|
||||
|
||||
if (MochiKit.Base.isArrayLike(o)) {
|
||||
for (var i = 0, l = o.length; i < l; i++) {
|
||||
b += createHtml(o[i]);
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
b += '<' + o.tag;
|
||||
for(var attr in o){
|
||||
if(attr == 'tag' || attr == 'children' || attr == 'html' || typeof o[attr] == 'function') continue;
|
||||
if(attr == 'style'){
|
||||
var s = o['style'];
|
||||
if(typeof s == 'function'){
|
||||
s = s.call();
|
||||
}
|
||||
if(typeof s == 'string'){
|
||||
b += ' style="' + s + '"';
|
||||
}else if(typeof s == 'object'){
|
||||
b += ' style="';
|
||||
for(var key in s){
|
||||
if(typeof s[key] != 'function'){
|
||||
b += key + ':' + s[key] + ';';
|
||||
}
|
||||
}
|
||||
b += '"';
|
||||
}
|
||||
}else{
|
||||
if(attr == 'cls'){
|
||||
b += ' class="' + o['cls'] + '"';
|
||||
}else if(attr == 'htmlFor'){
|
||||
b += ' for="' + o['htmlFor'] + '"';
|
||||
}else{
|
||||
b += ' ' + attr + '="' + o[attr] + '"';
|
||||
}
|
||||
}
|
||||
}
|
||||
if(emptyTags.test(o.tag)){
|
||||
b += ' />';
|
||||
}else{
|
||||
b += '>';
|
||||
if(o.children){
|
||||
for(var i = 0, len = o.children.length; i < len; i++) {
|
||||
b += createHtml(o.children[i], b);
|
||||
}
|
||||
}
|
||||
if(o.html){
|
||||
b += o.html;
|
||||
}
|
||||
b += '</' + o.tag + '>';
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
// build as dom
|
||||
/** @ignore */
|
||||
var createDom = function(o, parentNode){
|
||||
var el = d.createElement(o.tag);
|
||||
var useSet = el.setAttribute ? true : false; // In IE some elements don't have setAttribute
|
||||
for(var attr in o){
|
||||
if(attr == 'tag' || attr == 'children' || attr == 'html' || attr == 'style' || typeof o[attr] == 'function') continue;
|
||||
if(attr=='cls'){
|
||||
el.className = o['cls'];
|
||||
}else{
|
||||
if(useSet) el.setAttribute(attr, o[attr]);
|
||||
else el[attr] = o[attr];
|
||||
}
|
||||
}
|
||||
Clipperz.YUI.DomHelper.applyStyles(el, o.style);
|
||||
if(o.children){
|
||||
for(var i = 0, len = o.children.length; i < len; i++) {
|
||||
createDom(o.children[i], el);
|
||||
}
|
||||
}
|
||||
if(o.html){
|
||||
el.innerHTML = o.html;
|
||||
}
|
||||
if(parentNode){
|
||||
parentNode.appendChild(el);
|
||||
}
|
||||
return el;
|
||||
};
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
* Nasty code for IE's broken table implementation
|
||||
*/
|
||||
var insertIntoTable = function(tag, where, el, html){
|
||||
if(!tempTableEl){
|
||||
tempTableEl = document.createElement('div');
|
||||
}
|
||||
var nodes;
|
||||
if(tag == 'table' || tag == 'tbody'){
|
||||
tempTableEl.innerHTML = '<table><tbody>'+html+'</tbody></table>';
|
||||
nodes = tempTableEl.firstChild.firstChild.childNodes;
|
||||
}else{
|
||||
tempTableEl.innerHTML = '<table><tbody><tr>'+html+'</tr></tbody></table>';
|
||||
nodes = tempTableEl.firstChild.firstChild.firstChild.childNodes;
|
||||
}
|
||||
if (where == 'beforebegin') {
|
||||
nodes.reverse();
|
||||
// el.parentNode.insertBefore(node, el);
|
||||
MochiKit.Base.map(function(aNode) {el.parentNode.insertBefore(aNode, el)}, nodes);
|
||||
} else if (where == 'afterbegin') {
|
||||
nodes.reverse();
|
||||
// el.insertBefore(node, el.firstChild);
|
||||
MochiKit.Base.map(function(aNode) {el.insertBefore(aNode, el.firstChild)}, nodes);
|
||||
} else if (where == 'beforeend') {
|
||||
// el.appendChild(node);
|
||||
MochiKit.Base.map(function(aNode) {el.appendChild(aNode)}, nodes);
|
||||
} else if (where == 'afterend') {
|
||||
// el.parentNode.insertBefore(node, el.nextSibling);
|
||||
MochiKit.Base.map(function(aNode) {el.parentNode.insertBefore(aNode, el.nextSibling)}, nodes);
|
||||
}
|
||||
|
||||
return nodes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts an HTML fragment into the Dom
|
||||
* @param {String} where Where to insert the html in relation to el - beforeBegin, afterBegin, beforeEnd, afterEnd.
|
||||
* @param {HTMLElement} el The context element
|
||||
* @param {String} html The HTML fragmenet
|
||||
* @return {HTMLElement} The new node
|
||||
*/
|
||||
this.insertHtml = function(where, el, html){
|
||||
where = where.toLowerCase();
|
||||
// if(el.insertAdjacentHTML){
|
||||
if(Clipperz_IEisBroken){
|
||||
var tag = el.tagName.toLowerCase();
|
||||
if(tag == 'table' || tag == 'tbody' || tag == 'tr'){
|
||||
return insertIntoTable(tag, where, el, html);
|
||||
}
|
||||
switch(where){
|
||||
case 'beforebegin':
|
||||
el.insertAdjacentHTML(where, html);
|
||||
return el.previousSibling;
|
||||
case 'afterbegin':
|
||||
el.insertAdjacentHTML(where, html);
|
||||
return el.firstChild;
|
||||
case 'beforeend':
|
||||
el.insertAdjacentHTML(where, html);
|
||||
return el.lastChild;
|
||||
case 'afterend':
|
||||
el.insertAdjacentHTML(where, html);
|
||||
return el.nextSibling;
|
||||
}
|
||||
throw 'Illegal insertion point -> "' + where + '"';
|
||||
}
|
||||
var range = el.ownerDocument.createRange();
|
||||
var frag;
|
||||
switch(where){
|
||||
case 'beforebegin':
|
||||
range.setStartBefore(el);
|
||||
frag = range.createContextualFragment(html);
|
||||
el.parentNode.insertBefore(frag, el);
|
||||
return el.previousSibling;
|
||||
case 'afterbegin':
|
||||
if(el.firstChild){ // faster
|
||||
range.setStartBefore(el.firstChild);
|
||||
}else{
|
||||
range.selectNodeContents(el);
|
||||
range.collapse(true);
|
||||
}
|
||||
frag = range.createContextualFragment(html);
|
||||
el.insertBefore(frag, el.firstChild);
|
||||
return el.firstChild;
|
||||
case 'beforeend':
|
||||
if(el.lastChild){
|
||||
range.setStartAfter(el.lastChild); // faster
|
||||
}else{
|
||||
range.selectNodeContents(el);
|
||||
range.collapse(false);
|
||||
}
|
||||
frag = range.createContextualFragment(html);
|
||||
el.appendChild(frag);
|
||||
return el.lastChild;
|
||||
case 'afterend':
|
||||
range.setStartAfter(el);
|
||||
frag = range.createContextualFragment(html);
|
||||
el.parentNode.insertBefore(frag, el.nextSibling);
|
||||
return el.nextSibling;
|
||||
}
|
||||
throw 'Illegal insertion point -> "' + where + '"';
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates new Dom element(s) and inserts them before el
|
||||
* @param {String/HTMLElement/Element} el The context element
|
||||
* @param {Object} o The Dom object spec (and children)
|
||||
* @param {<i>Boolean</i>} returnElement (optional) true to return a YAHOO.Element
|
||||
* @return {HTMLElement} The new node
|
||||
*/
|
||||
this.insertBefore = function(el, o, returnElement){
|
||||
el = el.dom ? el.dom : YAHOO.util.Dom.get(el);
|
||||
var newNode;
|
||||
if(this.useDom){
|
||||
newNode = createDom(o, null);
|
||||
el.parentNode.insertBefore(newNode, el);
|
||||
}else{
|
||||
var html = createHtml(o);
|
||||
newNode = this.insertHtml('beforeBegin', el, html);
|
||||
}
|
||||
return returnElement ? YAHOO.Element.get(newNode, true) : newNode;
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates new Dom element(s) and inserts them after el
|
||||
* @param {String/HTMLElement/Element} el The context element
|
||||
* @param {Object} o The Dom object spec (and children)
|
||||
* @param {<i>Boolean</i>} returnElement (optional) true to return a YAHOO.Element
|
||||
* @return {HTMLElement} The new node
|
||||
*/
|
||||
this.insertAfter = function(el, o, returnElement){
|
||||
el = el.dom ? el.dom : YAHOO.util.Dom.get(el);
|
||||
var newNode;
|
||||
if(this.useDom){
|
||||
newNode = createDom(o, null);
|
||||
el.parentNode.insertBefore(newNode, el.nextSibling);
|
||||
}else{
|
||||
var html = createHtml(o);
|
||||
newNode = this.insertHtml('afterEnd', el, html);
|
||||
}
|
||||
return returnElement ? YAHOO.Element.get(newNode, true) : newNode;
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates new Dom element(s) and appends them to el
|
||||
* @param {String/HTMLElement/Element} el The context element
|
||||
* @param {Object} o The Dom object spec (and children)
|
||||
* @param {<i>Boolean</i>} returnElement (optional) true to return a YAHOO.Element
|
||||
* @return {HTMLElement} The new node
|
||||
*/
|
||||
this.append = function(el, o, returnElement){
|
||||
el = el.dom ? el.dom : YAHOO.util.Dom.get(el);
|
||||
var newNode;
|
||||
if(this.useDom){
|
||||
newNode = createDom(o, null);
|
||||
el.appendChild(newNode);
|
||||
}else{
|
||||
var html = createHtml(o);
|
||||
newNode = this.insertHtml('beforeEnd', el, html);
|
||||
}
|
||||
return returnElement ? YAHOO.Element.get(newNode, true) : newNode;
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates new Dom element(s) and overwrites the contents of el with them
|
||||
* @param {String/HTMLElement/Element} el The context element
|
||||
* @param {Object} o The Dom object spec (and children)
|
||||
* @param {<i>Boolean</i>} returnElement (optional) true to return a YAHOO.Element
|
||||
* @return {HTMLElement} The new node
|
||||
*/
|
||||
this.overwrite = function(el, o, returnElement){
|
||||
el = el.dom ? el.dom : YAHOO.util.Dom.get(el);
|
||||
el.innerHTML = createHtml(o);
|
||||
return returnElement ? YAHOO.Element.get(el.firstChild, true) : el.firstChild;
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new Clipperz.YUI.DomHelper.Template from the Dom object spec
|
||||
* @param {Object} o The Dom object spec (and children)
|
||||
* @return {Clipperz.YUI.DomHelper.Template} The new template
|
||||
*/
|
||||
this.createTemplate = function(o){
|
||||
var html = createHtml(o);
|
||||
return new Clipperz.YUI.DomHelper.Template(html);
|
||||
};
|
||||
}();
|
||||
|
||||
/**
|
||||
* @class Clipperz.YUI.DomHelper.Template
|
||||
* Represents an HTML fragment template.
|
||||
* For more information see <a href="http://www.jackslocum.com/yui/2006/10/06/domhelper-create-elements-using-dom-html-fragments-or-templates/">this blog post with examples</a>.
|
||||
* <br>
|
||||
* <b>This class is also available as Clipperz.YUI.Template</b>.
|
||||
* @constructor
|
||||
* @param {String/Array} html The HTML fragment or an array of fragments to join('') or multiple arguments to join('')
|
||||
*/
|
||||
Clipperz.YUI.DomHelper.Template = function(html){
|
||||
if(html instanceof Array){
|
||||
html = html.join('');
|
||||
}else if(arguments.length > 1){
|
||||
html = Array.prototype.join.call(arguments, '');
|
||||
}
|
||||
/**@private*/
|
||||
this.html = html;
|
||||
};
|
||||
Clipperz.YUI.DomHelper.Template.prototype = {
|
||||
/**
|
||||
* Returns an HTML fragment of this template with the specified values applied
|
||||
* @param {Object} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'})
|
||||
* @return {String}
|
||||
*/
|
||||
applyTemplate : function(values){
|
||||
if(this.compiled){
|
||||
return this.compiled(values);
|
||||
}
|
||||
var empty = '';
|
||||
var fn = function(match, index){
|
||||
if(typeof values[index] != 'undefined'){
|
||||
return values[index];
|
||||
}else{
|
||||
return empty;
|
||||
}
|
||||
}
|
||||
return this.html.replace(this.re, fn);
|
||||
},
|
||||
|
||||
/**
|
||||
* The regular expression used to match template variables
|
||||
* @type RegExp
|
||||
* @property
|
||||
*/
|
||||
re : /\{([\w|-]+)\}/g,
|
||||
|
||||
/**
|
||||
* Compiles the template into an internal function, eliminating the RegEx overhead
|
||||
*/
|
||||
compile : function(){
|
||||
var body = ["this.compiled = function(values){ return ['"];
|
||||
body.push(this.html.replace(this.re, "', values['$1'], '"));
|
||||
body.push("'].join('');};");
|
||||
eval(body.join(''));
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Applies the supplied values to the template and inserts the new node(s) before el
|
||||
* @param {String/HTMLElement/Element} el The context element
|
||||
* @param {Object} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'})
|
||||
* @param {<i>Boolean</i>} returnElement (optional) true to return a YAHOO.Element
|
||||
* @return {HTMLElement} The new node
|
||||
*/
|
||||
insertBefore: function(el, values, returnElement){
|
||||
el = el.dom ? el.dom : YAHOO.util.Dom.get(el);
|
||||
var newNode = Clipperz.YUI.DomHelper.insertHtml('beforeBegin', el, this.applyTemplate(values));
|
||||
return returnElement ? YAHOO.Element.get(newNode, true) : newNode;
|
||||
},
|
||||
|
||||
/**
|
||||
* Applies the supplied values to the template and inserts the new node(s) after el
|
||||
* @param {String/HTMLElement/Element} el The context element
|
||||
* @param {Object} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'})
|
||||
* @param {<i>Boolean</i>} returnElement (optional) true to return a YAHOO.Element
|
||||
* @return {HTMLElement} The new node
|
||||
*/
|
||||
insertAfter : function(el, values, returnElement){
|
||||
el = el.dom ? el.dom : YAHOO.util.Dom.get(el);
|
||||
var newNode = Clipperz.YUI.DomHelper.insertHtml('afterEnd', el, this.applyTemplate(values));
|
||||
return returnElement ? YAHOO.Element.get(newNode, true) : newNode;
|
||||
},
|
||||
|
||||
/**
|
||||
* Applies the supplied values to the template and append the new node(s) to el
|
||||
* @param {String/HTMLElement/Element} el The context element
|
||||
* @param {Object} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'})
|
||||
* @param {<i>Boolean</i>} returnElement (optional) true to return a YAHOO.Element
|
||||
* @return {HTMLElement} The new node
|
||||
*/
|
||||
append : function(el, values, returnElement){
|
||||
var sanitizedValues;
|
||||
var key;
|
||||
|
||||
sanitizedValues = {};
|
||||
for (key in values) {
|
||||
sanitizedValues[key] = Clipperz.Base.sanitizeString(values[key]);
|
||||
}
|
||||
el = (typeof el == 'string') ? YAHOO.util.Dom.get(el) : el;
|
||||
var newNode = Clipperz.YUI.DomHelper.insertHtml('beforeEnd', el, this.applyTemplate(sanitizedValues));
|
||||
|
||||
return newNode;
|
||||
},
|
||||
|
||||
/**
|
||||
* Applies the supplied values to the template and overwrites the content of el with the new node(s)
|
||||
* @param {String/HTMLElement/Element} el The context element
|
||||
* @param {Object} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'})
|
||||
* @param {<i>Boolean</i>} returnElement (optional) true to return a YAHOO.Element
|
||||
* @return {HTMLElement} The new node
|
||||
*/
|
||||
overwrite : function(el, values, returnElement){
|
||||
el = el.dom ? el.dom : YAHOO.util.Dom.get(el);
|
||||
el.innerHTML = '';
|
||||
var newNode = Clipperz.YUI.DomHelper.insertHtml('beforeEnd', el, this.applyTemplate(values));
|
||||
return returnElement ? YAHOO.Element.get(newNode, true) : newNode;
|
||||
}
|
||||
};
|
||||
/**
|
||||
* Alias for applyTemplate
|
||||
* @method
|
||||
*/
|
||||
Clipperz.YUI.DomHelper.Template.prototype.apply = Clipperz.YUI.DomHelper.Template.prototype.applyTemplate;
|
||||
|
||||
Clipperz.YUI.Template = Clipperz.YUI.DomHelper.Template;
|
||||
709
frontend/delta/js/Clipperz/YUI/DomQuery.js
Normal file
709
frontend/delta/js/Clipperz/YUI/DomQuery.js
Normal file
@@ -0,0 +1,709 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
|
||||
if (typeof(Clipperz.YUI) == 'undefined') { Clipperz.YUI = {}; }
|
||||
|
||||
|
||||
/*
|
||||
* yui-ext 0.40
|
||||
* Copyright(c) 2006, Jack Slocum.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @class Clipperz.YUI.DomQuery
|
||||
* Provides high performance selector/xpath processing by compiling queries into reusable functions.
|
||||
* New pseudo classes and matchers can be plugged. It works on HTML and XML documents (if a content node is passed in).
|
||||
* @singleton
|
||||
*/
|
||||
Clipperz.YUI.DomQuery = function(){
|
||||
var cache = {}, simpleCache = {}, valueCache = {};
|
||||
var nonSpace = /\S/;
|
||||
var trimRe = /^\s*(.*?)\s*$/;
|
||||
var tplRe = /\{(\d+)\}/g;
|
||||
var modeRe = /^(\s?[\/>]\s?|\s|$)/;
|
||||
var clsRes = {};
|
||||
|
||||
function child(p, index){
|
||||
var i = 0;
|
||||
var n = p.firstChild;
|
||||
while(n){
|
||||
if(n.nodeType == 1){
|
||||
i++;
|
||||
if(i == index){
|
||||
return n;
|
||||
}
|
||||
}
|
||||
n = n.nextSibling;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
function next(d){
|
||||
var n = d.nextSibling;
|
||||
while(n && n.nodeType != 1){
|
||||
n = n.nextSibling;
|
||||
}
|
||||
return n;
|
||||
};
|
||||
|
||||
function prev(d){
|
||||
var n = d.previousSibling;
|
||||
while(n && n.nodeType != 1){
|
||||
n = n.previousSibling;
|
||||
}
|
||||
return n;
|
||||
};
|
||||
|
||||
function clean(d){
|
||||
var n = d.firstChild, ni = -1;
|
||||
while(n){
|
||||
var nx = n.nextSibling;
|
||||
if(n.nodeType == 3 && !nonSpace.test(n.nodeValue)){
|
||||
d.removeChild(n);
|
||||
}else{
|
||||
n.nodeIndex = ++ni;
|
||||
}
|
||||
n = nx;
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
function byClassName(c, a, v){
|
||||
if(!v){
|
||||
return c;
|
||||
}
|
||||
var re = clsRes[v];
|
||||
if(!re){
|
||||
re = new RegExp('(?:^|\\s)(?:' + v + ')(?:\\s|$)');
|
||||
clsRes[v] = re;
|
||||
}
|
||||
var r = [];
|
||||
for(var i = 0, ci; ci = c[i]; i++){
|
||||
if(re.test(ci.className)){
|
||||
r[r.length] = ci;
|
||||
}
|
||||
}
|
||||
return r;
|
||||
};
|
||||
|
||||
function convert(c){
|
||||
if(c.slice){
|
||||
return c;
|
||||
}
|
||||
var r = [];
|
||||
for(var i = 0, l = c.length; i < l; i++){
|
||||
r[r.length] = c[i];
|
||||
}
|
||||
return r;
|
||||
};
|
||||
|
||||
function attrValue(n, attr){
|
||||
if(!n.tagName && typeof n.length != 'undefined'){
|
||||
n = n[0];
|
||||
}
|
||||
if(!n){
|
||||
return null;
|
||||
}
|
||||
if(attr == 'for'){
|
||||
return n.htmlFor;
|
||||
}
|
||||
if(attr == 'class' || attr == 'className'){
|
||||
return n.className;
|
||||
}
|
||||
return n.getAttribute(attr) || n[attr];
|
||||
|
||||
};
|
||||
|
||||
function getNodes(ns, mode, tagName){
|
||||
var result = [], cs;
|
||||
if(!ns){
|
||||
return result;
|
||||
}
|
||||
mode = mode ? mode.replace(trimRe, '$1') : '';
|
||||
tagName = tagName || '*';
|
||||
if(ns.tagName || ns == document){
|
||||
ns = [ns];
|
||||
}
|
||||
if(mode != '/' && mode != '>'){
|
||||
for(var i = 0, ni; ni = ns[i]; i++){
|
||||
cs = ni.getElementsByTagName(tagName);
|
||||
result = concat(result, cs);
|
||||
}
|
||||
}else{
|
||||
for(var i = 0, ni; ni = ns[i]; i++){
|
||||
var cn = ni.getElementsByTagName(tagName);
|
||||
for(var j = 0, cj; cj = cn[j]; j++){
|
||||
if(cj.parentNode == ni){
|
||||
result[result.length] = cj;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
function concat(a, b){
|
||||
if(b.slice){
|
||||
return a.concat(b);
|
||||
}
|
||||
for(var i = 0, l = b.length; i < l; i++){
|
||||
a[a.length] = b[i];
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
function byTag(cs, tagName){
|
||||
if(cs.tagName || cs == document){
|
||||
cs = [cs];
|
||||
}
|
||||
if(!tagName){
|
||||
return cs;
|
||||
}
|
||||
var r = []; tagName = tagName.toLowerCase();
|
||||
for(var i = 0, ci; ci = cs[i]; i++){
|
||||
if(ci.nodeType == 1 && ci.tagName.toLowerCase()==tagName){
|
||||
r[r.length] = ci;
|
||||
}
|
||||
}
|
||||
return r;
|
||||
};
|
||||
|
||||
function byId(cs, attr, id){
|
||||
if(cs.tagName || cs == document){
|
||||
cs = [cs];
|
||||
}
|
||||
if(!id){
|
||||
return cs;
|
||||
}
|
||||
var r = [];
|
||||
for(var i = 0, l = cs.length; i < l; i++){
|
||||
var ci = cs[i];
|
||||
if(ci && ci.id == id){
|
||||
r[r.length] = ci;
|
||||
}
|
||||
}
|
||||
return r;
|
||||
};
|
||||
|
||||
function byAttribute(cs, attr, value, op, custom){
|
||||
var r = [], st = custom=='{';
|
||||
var f = Clipperz.YUI.DomQuery.operators[op];
|
||||
for(var i = 0, l = cs.length; i < l; i++){
|
||||
var a;
|
||||
if(st){
|
||||
a = Clipperz.YUI.DomQuery.getStyle(cs[i], attr);
|
||||
}
|
||||
else if(attr == 'class' || attr == 'className'){
|
||||
a = cs[i].className;
|
||||
}else if(attr == 'for'){
|
||||
a = cs[i].htmlFor;
|
||||
}else{
|
||||
a = cs[i].getAttribute(attr);
|
||||
}
|
||||
if((f && f(a, value)) || (!f && a)){
|
||||
r[r.length] = cs[i];
|
||||
}
|
||||
}
|
||||
return r;
|
||||
};
|
||||
|
||||
function byPseudo(cs, name, value){
|
||||
return Clipperz.YUI.DomQuery.pseudos[name](cs, value);
|
||||
};
|
||||
|
||||
// This is for IE MSXML which does not support expandos.
|
||||
// IE runs the same speed using setAttribute, however FF slows way down
|
||||
// and Safari completely fails so they need to continue to use expandos.
|
||||
// Branched at load time for faster execution.
|
||||
var isIE = window.ActiveXObject;
|
||||
var addAttr = isIE ?
|
||||
function(n, a, v){
|
||||
n.setAttribute(a, v);
|
||||
} :
|
||||
function(n, a, v){
|
||||
n[a] = v;
|
||||
};
|
||||
var getAttr = isIE ?
|
||||
function(n, a){
|
||||
return n.getAttribute(a);
|
||||
} :
|
||||
function(n, a){
|
||||
return n[a];
|
||||
};
|
||||
var clearAttr = isIE ?
|
||||
function(n, a){
|
||||
n.removeAttribute(a);
|
||||
} :
|
||||
function(n, a, v){
|
||||
delete n[a];
|
||||
};
|
||||
|
||||
function nodup(cs){
|
||||
if(!cs.length){
|
||||
return cs;
|
||||
}
|
||||
addAttr(cs[0], '_nodup', true);
|
||||
var r = [cs[0]];
|
||||
for(var i = 1, len = cs.length; i < len; i++){
|
||||
var c = cs[i];
|
||||
if(!getAttr(c, '_nodup')){
|
||||
addAttr(c, '_nodup', true);
|
||||
r[r.length] = c;
|
||||
}
|
||||
}
|
||||
for(var i = 0, len = cs.length; i < len; i++){
|
||||
clearAttr(cs[i], '_nodup');
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
function quickDiff(c1, c2){
|
||||
if(!c1.length){
|
||||
return c2;
|
||||
}
|
||||
for(var i = 0, len = c1.length; i < len; i++){
|
||||
addAttr(c1[i], '_qdiff', true);
|
||||
}
|
||||
var r = [];
|
||||
for(var i = 0, len = c2.length; i < len; i++){
|
||||
if(!getAttr(c2[i], '_qdiff')){
|
||||
r[r.length] = c2[i];
|
||||
}
|
||||
}
|
||||
for(var i = 0, len = c1.length; i < len; i++){
|
||||
clearAttr(c1[i], '_qdiff');
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
function quickId(ns, mode, root, id){
|
||||
if(ns == root){
|
||||
var d = root.ownerDocument || root;
|
||||
return d.getElementById(id);
|
||||
}
|
||||
ns = getNodes(ns, mode, '*');
|
||||
return byId(ns, null, id);
|
||||
}
|
||||
|
||||
return {
|
||||
getStyle : function(el, name){
|
||||
return YAHOO.util.Dom.getStyle(el, name);
|
||||
},
|
||||
/**
|
||||
* Compiles a selector/xpath query into a reusable function. The returned function
|
||||
* takes one parameter "root" (optional), which is the context node from where the query should start.
|
||||
* @param {String} selector The selector/xpath query
|
||||
* @param {String} type (optional) Either 'select' (the default) or 'simple' for a simple selector match
|
||||
* @return {Function}
|
||||
*/
|
||||
compile : function(path, type){
|
||||
// strip leading slashes
|
||||
while(path.substr(0, 1)=='/'){
|
||||
path = path.substr(1);
|
||||
}
|
||||
type = type || 'select';
|
||||
|
||||
var fn = ['var f = function(root){\n var mode; var n = root || document;\n'];
|
||||
var q = path, mode, lq;
|
||||
var tk = Clipperz.YUI.DomQuery.matchers;
|
||||
var tklen = tk.length;
|
||||
var mm;
|
||||
while(q && lq != q){
|
||||
lq = q;
|
||||
var tm = q.match(/^(#)?([\w-\*]+)/);
|
||||
if(type == 'select'){
|
||||
if(tm){
|
||||
if(tm[1] == '#'){
|
||||
fn[fn.length] = 'n = quickId(n, mode, root, "'+tm[2]+'");';
|
||||
}else{
|
||||
fn[fn.length] = 'n = getNodes(n, mode, "'+tm[2]+'");';
|
||||
}
|
||||
q = q.replace(tm[0], '');
|
||||
}else{
|
||||
fn[fn.length] = 'n = getNodes(n, mode, "*");';
|
||||
}
|
||||
}else{
|
||||
if(tm){
|
||||
if(tm[1] == '#'){
|
||||
fn[fn.length] = 'n = byId(n, null, "'+tm[2]+'");';
|
||||
}else{
|
||||
fn[fn.length] = 'n = byTag(n, "'+tm[2]+'");';
|
||||
}
|
||||
q = q.replace(tm[0], '');
|
||||
}
|
||||
}
|
||||
while(!(mm = q.match(modeRe))){
|
||||
var matched = false;
|
||||
for(var j = 0; j < tklen; j++){
|
||||
var t = tk[j];
|
||||
var m = q.match(t.re);
|
||||
if(m){
|
||||
fn[fn.length] = t.select.replace(tplRe, function(x, i){
|
||||
return m[i];
|
||||
});
|
||||
q = q.replace(m[0], '');
|
||||
matched = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// prevent infinite loop on bad selector
|
||||
if(!matched){
|
||||
throw 'Error parsing selector, parsing failed at "' + q + '"';
|
||||
}
|
||||
}
|
||||
if(mm[1]){
|
||||
fn[fn.length] = 'mode="'+mm[1]+'";';
|
||||
q = q.replace(mm[1], '');
|
||||
}
|
||||
}
|
||||
fn[fn.length] = 'return nodup(n);\n}';
|
||||
eval(fn.join(''));
|
||||
return f;
|
||||
},
|
||||
|
||||
/**
|
||||
* Selects a group of elements.
|
||||
* @param {String} selector The selector/xpath query
|
||||
* @param {Node} root (optional) The start of the query (defaults to document).
|
||||
* @return {Array}
|
||||
*/
|
||||
select : function(path, root, type){
|
||||
if(!root || root == document){
|
||||
root = document;
|
||||
}
|
||||
if(typeof root == 'string'){
|
||||
root = document.getElementById(root);
|
||||
}
|
||||
var paths = path.split(',');
|
||||
var results = [];
|
||||
for(var i = 0, len = paths.length; i < len; i++){
|
||||
var p = paths[i].replace(trimRe, '$1');
|
||||
if(!cache[p]){
|
||||
cache[p] = Clipperz.YUI.DomQuery.compile(p);
|
||||
if(!cache[p]){
|
||||
throw p + ' is not a valid selector';
|
||||
}
|
||||
}
|
||||
var result = cache[p](root);
|
||||
if(result && result != document){
|
||||
results = results.concat(result);
|
||||
}
|
||||
}
|
||||
return results;
|
||||
},
|
||||
|
||||
/**
|
||||
* Selects a single element.
|
||||
* @param {String} selector The selector/xpath query
|
||||
* @param {Node} root (optional) The start of the query (defaults to document).
|
||||
* @return {Element}
|
||||
*/
|
||||
selectNode : function(path, root){
|
||||
return Clipperz.YUI.DomQuery.select(path, root)[0];
|
||||
},
|
||||
|
||||
/**
|
||||
* Selects the value of a node, optionally replacing null with the defaultValue.
|
||||
* @param {String} selector The selector/xpath query
|
||||
* @param {Node} root (optional) The start of the query (defaults to document).
|
||||
* @param {String} defaultValue
|
||||
*/
|
||||
selectValue : function(path, root, defaultValue){
|
||||
path = path.replace(trimRe, '$1');
|
||||
if(!valueCache[path]){
|
||||
valueCache[path] = Clipperz.YUI.DomQuery.compile(path, 'simple');
|
||||
}
|
||||
var n = valueCache[path](root);
|
||||
n = n[0] ? n[0] : n;
|
||||
var v = (n && n.firstChild ? n.firstChild.nodeValue : null);
|
||||
return (v === null ? defaultValue : v);
|
||||
},
|
||||
|
||||
/**
|
||||
* Selects the value of a node, parsing integers and floats.
|
||||
* @param {String} selector The selector/xpath query
|
||||
* @param {Node} root (optional) The start of the query (defaults to document).
|
||||
* @param {Number} defaultValue
|
||||
* @return {Number}
|
||||
*/
|
||||
selectNumber : function(path, root, defaultValue){
|
||||
var v = Clipperz.YUI.DomQuery.selectValue(path, root, defaultValue || 0);
|
||||
return parseFloat(v);
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns true if the passed element(s) match the passed simple selector (e.g. div.some-class or span:first-child)
|
||||
* @param {String/HTMLElement/Array} el An element id, element or array of elements
|
||||
* @param {String} selector The simple selector to test
|
||||
* @return {Boolean}
|
||||
*/
|
||||
is : function(el, ss){
|
||||
if(typeof el == 'string'){
|
||||
el = document.getElementById(el);
|
||||
}
|
||||
var isArray = (el instanceof Array);
|
||||
var result = Clipperz.YUI.DomQuery.filter(isArray ? el : [el], ss);
|
||||
return isArray ? (result.length == el.length) : (result.length > 0);
|
||||
},
|
||||
|
||||
/**
|
||||
* Filters an array of elements to only include matches of a simple selector (e.g. div.some-class or span:first-child)
|
||||
* @param {Array} el An array of elements to filter
|
||||
* @param {String} selector The simple selector to test
|
||||
* @param {Boolean} nonMatches If true, it returns the elements that DON'T match
|
||||
* the selector instead of the ones that match
|
||||
* @return {Array}
|
||||
*/
|
||||
filter : function(els, ss, nonMatches){
|
||||
ss = ss.replace(trimRe, '$1');
|
||||
if(!simpleCache[ss]){
|
||||
simpleCache[ss] = Clipperz.YUI.DomQuery.compile(ss, 'simple');
|
||||
}
|
||||
var result = simpleCache[ss](els);
|
||||
return nonMatches ? quickDiff(result, els) : result;
|
||||
},
|
||||
|
||||
/**
|
||||
* Collection of matching regular expressions and code snippets.
|
||||
*/
|
||||
matchers : [{
|
||||
re: /^\.([\w-]+)/,
|
||||
select: 'n = byClassName(n, null, "{1}");'
|
||||
}, {
|
||||
re: /^\:([\w-]+)(?:\(((?:[^\s>\/]*|.*?))\))?/,
|
||||
select: 'n = byPseudo(n, "{1}", "{2}");'
|
||||
},{
|
||||
re: /^(?:([\[\{])(?:@)?([\w-]+)\s?(?:(=|.=)\s?['"]?(.*?)["']?)?[\]\}])/,
|
||||
select: 'n = byAttribute(n, "{2}", "{4}", "{3}", "{1}");'
|
||||
}, {
|
||||
re: /^#([\w-]+)/,
|
||||
select: 'n = byId(n, null, "{1}");'
|
||||
},{
|
||||
re: /^@([\w-]+)/,
|
||||
select: 'return {firstChild:{nodeValue:attrValue(n, "{1}")}};'
|
||||
}
|
||||
],
|
||||
|
||||
/**
|
||||
* Collection of operator comparison functions. The default operators are =, !=, ^=, $=, *= and %=.
|
||||
* New operators can be added as long as the match the format <i>c</i>= where <i>c<i> is any character other than space, > <.
|
||||
*/
|
||||
operators : {
|
||||
'=' : function(a, v){
|
||||
return a == v;
|
||||
},
|
||||
'!=' : function(a, v){
|
||||
return a != v;
|
||||
},
|
||||
'^=' : function(a, v){
|
||||
return a && a.substr(0, v.length) == v;
|
||||
},
|
||||
'$=' : function(a, v){
|
||||
return a && a.substr(a.length-v.length) == v;
|
||||
},
|
||||
'*=' : function(a, v){
|
||||
return a && a.indexOf(v) !== -1;
|
||||
},
|
||||
'%=' : function(a, v){
|
||||
return (a % v) == 0;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Collection of "pseudo class" processors. Each processor is passed the current nodeset (array)
|
||||
* and the argument (if any) supplied in the selector.
|
||||
*/
|
||||
pseudos : {
|
||||
'first-child' : function(c){
|
||||
var r = [];
|
||||
for(var i = 0, l = c.length; i < l; i++){
|
||||
var ci = c[i];
|
||||
if(!prev(ci)){
|
||||
r[r.length] = ci;
|
||||
}
|
||||
}
|
||||
return r;
|
||||
},
|
||||
|
||||
'last-child' : function(c){
|
||||
var r = [];
|
||||
for(var i = 0, l = c.length; i < l; i++){
|
||||
var ci = c[i];
|
||||
if(!next(ci)){
|
||||
r[r.length] = ci;
|
||||
}
|
||||
}
|
||||
return r;
|
||||
},
|
||||
|
||||
'nth-child' : function(c, a){
|
||||
var r = [];
|
||||
if(a != 'odd' && a != 'even'){
|
||||
for(var i = 0, ci; ci = c[i]; i++){
|
||||
var m = child(ci.parentNode, a);
|
||||
if(m == ci){
|
||||
r[r.length] = m;
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
var p;
|
||||
// first let's clean up the parent nodes
|
||||
for(var i = 0, l = c.length; i < l; i++){
|
||||
var cp = c[i].parentNode;
|
||||
if(cp != p){
|
||||
clean(cp);
|
||||
p = cp;
|
||||
}
|
||||
}
|
||||
// then lets see if we match
|
||||
for(var i = 0, l = c.length; i < l; i++){
|
||||
var ci = c[i], m = false;
|
||||
if(a == 'odd'){
|
||||
m = ((ci.nodeIndex+1) % 2 == 1);
|
||||
}else if(a == 'even'){
|
||||
m = ((ci.nodeIndex+1) % 2 == 0);
|
||||
}
|
||||
if(m){
|
||||
r[r.length] = ci;
|
||||
}
|
||||
}
|
||||
return r;
|
||||
},
|
||||
|
||||
'only-child' : function(c){
|
||||
var r = [];
|
||||
for(var i = 0, l = c.length; i < l; i++){
|
||||
var ci = c[i];
|
||||
if(!prev(ci) && !next(ci)){
|
||||
r[r.length] = ci;
|
||||
}
|
||||
}
|
||||
return r;
|
||||
},
|
||||
|
||||
'empty' : function(c){
|
||||
var r = [];
|
||||
for(var i = 0, l = c.length; i < l; i++){
|
||||
var ci = c[i];
|
||||
if(!ci.firstChild){
|
||||
r[r.length] = ci;
|
||||
}
|
||||
}
|
||||
return r;
|
||||
},
|
||||
|
||||
'contains' : function(c, v){
|
||||
var r = [];
|
||||
for(var i = 0, l = c.length; i < l; i++){
|
||||
var ci = c[i];
|
||||
if(ci.innerHTML.indexOf(v) !== -1){
|
||||
r[r.length] = ci;
|
||||
}
|
||||
}
|
||||
return r;
|
||||
},
|
||||
|
||||
'checked' : function(c){
|
||||
var r = [];
|
||||
for(var i = 0, l = c.length; i < l; i++){
|
||||
if(c[i].checked == 'checked'){
|
||||
r[r.length] = c[i];
|
||||
}
|
||||
}
|
||||
return r;
|
||||
},
|
||||
|
||||
'not' : function(c, ss){
|
||||
return Clipperz.YUI.DomQuery.filter(c, ss, true);
|
||||
},
|
||||
|
||||
'odd' : function(c){
|
||||
return this['nth-child'](c, 'odd');
|
||||
},
|
||||
|
||||
'even' : function(c){
|
||||
return this['nth-child'](c, 'even');
|
||||
},
|
||||
|
||||
'nth' : function(c, a){
|
||||
return c[a-1];
|
||||
},
|
||||
|
||||
'first' : function(c){
|
||||
return c[0];
|
||||
},
|
||||
|
||||
'last' : function(c){
|
||||
return c[c.length-1];
|
||||
},
|
||||
|
||||
'has' : function(c, ss){
|
||||
var s = Clipperz.YUI.DomQuery.select;
|
||||
var r = [];
|
||||
for(var i = 0, ci; ci = c[i]; i++){
|
||||
if(s(ss, ci).length > 0){
|
||||
r[r.length] = ci;
|
||||
}
|
||||
}
|
||||
return r;
|
||||
},
|
||||
|
||||
'next' : function(c, ss){
|
||||
var is = Clipperz.YUI.DomQuery.is;
|
||||
var r = [];
|
||||
for(var i = 0, ci; ci = c[i]; i++){
|
||||
var n = next(ci);
|
||||
if(n && is(n, ss)){
|
||||
r[r.length] = ci;
|
||||
}
|
||||
}
|
||||
return r;
|
||||
},
|
||||
|
||||
'prev' : function(c, ss){
|
||||
var is = Clipperz.YUI.DomQuery.is;
|
||||
var r = [];
|
||||
for(var i = 0, ci; ci = c[i]; i++){
|
||||
var n = prev(ci);
|
||||
if(n && is(n, ss)){
|
||||
r[r.length] = ci;
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
}
|
||||
};
|
||||
}();
|
||||
|
||||
/**
|
||||
* Selects an array of DOM nodes by CSS/XPath selector. Shorthand of {@link Clipperz.YUI.DomQuery#select}
|
||||
* @param {String} path The selector/xpath query
|
||||
* @param {Node} root (optional) The start of the query (defaults to document).
|
||||
* @return {Array}
|
||||
* @member Ext
|
||||
* @method query
|
||||
*/
|
||||
Clipperz.YUI.query = Clipperz.YUI.DomQuery.select;
|
||||
93
frontend/delta/js/Clipperz/YUI/Utils.js
Normal file
93
frontend/delta/js/Clipperz/YUI/Utils.js
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
if (typeof YAHOO == 'undefined') { YAHOO = {}; };
|
||||
if (typeof YAHOO.util == 'undefined') { YAHOO.util = {}; };
|
||||
if (typeof YAHOO.util.Dom == 'undefined') { YAHOO.util.Dom = {}; };
|
||||
|
||||
YAHOO.extend = function(subc, superc, overrides) {
|
||||
var F = function() {};
|
||||
F.prototype=superc.prototype;
|
||||
subc.prototype=new F();
|
||||
subc.prototype.constructor=subc;
|
||||
subc.superclass=superc.prototype;
|
||||
if (superc.prototype.constructor == Object.prototype.constructor) {
|
||||
superc.prototype.constructor=superc;
|
||||
}
|
||||
|
||||
if (overrides) {
|
||||
for (var i in overrides) {
|
||||
subc.prototype[i]=overrides[i];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
YAHOO.override = function(origclass, overrides){
|
||||
if(overrides){
|
||||
var p = origclass.prototype;
|
||||
for(var method in overrides){
|
||||
p[method] = overrides[method];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
YAHOO.extendX = function(subclass, superclass, overrides){
|
||||
YAHOO.extend(subclass, superclass);
|
||||
subclass.override = function(o){
|
||||
YAHOO.override(subclass, o);
|
||||
};
|
||||
if(!subclass.prototype.override){
|
||||
subclass.prototype.override = function(o){
|
||||
for(var method in o){
|
||||
this[method] = o[method];
|
||||
}
|
||||
};
|
||||
}
|
||||
if(overrides){
|
||||
subclass.override(overrides);
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
YAHOO.util.Dom.get = function(el) {
|
||||
if (!el) { return null; } // nothing to work with
|
||||
|
||||
if (typeof el != 'string' && !(el instanceof Array) ) { // assuming HTMLElement or HTMLCollection, so pass back as is
|
||||
return el;
|
||||
}
|
||||
|
||||
if (typeof el == 'string') { // ID
|
||||
return document.getElementById(el);
|
||||
}
|
||||
else { // array of ID's and/or elements
|
||||
var collection = [];
|
||||
for (var i = 0, len = el.length; i < len; ++i) {
|
||||
collection[collection.length] = YAHOO.util.Dom.get(el[i]);
|
||||
}
|
||||
|
||||
return collection;
|
||||
}
|
||||
|
||||
return null; // safety, should never happen
|
||||
};
|
||||
|
||||
365
frontend/delta/js/Cubiq/add2home.js
Normal file
365
frontend/delta/js/Cubiq/add2home.js
Normal file
@@ -0,0 +1,365 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
/*!
|
||||
* Add to Homescreen v2.0.8 ~ Copyright (c) 2013 Matteo Spinelli, http://cubiq.org
|
||||
* Released under MIT license, http://cubiq.org/license
|
||||
*/
|
||||
var addToHome = (function (w) {
|
||||
var nav = w.navigator,
|
||||
isIDevice = 'platform' in nav && (/iphone|ipod|ipad/gi).test(nav.platform),
|
||||
isIPad,
|
||||
isRetina,
|
||||
isSafari,
|
||||
isStandalone,
|
||||
OSVersion,
|
||||
startX = 0,
|
||||
startY = 0,
|
||||
lastVisit = 0,
|
||||
isExpired,
|
||||
isSessionActive,
|
||||
isReturningVisitor,
|
||||
balloon,
|
||||
overrideChecks,
|
||||
|
||||
positionInterval,
|
||||
closeTimeout,
|
||||
|
||||
options = {
|
||||
autostart: true, // Automatically open the balloon
|
||||
returningVisitor: false, // Show the balloon to returning visitors only (setting this to true is highly recommended)
|
||||
animationIn: 'drop', // drop || bubble || fade
|
||||
animationOut: 'fade', // drop || bubble || fade
|
||||
startDelay: 2000, // 2 seconds from page load before the balloon appears
|
||||
lifespan: 15000, // 15 seconds before it is automatically destroyed
|
||||
bottomOffset: 14, // Distance of the balloon from bottom
|
||||
expire: 0, // Minutes to wait before showing the popup again (0 = always displayed)
|
||||
message: '', // Customize your message or force a language ('' = automatic)
|
||||
touchIcon: false, // Display the touch icon
|
||||
arrow: true, // Display the balloon arrow
|
||||
hookOnLoad: true, // Should we hook to onload event? (really advanced usage)
|
||||
closeButton: true, // Let the user close the balloon
|
||||
iterations: 100 // Internal/debug use
|
||||
},
|
||||
|
||||
intl = {
|
||||
ar: '<span dir="rtl">قم بتثبيت هذا التطبيق على <span dir="ltr">%device:</span>انقر<span dir="ltr">%icon</span> ،<strong>ثم اضفه الى الشاشة الرئيسية.</strong></span>',
|
||||
ca_es: 'Per instal·lar aquesta aplicació al vostre %device premeu %icon i llavors <strong>Afegir a pantalla d\'inici</strong>.',
|
||||
cs_cz: 'Pro instalaci aplikace na Váš %device, stiskněte %icon a v nabídce <strong>Přidat na plochu</strong>.',
|
||||
da_dk: 'Tilføj denne side til din %device: tryk på %icon og derefter <strong>Føj til hjemmeskærm</strong>.',
|
||||
de_de: 'Installieren Sie diese App auf Ihrem %device: %icon antippen und dann <strong>Zum Home-Bildschirm</strong>.',
|
||||
el_gr: 'Εγκαταστήσετε αυτήν την Εφαρμογή στήν συσκευή σας %device: %icon μετά πατάτε <strong>Προσθήκη σε Αφετηρία</strong>.',
|
||||
en_us: 'Install this web app on your %device: tap %icon and then <strong>Add to Home Screen</strong>.',
|
||||
es_es: 'Para instalar esta app en su %device, pulse %icon y seleccione <strong>Añadir a pantalla de inicio</strong>.',
|
||||
fi_fi: 'Asenna tämä web-sovellus laitteeseesi %device: paina %icon ja sen jälkeen valitse <strong>Lisää Koti-valikkoon</strong>.',
|
||||
fr_fr: 'Ajoutez cette application sur votre %device en cliquant sur %icon, puis <strong>Ajouter à l\'écran d\'accueil</strong>.',
|
||||
he_il: '<span dir="rtl">התקן אפליקציה זו על ה-%device שלך: הקש %icon ואז <strong>הוסף למסך הבית</strong>.</span>',
|
||||
hr_hr: 'Instaliraj ovu aplikaciju na svoj %device: klikni na %icon i odaberi <strong>Dodaj u početni zaslon</strong>.',
|
||||
hu_hu: 'Telepítse ezt a web-alkalmazást az Ön %device-jára: nyomjon a %icon-ra majd a <strong>Főképernyőhöz adás</strong> gombra.',
|
||||
it_it: 'Installa questa applicazione sul tuo %device: premi su %icon e poi <strong>Aggiungi a Home</strong>.',
|
||||
ja_jp: 'このウェブアプリをあなたの%deviceにインストールするには%iconをタップして<strong>ホーム画面に追加</strong>を選んでください。',
|
||||
ko_kr: '%device에 웹앱을 설치하려면 %icon을 터치 후 "홈화면에 추가"를 선택하세요',
|
||||
nb_no: 'Installer denne appen på din %device: trykk på %icon og deretter <strong>Legg til på Hjem-skjerm</strong>',
|
||||
nl_nl: 'Installeer deze webapp op uw %device: tik %icon en dan <strong>Voeg toe aan beginscherm</strong>.',
|
||||
pl_pl: 'Aby zainstalować tę aplikacje na %device: naciśnij %icon a następnie <strong>Dodaj jako ikonę</strong>.',
|
||||
pt_br: 'Instale este aplicativo em seu %device: aperte %icon e selecione <strong>Adicionar à Tela Inicio</strong>.',
|
||||
pt_pt: 'Para instalar esta aplicação no seu %device, prima o %icon e depois em <strong>Adicionar ao ecrã principal</strong>.',
|
||||
ru_ru: 'Установите это веб-приложение на ваш %device: нажмите %icon, затем <strong>Добавить в «Домой»</strong>.',
|
||||
sv_se: 'Lägg till denna webbapplikation på din %device: tryck på %icon och därefter <strong>Lägg till på hemskärmen</strong>.',
|
||||
th_th: 'ติดตั้งเว็บแอพฯ นี้บน %device ของคุณ: แตะ %icon และ <strong>เพิ่มที่หน้าจอโฮม</strong>',
|
||||
tr_tr: 'Bu uygulamayı %device\'a eklemek için %icon simgesine sonrasında <strong>Ana Ekrana Ekle</strong> düğmesine basın.',
|
||||
uk_ua: 'Встановіть цей веб сайт на Ваш %device: натисніть %icon, а потім <strong>На початковий екран</strong>.',
|
||||
zh_cn: '您可以将此应用程式安装到您的 %device 上。请按 %icon 然后点选<strong>添加至主屏幕</strong>。',
|
||||
zh_tw: '您可以將此應用程式安裝到您的 %device 上。請按 %icon 然後點選<strong>加入主畫面螢幕</strong>。'
|
||||
};
|
||||
|
||||
function init () {
|
||||
// Preliminary check, all further checks are performed on iDevices only
|
||||
if ( !isIDevice ) return;
|
||||
|
||||
var now = Date.now(),
|
||||
i;
|
||||
|
||||
// Merge local with global options
|
||||
if ( w.addToHomeConfig ) {
|
||||
for ( i in w.addToHomeConfig ) {
|
||||
options[i] = w.addToHomeConfig[i];
|
||||
}
|
||||
}
|
||||
if ( !options.autostart ) options.hookOnLoad = false;
|
||||
|
||||
isIPad = (/ipad/gi).test(nav.platform);
|
||||
isRetina = w.devicePixelRatio && w.devicePixelRatio > 1;
|
||||
isSafari = (/Safari/i).test(nav.appVersion) && !(/CriOS/i).test(nav.appVersion);
|
||||
isStandalone = nav.standalone;
|
||||
OSVersion = nav.appVersion.match(/OS (\d+_\d+)/i);
|
||||
OSVersion = OSVersion && OSVersion[1] ? +OSVersion[1].replace('_', '.') : 0;
|
||||
|
||||
lastVisit = +w.localStorage.getItem('addToHome');
|
||||
|
||||
isSessionActive = w.sessionStorage.getItem('addToHomeSession');
|
||||
isReturningVisitor = options.returningVisitor ? lastVisit && lastVisit + 28*24*60*60*1000 > now : true;
|
||||
|
||||
if ( !lastVisit ) lastVisit = now;
|
||||
|
||||
// If it is expired we need to reissue a new balloon
|
||||
isExpired = isReturningVisitor && lastVisit <= now;
|
||||
|
||||
if ( options.hookOnLoad ) w.addEventListener('load', loaded, false);
|
||||
else if ( !options.hookOnLoad && options.autostart ) loaded();
|
||||
}
|
||||
|
||||
function loaded () {
|
||||
w.removeEventListener('load', loaded, false);
|
||||
|
||||
if ( !isReturningVisitor ) w.localStorage.setItem('addToHome', Date.now());
|
||||
else if ( options.expire && isExpired ) w.localStorage.setItem('addToHome', Date.now() + options.expire * 60000);
|
||||
|
||||
if ( !overrideChecks && ( !isSafari || !isExpired || isSessionActive || isStandalone || !isReturningVisitor ) ) return;
|
||||
|
||||
var touchIcon = '',
|
||||
platform = nav.platform.split(' ')[0],
|
||||
language = nav.language.replace('-', '_');
|
||||
|
||||
balloon = document.createElement('div');
|
||||
balloon.id = 'addToHomeScreen';
|
||||
balloon.style.cssText += 'left:-9999px;-webkit-transition-property:-webkit-transform,opacity;-webkit-transition-duration:0;-webkit-transform:translate3d(0,0,0);position:' + (OSVersion < 5 ? 'absolute' : 'fixed');
|
||||
|
||||
// Localize message
|
||||
if ( options.message in intl ) { // You may force a language despite the user's locale
|
||||
language = options.message;
|
||||
options.message = '';
|
||||
}
|
||||
if ( options.message === '' ) { // We look for a suitable language (defaulted to en_us)
|
||||
options.message = language in intl ? intl[language] : intl['en_us'];
|
||||
}
|
||||
|
||||
if ( options.touchIcon ) {
|
||||
touchIcon = isRetina ?
|
||||
document.querySelector('head link[rel^=apple-touch-icon][sizes="114x114"],head link[rel^=apple-touch-icon][sizes="144x144"],head link[rel^=apple-touch-icon]') :
|
||||
document.querySelector('head link[rel^=apple-touch-icon][sizes="57x57"],head link[rel^=apple-touch-icon]');
|
||||
|
||||
if ( touchIcon ) {
|
||||
touchIcon = '<span style="background-image:url(' + touchIcon.href + ')" class="addToHomeTouchIcon"></span>';
|
||||
}
|
||||
}
|
||||
|
||||
balloon.className = (isIPad ? 'addToHomeIpad' : 'addToHomeIphone') + (touchIcon ? ' addToHomeWide' : '');
|
||||
balloon.innerHTML = touchIcon +
|
||||
options.message.replace('%device', platform).replace('%icon', OSVersion >= 4.2 ? '<span class="addToHomeShare' + (OSVersion >= 7 ? ' addToHomeShareOS7' : '') + '"></span>' : '<span class="addToHomePlus">+</span>') +
|
||||
(options.arrow ? '<span class="addToHomeArrow"></span>' : '') +
|
||||
(options.closeButton ? '<span class="addToHomeClose">\u00D7</span>' : '');
|
||||
|
||||
document.body.appendChild(balloon);
|
||||
|
||||
// Add the close action
|
||||
if ( options.closeButton ) balloon.addEventListener('click', clicked, false);
|
||||
|
||||
if ( !isIPad && OSVersion >= 6 ) window.addEventListener('orientationchange', orientationCheck, false);
|
||||
|
||||
setTimeout(show, options.startDelay);
|
||||
}
|
||||
|
||||
function show () {
|
||||
var duration,
|
||||
iPadXShift = 208;
|
||||
|
||||
// Set the initial position
|
||||
if ( isIPad ) {
|
||||
if ( OSVersion < 5 ) {
|
||||
startY = w.scrollY;
|
||||
startX = w.scrollX;
|
||||
} else if ( OSVersion < 6 ) {
|
||||
iPadXShift = 160;
|
||||
}
|
||||
|
||||
balloon.style.top = startY + options.bottomOffset + 'px';
|
||||
balloon.style.left = startX + iPadXShift - Math.round(balloon.offsetWidth / 2) + 'px';
|
||||
|
||||
switch ( options.animationIn ) {
|
||||
case 'drop':
|
||||
duration = '0.6s';
|
||||
balloon.style.webkitTransform = 'translate3d(0,' + -(w.scrollY + options.bottomOffset + balloon.offsetHeight) + 'px,0)';
|
||||
break;
|
||||
case 'bubble':
|
||||
duration = '0.6s';
|
||||
balloon.style.opacity = '0';
|
||||
balloon.style.webkitTransform = 'translate3d(0,' + (startY + 50) + 'px,0)';
|
||||
break;
|
||||
default:
|
||||
duration = '1s';
|
||||
balloon.style.opacity = '0';
|
||||
}
|
||||
} else {
|
||||
startY = w.innerHeight + w.scrollY;
|
||||
|
||||
if ( OSVersion < 5 ) {
|
||||
startX = Math.round((w.innerWidth - balloon.offsetWidth) / 2) + w.scrollX;
|
||||
balloon.style.left = startX + 'px';
|
||||
balloon.style.top = startY - balloon.offsetHeight - options.bottomOffset + 'px';
|
||||
} else {
|
||||
balloon.style.left = '50%';
|
||||
balloon.style.marginLeft = -Math.round(balloon.offsetWidth / 2) - ( w.orientation%180 && OSVersion >= 6 ? 40 : 0 ) + 'px';
|
||||
balloon.style.bottom = options.bottomOffset + 'px';
|
||||
}
|
||||
|
||||
switch (options.animationIn) {
|
||||
case 'drop':
|
||||
duration = '1s';
|
||||
balloon.style.webkitTransform = 'translate3d(0,' + -(startY + options.bottomOffset) + 'px,0)';
|
||||
break;
|
||||
case 'bubble':
|
||||
duration = '0.6s';
|
||||
balloon.style.webkitTransform = 'translate3d(0,' + (balloon.offsetHeight + options.bottomOffset + 50) + 'px,0)';
|
||||
break;
|
||||
default:
|
||||
duration = '1s';
|
||||
balloon.style.opacity = '0';
|
||||
}
|
||||
}
|
||||
|
||||
balloon.offsetHeight; // repaint trick
|
||||
balloon.style.webkitTransitionDuration = duration;
|
||||
balloon.style.opacity = '1';
|
||||
balloon.style.webkitTransform = 'translate3d(0,0,0)';
|
||||
balloon.addEventListener('webkitTransitionEnd', transitionEnd, false);
|
||||
|
||||
closeTimeout = setTimeout(close, options.lifespan);
|
||||
}
|
||||
|
||||
function manualShow (override) {
|
||||
if ( !isIDevice || balloon ) return;
|
||||
|
||||
overrideChecks = override;
|
||||
loaded();
|
||||
}
|
||||
|
||||
function close () {
|
||||
clearInterval( positionInterval );
|
||||
clearTimeout( closeTimeout );
|
||||
closeTimeout = null;
|
||||
|
||||
// check if the popup is displayed and prevent errors
|
||||
if ( !balloon ) return;
|
||||
|
||||
var posY = 0,
|
||||
posX = 0,
|
||||
opacity = '1',
|
||||
duration = '0';
|
||||
|
||||
if ( options.closeButton ) balloon.removeEventListener('click', clicked, false);
|
||||
if ( !isIPad && OSVersion >= 6 ) window.removeEventListener('orientationchange', orientationCheck, false);
|
||||
|
||||
if ( OSVersion < 5 ) {
|
||||
posY = isIPad ? w.scrollY - startY : w.scrollY + w.innerHeight - startY;
|
||||
posX = isIPad ? w.scrollX - startX : w.scrollX + Math.round((w.innerWidth - balloon.offsetWidth)/2) - startX;
|
||||
}
|
||||
|
||||
balloon.style.webkitTransitionProperty = '-webkit-transform,opacity';
|
||||
|
||||
switch ( options.animationOut ) {
|
||||
case 'drop':
|
||||
if ( isIPad ) {
|
||||
duration = '0.4s';
|
||||
opacity = '0';
|
||||
posY += 50;
|
||||
} else {
|
||||
duration = '0.6s';
|
||||
posY += balloon.offsetHeight + options.bottomOffset + 50;
|
||||
}
|
||||
break;
|
||||
case 'bubble':
|
||||
if ( isIPad ) {
|
||||
duration = '0.8s';
|
||||
posY -= balloon.offsetHeight + options.bottomOffset + 50;
|
||||
} else {
|
||||
duration = '0.4s';
|
||||
opacity = '0';
|
||||
posY -= 50;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
duration = '0.8s';
|
||||
opacity = '0';
|
||||
}
|
||||
|
||||
balloon.addEventListener('webkitTransitionEnd', transitionEnd, false);
|
||||
balloon.style.opacity = opacity;
|
||||
balloon.style.webkitTransitionDuration = duration;
|
||||
balloon.style.webkitTransform = 'translate3d(' + posX + 'px,' + posY + 'px,0)';
|
||||
}
|
||||
|
||||
|
||||
function clicked () {
|
||||
w.sessionStorage.setItem('addToHomeSession', '1');
|
||||
isSessionActive = true;
|
||||
close();
|
||||
}
|
||||
|
||||
function transitionEnd () {
|
||||
balloon.removeEventListener('webkitTransitionEnd', transitionEnd, false);
|
||||
|
||||
balloon.style.webkitTransitionProperty = '-webkit-transform';
|
||||
balloon.style.webkitTransitionDuration = '0.2s';
|
||||
|
||||
// We reached the end!
|
||||
if ( !closeTimeout ) {
|
||||
balloon.parentNode.removeChild(balloon);
|
||||
balloon = null;
|
||||
return;
|
||||
}
|
||||
|
||||
// On iOS 4 we start checking the element position
|
||||
if ( OSVersion < 5 && closeTimeout ) positionInterval = setInterval(setPosition, options.iterations);
|
||||
}
|
||||
|
||||
function setPosition () {
|
||||
var matrix = new WebKitCSSMatrix(w.getComputedStyle(balloon, null).webkitTransform),
|
||||
posY = isIPad ? w.scrollY - startY : w.scrollY + w.innerHeight - startY,
|
||||
posX = isIPad ? w.scrollX - startX : w.scrollX + Math.round((w.innerWidth - balloon.offsetWidth) / 2) - startX;
|
||||
|
||||
// Screen didn't move
|
||||
if ( posY == matrix.m42 && posX == matrix.m41 ) return;
|
||||
|
||||
balloon.style.webkitTransform = 'translate3d(' + posX + 'px,' + posY + 'px,0)';
|
||||
}
|
||||
|
||||
// Clear local and session storages (this is useful primarily in development)
|
||||
function reset () {
|
||||
w.localStorage.removeItem('addToHome');
|
||||
w.sessionStorage.removeItem('addToHomeSession');
|
||||
}
|
||||
|
||||
function orientationCheck () {
|
||||
balloon.style.marginLeft = -Math.round(balloon.offsetWidth / 2) - ( w.orientation%180 && OSVersion >= 6 ? 40 : 0 ) + 'px';
|
||||
}
|
||||
|
||||
// Bootstrap!
|
||||
init();
|
||||
|
||||
return {
|
||||
show: manualShow,
|
||||
close: close,
|
||||
reset: reset
|
||||
};
|
||||
})(window);
|
||||
733
frontend/delta/js/MochiKit/Async.js
Normal file
733
frontend/delta/js/MochiKit/Async.js
Normal file
@@ -0,0 +1,733 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
/***
|
||||
|
||||
MochiKit.Async 1.5
|
||||
|
||||
See <http://mochikit.com/> for documentation, downloads, license, etc.
|
||||
|
||||
(c) 2005 Bob Ippolito. All rights Reserved.
|
||||
|
||||
***/
|
||||
|
||||
MochiKit.Base.module(MochiKit, 'Async', '1.5', ['Base']);
|
||||
|
||||
/** @id MochiKit.Async.Deferred */
|
||||
MochiKit.Async.Deferred = function (/* optional */ canceller) {
|
||||
this.chain = [];
|
||||
this.id = this._nextId();
|
||||
this.fired = -1;
|
||||
this.paused = 0;
|
||||
this.results = [null, null];
|
||||
this.canceller = canceller;
|
||||
this.silentlyCancelled = false;
|
||||
this.chained = false;
|
||||
this.finalized = false;
|
||||
};
|
||||
|
||||
MochiKit.Async.Deferred.prototype = {
|
||||
/** @id MochiKit.Async.Deferred.prototype.repr */
|
||||
repr: function () {
|
||||
return 'Deferred(' + this.id + ', ' + this.state() + ')';
|
||||
},
|
||||
|
||||
toString: MochiKit.Base.forwardCall("repr"),
|
||||
|
||||
_nextId: MochiKit.Base.counter(),
|
||||
|
||||
/** @id MochiKit.Async.Deferred.prototype.state */
|
||||
state: function () {
|
||||
if (this.fired == -1) {
|
||||
return 'unfired';
|
||||
} else if (this.fired === 0) {
|
||||
return 'success';
|
||||
} else {
|
||||
return 'error';
|
||||
}
|
||||
},
|
||||
|
||||
/** @id MochiKit.Async.Deferred.prototype.cancel */
|
||||
cancel: function (e) {
|
||||
var self = MochiKit.Async;
|
||||
if (this.fired == -1) {
|
||||
if (this.canceller) {
|
||||
this.canceller(this);
|
||||
} else {
|
||||
this.silentlyCancelled = true;
|
||||
}
|
||||
if (this.fired == -1) {
|
||||
if (typeof(e) === 'string') {
|
||||
e = new self.GenericError(e);
|
||||
} else if (!(e instanceof Error)) {
|
||||
e = new self.CancelledError(this);
|
||||
}
|
||||
this.errback(e);
|
||||
}
|
||||
} else if ((this.fired === 0) && (this.results[0] instanceof self.Deferred)) {
|
||||
this.results[0].cancel(e);
|
||||
}
|
||||
},
|
||||
|
||||
_resback: function (res) {
|
||||
/***
|
||||
|
||||
The primitive that means either callback or errback
|
||||
|
||||
***/
|
||||
this.fired = ((res instanceof Error) ? 1 : 0);
|
||||
this.results[this.fired] = res;
|
||||
if (this.paused === 0) {
|
||||
this._fire();
|
||||
}
|
||||
},
|
||||
|
||||
_check: function () {
|
||||
if (this.fired != -1) {
|
||||
if (!this.silentlyCancelled) {
|
||||
throw new MochiKit.Async.AlreadyCalledError(this);
|
||||
}
|
||||
this.silentlyCancelled = false;
|
||||
return;
|
||||
}
|
||||
},
|
||||
|
||||
/** @id MochiKit.Async.Deferred.prototype.callback */
|
||||
callback: function (res) {
|
||||
this._check();
|
||||
if (res instanceof MochiKit.Async.Deferred) {
|
||||
throw new Error("Deferred instances can only be chained if they are the result of a callback");
|
||||
}
|
||||
this._resback(res);
|
||||
},
|
||||
|
||||
/** @id MochiKit.Async.Deferred.prototype.errback */
|
||||
errback: function (res) {
|
||||
this._check();
|
||||
var self = MochiKit.Async;
|
||||
if (res instanceof self.Deferred) {
|
||||
throw new Error("Deferred instances can only be chained if they are the result of a callback");
|
||||
}
|
||||
if (!(res instanceof Error)) {
|
||||
res = new self.GenericError(res);
|
||||
}
|
||||
this._resback(res);
|
||||
},
|
||||
|
||||
/** @id MochiKit.Async.Deferred.prototype.addBoth */
|
||||
addBoth: function (fn) {
|
||||
if (arguments.length > 1) {
|
||||
fn = MochiKit.Base.partial.apply(null, arguments);
|
||||
}
|
||||
return this.addCallbacks(fn, fn);
|
||||
},
|
||||
|
||||
/** @id MochiKit.Async.Deferred.prototype.addCallback */
|
||||
addCallback: function (fn) {
|
||||
if (arguments.length > 1) {
|
||||
fn = MochiKit.Base.partial.apply(null, arguments);
|
||||
}
|
||||
return this.addCallbacks(fn, null);
|
||||
},
|
||||
|
||||
/** @id MochiKit.Async.Deferred.prototype.addErrback */
|
||||
addErrback: function (fn) {
|
||||
if (arguments.length > 1) {
|
||||
fn = MochiKit.Base.partial.apply(null, arguments);
|
||||
}
|
||||
return this.addCallbacks(null, fn);
|
||||
},
|
||||
|
||||
/** @id MochiKit.Async.Deferred.prototype.addCallbacks */
|
||||
addCallbacks: function (cb, eb) {
|
||||
if (this.chained) {
|
||||
throw new Error("Chained Deferreds can not be re-used");
|
||||
}
|
||||
if (this.finalized) {
|
||||
throw new Error("Finalized Deferreds can not be re-used");
|
||||
}
|
||||
this.chain.push([cb, eb]);
|
||||
if (this.fired >= 0) {
|
||||
this._fire();
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
/** @id MochiKit.Async.Deferred.prototype.setFinalizer */
|
||||
setFinalizer: function (fn) {
|
||||
if (this.chained) {
|
||||
throw new Error("Chained Deferreds can not be re-used");
|
||||
}
|
||||
if (this.finalized) {
|
||||
throw new Error("Finalized Deferreds can not be re-used");
|
||||
}
|
||||
if (arguments.length > 1) {
|
||||
fn = MochiKit.Base.partial.apply(null, arguments);
|
||||
}
|
||||
this._finalizer = fn;
|
||||
if (this.fired >= 0) {
|
||||
this._fire();
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
_fire: function () {
|
||||
/***
|
||||
|
||||
Used internally to exhaust the callback sequence when a result
|
||||
is available.
|
||||
|
||||
***/
|
||||
var chain = this.chain;
|
||||
var fired = this.fired;
|
||||
var res = this.results[fired];
|
||||
var self = this;
|
||||
var cb = null;
|
||||
while (chain.length > 0 && this.paused === 0) {
|
||||
// Array
|
||||
var pair = chain.shift();
|
||||
var f = pair[fired];
|
||||
if (f === null) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
res = f(res);
|
||||
fired = ((res instanceof Error) ? 1 : 0);
|
||||
if (res instanceof MochiKit.Async.Deferred) {
|
||||
cb = function (res) {
|
||||
self.paused--;
|
||||
self._resback(res);
|
||||
};
|
||||
this.paused++;
|
||||
}
|
||||
} catch (err) {
|
||||
fired = 1;
|
||||
if (!(err instanceof Error)) {
|
||||
err = new MochiKit.Async.GenericError(err);
|
||||
}
|
||||
res = err;
|
||||
}
|
||||
}
|
||||
this.fired = fired;
|
||||
this.results[fired] = res;
|
||||
if (this.chain.length == 0 && this.paused === 0 && this._finalizer) {
|
||||
this.finalized = true;
|
||||
this._finalizer(res);
|
||||
}
|
||||
if (cb && this.paused) {
|
||||
// this is for "tail recursion" in case the dependent deferred
|
||||
// is already fired
|
||||
res.addBoth(cb);
|
||||
res.chained = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
MochiKit.Base.update(MochiKit.Async, {
|
||||
/** @id MochiKit.Async.evalJSONRequest */
|
||||
evalJSONRequest: function (req) {
|
||||
return MochiKit.Base.evalJSON(req.responseText);
|
||||
},
|
||||
|
||||
/** @id MochiKit.Async.succeed */
|
||||
succeed: function (/* optional */result) {
|
||||
var d = new MochiKit.Async.Deferred();
|
||||
d.callback.apply(d, arguments);
|
||||
return d;
|
||||
},
|
||||
|
||||
/** @id MochiKit.Async.fail */
|
||||
fail: function (/* optional */result) {
|
||||
var d = new MochiKit.Async.Deferred();
|
||||
d.errback.apply(d, arguments);
|
||||
return d;
|
||||
},
|
||||
|
||||
/** @id MochiKit.Async.getXMLHttpRequest */
|
||||
getXMLHttpRequest: function () {
|
||||
var self = arguments.callee;
|
||||
if (!self.XMLHttpRequest) {
|
||||
var tryThese = [
|
||||
function () { return new XMLHttpRequest(); },
|
||||
function () { return new ActiveXObject('Msxml2.XMLHTTP'); },
|
||||
function () { return new ActiveXObject('Microsoft.XMLHTTP'); },
|
||||
function () { return new ActiveXObject('Msxml2.XMLHTTP.4.0'); },
|
||||
function () {
|
||||
throw new MochiKit.Async.BrowserComplianceError("Browser does not support XMLHttpRequest");
|
||||
}
|
||||
];
|
||||
for (var i = 0; i < tryThese.length; i++) {
|
||||
var func = tryThese[i];
|
||||
try {
|
||||
self.XMLHttpRequest = func;
|
||||
return func();
|
||||
} catch (e) {
|
||||
// pass
|
||||
}
|
||||
}
|
||||
}
|
||||
return self.XMLHttpRequest();
|
||||
},
|
||||
|
||||
_xhr_onreadystatechange: function (d) {
|
||||
// MochiKit.Logging.logDebug('this.readyState', this.readyState);
|
||||
var m = MochiKit.Base;
|
||||
if (this.readyState == 4) {
|
||||
// IE SUCKS
|
||||
try {
|
||||
this.onreadystatechange = null;
|
||||
} catch (e) {
|
||||
try {
|
||||
this.onreadystatechange = m.noop;
|
||||
} catch (e) {
|
||||
}
|
||||
}
|
||||
var status = null;
|
||||
try {
|
||||
status = this.status;
|
||||
if (!status && (this.response || m.isNotEmpty(this.responseText))) {
|
||||
// 0 or undefined seems to mean cached or local
|
||||
status = 304;
|
||||
}
|
||||
} catch (e) {
|
||||
// pass
|
||||
// MochiKit.Logging.logDebug('error getting status?', repr(items(e)));
|
||||
}
|
||||
// 200 is OK, 201 is CREATED, 204 is NO CONTENT
|
||||
// 304 is NOT MODIFIED, 1223 is apparently a bug in IE
|
||||
if (status == 200 || status == 201 || status == 204 ||
|
||||
status == 304 || status == 1223) {
|
||||
d.callback(this);
|
||||
} else {
|
||||
var err = new MochiKit.Async.XMLHttpRequestError(this, "Request failed");
|
||||
if (err.number) {
|
||||
// XXX: This seems to happen on page change
|
||||
d.errback(err);
|
||||
} else {
|
||||
// XXX: this seems to happen when the server is unreachable
|
||||
d.errback(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_xhr_canceller: function (req) {
|
||||
// IE SUCKS
|
||||
try {
|
||||
req.onreadystatechange = null;
|
||||
} catch (e) {
|
||||
try {
|
||||
req.onreadystatechange = MochiKit.Base.noop;
|
||||
} catch (e) {
|
||||
}
|
||||
}
|
||||
req.abort();
|
||||
},
|
||||
|
||||
|
||||
/** @id MochiKit.Async.sendXMLHttpRequest */
|
||||
sendXMLHttpRequest: function (req, /* optional */ sendContent) {
|
||||
if (typeof(sendContent) == "undefined" || sendContent === null) {
|
||||
sendContent = "";
|
||||
}
|
||||
|
||||
var m = MochiKit.Base;
|
||||
var self = MochiKit.Async;
|
||||
var d = new self.Deferred(m.partial(self._xhr_canceller, req));
|
||||
|
||||
try {
|
||||
req.onreadystatechange = m.bind(self._xhr_onreadystatechange,
|
||||
req, d);
|
||||
req.send(sendContent);
|
||||
} catch (e) {
|
||||
try {
|
||||
req.onreadystatechange = null;
|
||||
} catch (ignore) {
|
||||
// pass
|
||||
}
|
||||
d.errback(e);
|
||||
}
|
||||
|
||||
return d;
|
||||
|
||||
},
|
||||
|
||||
/** @id MochiKit.Async.doXHR */
|
||||
doXHR: function (url, opts) {
|
||||
/*
|
||||
Work around a Firefox bug by dealing with XHR during
|
||||
the next event loop iteration. Maybe it's this one:
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=249843
|
||||
*/
|
||||
var self = MochiKit.Async;
|
||||
return self.callLater(0, self._doXHR, url, opts);
|
||||
},
|
||||
|
||||
_doXHR: function (url, opts) {
|
||||
var m = MochiKit.Base;
|
||||
opts = m.update({
|
||||
method: 'GET',
|
||||
sendContent: ''
|
||||
/*
|
||||
queryString: undefined,
|
||||
username: undefined,
|
||||
password: undefined,
|
||||
headers: undefined,
|
||||
mimeType: undefined,
|
||||
responseType: undefined,
|
||||
withCredentials: undefined
|
||||
*/
|
||||
}, opts);
|
||||
var self = MochiKit.Async;
|
||||
var req = self.getXMLHttpRequest();
|
||||
if (opts.queryString) {
|
||||
var qs = m.queryString(opts.queryString);
|
||||
if (qs) {
|
||||
url += "?" + qs;
|
||||
}
|
||||
}
|
||||
// Safari will send undefined:undefined, so we have to check.
|
||||
// We can't use apply, since the function is native.
|
||||
if ('username' in opts) {
|
||||
req.open(opts.method, url, true, opts.username, opts.password);
|
||||
} else {
|
||||
req.open(opts.method, url, true);
|
||||
}
|
||||
if (req.overrideMimeType && opts.mimeType) {
|
||||
req.overrideMimeType(opts.mimeType);
|
||||
}
|
||||
req.setRequestHeader("X-Requested-With", "XMLHttpRequest");
|
||||
if (opts.headers) {
|
||||
var headers = opts.headers;
|
||||
if (!m.isArrayLike(headers)) {
|
||||
headers = m.items(headers);
|
||||
}
|
||||
for (var i = 0; i < headers.length; i++) {
|
||||
var header = headers[i];
|
||||
var name = header[0];
|
||||
var value = header[1];
|
||||
req.setRequestHeader(name, value);
|
||||
}
|
||||
}
|
||||
if ("responseType" in opts && "responseType" in req) {
|
||||
req.responseType = opts.responseType;
|
||||
}
|
||||
if (opts.withCredentials) {
|
||||
req.withCredentials = 'true';
|
||||
}
|
||||
return self.sendXMLHttpRequest(req, opts.sendContent);
|
||||
},
|
||||
|
||||
_buildURL: function (url/*, ...*/) {
|
||||
if (arguments.length > 1) {
|
||||
var m = MochiKit.Base;
|
||||
var qs = m.queryString.apply(null, m.extend(null, arguments, 1));
|
||||
if (qs) {
|
||||
return url + "?" + qs;
|
||||
}
|
||||
}
|
||||
return url;
|
||||
},
|
||||
|
||||
/** @id MochiKit.Async.doSimpleXMLHttpRequest */
|
||||
doSimpleXMLHttpRequest: function (url/*, ...*/) {
|
||||
var self = MochiKit.Async;
|
||||
url = self._buildURL.apply(self, arguments);
|
||||
return self.doXHR(url);
|
||||
},
|
||||
|
||||
/** @id MochiKit.Async.loadJSONDoc */
|
||||
loadJSONDoc: function (url/*, ...*/) {
|
||||
var self = MochiKit.Async;
|
||||
url = self._buildURL.apply(self, arguments);
|
||||
var d = self.doXHR(url, {
|
||||
'mimeType': 'text/plain',
|
||||
'headers': [['Accept', 'application/json']]
|
||||
});
|
||||
d = d.addCallback(self.evalJSONRequest);
|
||||
return d;
|
||||
},
|
||||
|
||||
/** @id MochiKit.Async.loadScript */
|
||||
loadScript: function (url) {
|
||||
var d = new MochiKit.Async.Deferred();
|
||||
var script = document.createElement("script");
|
||||
script.type = "text/javascript";
|
||||
script.src = url;
|
||||
script.onload = function () {
|
||||
script.onload = null;
|
||||
script.onerror = null;
|
||||
script.onreadystatechange = null;
|
||||
script = null;
|
||||
d.callback();
|
||||
};
|
||||
script.onerror = function (msg) {
|
||||
script.onload = null;
|
||||
script.onerror = null;
|
||||
script.onreadystatechange = null;
|
||||
script = null;
|
||||
msg = "Failed to load script at " + url + ": " + msg;
|
||||
d.errback(new URIError(msg, url));
|
||||
}
|
||||
script.onreadystatechange = function () {
|
||||
if (script.readyState == "loaded" || script.readyState == "complete") {
|
||||
script.onload();
|
||||
} else {
|
||||
// IE doesn't bother to report errors...
|
||||
MochiKit.Async.callLater(10, script.onerror, "Script loading timed out")
|
||||
}
|
||||
};
|
||||
document.getElementsByTagName("head")[0].appendChild(script);
|
||||
return d;
|
||||
},
|
||||
|
||||
/** @id MochiKit.Async.wait */
|
||||
wait: function (seconds, /* optional */value) {
|
||||
var d = new MochiKit.Async.Deferred();
|
||||
var cb = MochiKit.Base.bind("callback", d, value);
|
||||
var timeout = setTimeout(cb, Math.floor(seconds * 1000));
|
||||
d.canceller = function () {
|
||||
try {
|
||||
clearTimeout(timeout);
|
||||
} catch (e) {
|
||||
// pass
|
||||
}
|
||||
};
|
||||
return d;
|
||||
},
|
||||
|
||||
/** @id MochiKit.Async.callLater */
|
||||
callLater: function (seconds, func) {
|
||||
var m = MochiKit.Base;
|
||||
var pfunc = m.partial.apply(m, m.extend(null, arguments, 1));
|
||||
return MochiKit.Async.wait(seconds).addCallback(
|
||||
function (res) { return pfunc(); }
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/** @id MochiKit.Async.DeferredLock */
|
||||
MochiKit.Async.DeferredLock = function () {
|
||||
this.waiting = [];
|
||||
this.locked = false;
|
||||
this.id = this._nextId();
|
||||
};
|
||||
|
||||
MochiKit.Async.DeferredLock.prototype = {
|
||||
__class__: MochiKit.Async.DeferredLock,
|
||||
/** @id MochiKit.Async.DeferredLock.prototype.acquire */
|
||||
acquire: function () {
|
||||
var d = new MochiKit.Async.Deferred();
|
||||
if (this.locked) {
|
||||
this.waiting.push(d);
|
||||
} else {
|
||||
this.locked = true;
|
||||
d.callback(this);
|
||||
}
|
||||
return d;
|
||||
},
|
||||
/** @id MochiKit.Async.DeferredLock.prototype.release */
|
||||
release: function () {
|
||||
if (!this.locked) {
|
||||
throw TypeError("Tried to release an unlocked DeferredLock");
|
||||
}
|
||||
this.locked = false;
|
||||
if (this.waiting.length > 0) {
|
||||
this.locked = true;
|
||||
this.waiting.shift().callback(this);
|
||||
}
|
||||
},
|
||||
_nextId: MochiKit.Base.counter(),
|
||||
repr: function () {
|
||||
var state;
|
||||
if (this.locked) {
|
||||
state = 'locked, ' + this.waiting.length + ' waiting';
|
||||
} else {
|
||||
state = 'unlocked';
|
||||
}
|
||||
return 'DeferredLock(' + this.id + ', ' + state + ')';
|
||||
},
|
||||
toString: MochiKit.Base.forwardCall("repr")
|
||||
|
||||
};
|
||||
|
||||
/** @id MochiKit.Async.DeferredList */
|
||||
MochiKit.Async.DeferredList = function (list, /* optional */fireOnOneCallback, fireOnOneErrback, consumeErrors, canceller) {
|
||||
|
||||
// call parent constructor
|
||||
MochiKit.Async.Deferred.apply(this, [canceller]);
|
||||
|
||||
this.list = list;
|
||||
var resultList = [];
|
||||
this.resultList = resultList;
|
||||
|
||||
this.finishedCount = 0;
|
||||
this.fireOnOneCallback = fireOnOneCallback;
|
||||
this.fireOnOneErrback = fireOnOneErrback;
|
||||
this.consumeErrors = consumeErrors;
|
||||
|
||||
var cb = MochiKit.Base.bind(this._cbDeferred, this);
|
||||
for (var i = 0; i < list.length; i++) {
|
||||
var d = list[i];
|
||||
resultList.push(undefined);
|
||||
d.addCallback(cb, i, true);
|
||||
d.addErrback(cb, i, false);
|
||||
}
|
||||
|
||||
if (list.length === 0 && !fireOnOneCallback) {
|
||||
this.callback(this.resultList);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
MochiKit.Async.DeferredList.prototype = new MochiKit.Async.Deferred();
|
||||
MochiKit.Async.DeferredList.prototype.constructor = MochiKit.Async.DeferredList;
|
||||
|
||||
MochiKit.Async.DeferredList.prototype._cbDeferred = function (index, succeeded, result) {
|
||||
this.resultList[index] = [succeeded, result];
|
||||
this.finishedCount += 1;
|
||||
if (this.fired == -1) {
|
||||
if (succeeded && this.fireOnOneCallback) {
|
||||
this.callback([index, result]);
|
||||
} else if (!succeeded && this.fireOnOneErrback) {
|
||||
this.errback(result);
|
||||
} else if (this.finishedCount == this.list.length) {
|
||||
this.callback(this.resultList);
|
||||
}
|
||||
}
|
||||
if (!succeeded && this.consumeErrors) {
|
||||
result = null;
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
/** @id MochiKit.Async.gatherResults */
|
||||
MochiKit.Async.gatherResults = function (deferredList) {
|
||||
var d = new MochiKit.Async.DeferredList(deferredList, false, true, false);
|
||||
d.addCallback(function (results) {
|
||||
var ret = [];
|
||||
for (var i = 0; i < results.length; i++) {
|
||||
ret.push(results[i][1]);
|
||||
}
|
||||
return ret;
|
||||
});
|
||||
return d;
|
||||
};
|
||||
|
||||
/** @id MochiKit.Async.maybeDeferred */
|
||||
MochiKit.Async.maybeDeferred = function (func) {
|
||||
var self = MochiKit.Async;
|
||||
var result;
|
||||
try {
|
||||
var r = func.apply(null, MochiKit.Base.extend([], arguments, 1));
|
||||
if (r instanceof self.Deferred) {
|
||||
result = r;
|
||||
} else if (r instanceof Error) {
|
||||
result = self.fail(r);
|
||||
} else {
|
||||
result = self.succeed(r);
|
||||
}
|
||||
} catch (e) {
|
||||
result = self.fail(e);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
|
||||
MochiKit.Async.__new__ = function () {
|
||||
var m = MochiKit.Base;
|
||||
var ne = m.partial(m._newNamedError, this);
|
||||
|
||||
ne("AlreadyCalledError",
|
||||
/** @id MochiKit.Async.AlreadyCalledError */
|
||||
function (deferred) {
|
||||
/***
|
||||
|
||||
Raised by the Deferred if callback or errback happens
|
||||
after it was already fired.
|
||||
|
||||
***/
|
||||
this.deferred = deferred;
|
||||
}
|
||||
);
|
||||
|
||||
ne("CancelledError",
|
||||
/** @id MochiKit.Async.CancelledError */
|
||||
function (deferred) {
|
||||
/***
|
||||
|
||||
Raised by the Deferred cancellation mechanism.
|
||||
|
||||
***/
|
||||
this.deferred = deferred;
|
||||
}
|
||||
);
|
||||
|
||||
ne("BrowserComplianceError",
|
||||
/** @id MochiKit.Async.BrowserComplianceError */
|
||||
function (msg) {
|
||||
/***
|
||||
|
||||
Raised when the JavaScript runtime is not capable of performing
|
||||
the given function. Technically, this should really never be
|
||||
raised because a non-conforming JavaScript runtime probably
|
||||
isn't going to support exceptions in the first place.
|
||||
|
||||
***/
|
||||
this.message = msg;
|
||||
}
|
||||
);
|
||||
|
||||
ne("GenericError",
|
||||
/** @id MochiKit.Async.GenericError */
|
||||
function (msg) {
|
||||
this.message = msg;
|
||||
}
|
||||
);
|
||||
|
||||
ne("XMLHttpRequestError",
|
||||
/** @id MochiKit.Async.XMLHttpRequestError */
|
||||
function (req, msg) {
|
||||
/***
|
||||
|
||||
Raised when an XMLHttpRequest does not complete for any reason.
|
||||
|
||||
***/
|
||||
this.req = req;
|
||||
this.message = msg;
|
||||
try {
|
||||
// Strange but true that this can raise in some cases.
|
||||
this.number = req.status;
|
||||
} catch (e) {
|
||||
// pass
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
m.nameFunctions(this);
|
||||
};
|
||||
|
||||
MochiKit.Async.__new__();
|
||||
|
||||
MochiKit.Base._exportSymbols(this, MochiKit.Async);
|
||||
1523
frontend/delta/js/MochiKit/Base.js
Normal file
1523
frontend/delta/js/MochiKit/Base.js
Normal file
File diff suppressed because it is too large
Load Diff
846
frontend/delta/js/MochiKit/Color.js
Normal file
846
frontend/delta/js/MochiKit/Color.js
Normal file
@@ -0,0 +1,846 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
/***
|
||||
|
||||
MochiKit.Color 1.5
|
||||
|
||||
See <http://mochikit.com/> for documentation, downloads, license, etc.
|
||||
|
||||
(c) 2005 Bob Ippolito and others. All rights Reserved.
|
||||
|
||||
***/
|
||||
|
||||
MochiKit.Base.module(MochiKit, 'Color', '1.5', ['Base', 'DOM', 'Style']);
|
||||
|
||||
/** @id MochiKit.Color.Color */
|
||||
MochiKit.Color.Color = function (red, green, blue, alpha) {
|
||||
if (typeof(alpha) == 'undefined' || alpha === null) {
|
||||
alpha = 1.0;
|
||||
}
|
||||
this.rgb = {
|
||||
r: red,
|
||||
g: green,
|
||||
b: blue,
|
||||
a: alpha
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
// Prototype methods
|
||||
|
||||
MochiKit.Color.Color.prototype = {
|
||||
|
||||
__class__: MochiKit.Color.Color,
|
||||
|
||||
/** @id MochiKit.Color.Color.prototype.colorWithAlpha */
|
||||
colorWithAlpha: function (alpha) {
|
||||
var rgb = this.rgb;
|
||||
var m = MochiKit.Color;
|
||||
return m.Color.fromRGB(rgb.r, rgb.g, rgb.b, alpha);
|
||||
},
|
||||
|
||||
/** @id MochiKit.Color.Color.prototype.colorWithHue */
|
||||
colorWithHue: function (hue) {
|
||||
// get an HSL model, and set the new hue...
|
||||
var hsl = this.asHSL();
|
||||
hsl.h = hue;
|
||||
var m = MochiKit.Color;
|
||||
// convert back to RGB...
|
||||
return m.Color.fromHSL(hsl);
|
||||
},
|
||||
|
||||
/** @id MochiKit.Color.Color.prototype.colorWithSaturation */
|
||||
colorWithSaturation: function (saturation) {
|
||||
// get an HSL model, and set the new hue...
|
||||
var hsl = this.asHSL();
|
||||
hsl.s = saturation;
|
||||
var m = MochiKit.Color;
|
||||
// convert back to RGB...
|
||||
return m.Color.fromHSL(hsl);
|
||||
},
|
||||
|
||||
/** @id MochiKit.Color.Color.prototype.colorWithLightness */
|
||||
colorWithLightness: function (lightness) {
|
||||
// get an HSL model, and set the new hue...
|
||||
var hsl = this.asHSL();
|
||||
hsl.l = lightness;
|
||||
var m = MochiKit.Color;
|
||||
// convert back to RGB...
|
||||
return m.Color.fromHSL(hsl);
|
||||
},
|
||||
|
||||
/** @id MochiKit.Color.Color.prototype.darkerColorWithLevel */
|
||||
darkerColorWithLevel: function (level) {
|
||||
var hsl = this.asHSL();
|
||||
hsl.l = Math.max(hsl.l - level, 0);
|
||||
var m = MochiKit.Color;
|
||||
return m.Color.fromHSL(hsl);
|
||||
},
|
||||
|
||||
/** @id MochiKit.Color.Color.prototype.lighterColorWithLevel */
|
||||
lighterColorWithLevel: function (level) {
|
||||
var hsl = this.asHSL();
|
||||
hsl.l = Math.min(hsl.l + level, 1);
|
||||
var m = MochiKit.Color;
|
||||
return m.Color.fromHSL(hsl);
|
||||
},
|
||||
|
||||
/** @id MochiKit.Color.Color.prototype.blendedColor */
|
||||
blendedColor: function (other, /* optional */ fraction) {
|
||||
if (typeof(fraction) == 'undefined' || fraction === null) {
|
||||
fraction = 0.5;
|
||||
}
|
||||
var sf = 1.0 - fraction;
|
||||
var s = this.rgb;
|
||||
var d = other.rgb;
|
||||
var df = fraction;
|
||||
return MochiKit.Color.Color.fromRGB(
|
||||
(s.r * sf) + (d.r * df),
|
||||
(s.g * sf) + (d.g * df),
|
||||
(s.b * sf) + (d.b * df),
|
||||
(s.a * sf) + (d.a * df)
|
||||
);
|
||||
},
|
||||
|
||||
/** @id MochiKit.Color.Color.prototype.compareRGB */
|
||||
compareRGB: function (other) {
|
||||
var a = this.asRGB();
|
||||
var b = other.asRGB();
|
||||
return MochiKit.Base.compare(
|
||||
[a.r, a.g, a.b, a.a],
|
||||
[b.r, b.g, b.b, b.a]
|
||||
);
|
||||
},
|
||||
|
||||
/** @id MochiKit.Color.Color.prototype.isLight */
|
||||
isLight: function () {
|
||||
return this.asHSL().l > 0.5;
|
||||
},
|
||||
|
||||
/** @id MochiKit.Color.Color.prototype.isDark */
|
||||
isDark: function () {
|
||||
return (!this.isLight());
|
||||
},
|
||||
|
||||
/** @id MochiKit.Color.Color.prototype.toHSLString */
|
||||
toHSLString: function () {
|
||||
var c = this.asHSL();
|
||||
var ccc = MochiKit.Color.clampColorComponent;
|
||||
var rval = this._hslString;
|
||||
if (!rval) {
|
||||
var mid = (
|
||||
ccc(c.h, 360).toFixed(0)
|
||||
+ "," + ccc(c.s, 100).toPrecision(4) + "%"
|
||||
+ "," + ccc(c.l, 100).toPrecision(4) + "%"
|
||||
);
|
||||
var a = c.a;
|
||||
if (a >= 1) {
|
||||
a = 1;
|
||||
rval = "hsl(" + mid + ")";
|
||||
} else {
|
||||
if (a <= 0) {
|
||||
a = 0;
|
||||
}
|
||||
rval = "hsla(" + mid + "," + a + ")";
|
||||
}
|
||||
this._hslString = rval;
|
||||
}
|
||||
return rval;
|
||||
},
|
||||
|
||||
/** @id MochiKit.Color.Color.prototype.toRGBString */
|
||||
toRGBString: function () {
|
||||
var c = this.rgb;
|
||||
var ccc = MochiKit.Color.clampColorComponent;
|
||||
var rval = this._rgbString;
|
||||
if (!rval) {
|
||||
var mid = (
|
||||
ccc(c.r, 255).toFixed(0)
|
||||
+ "," + ccc(c.g, 255).toFixed(0)
|
||||
+ "," + ccc(c.b, 255).toFixed(0)
|
||||
);
|
||||
if (c.a != 1) {
|
||||
rval = "rgba(" + mid + "," + c.a + ")";
|
||||
} else {
|
||||
rval = "rgb(" + mid + ")";
|
||||
}
|
||||
this._rgbString = rval;
|
||||
}
|
||||
return rval;
|
||||
},
|
||||
|
||||
/** @id MochiKit.Color.Color.prototype.asRGB */
|
||||
asRGB: function () {
|
||||
return MochiKit.Base.clone(this.rgb);
|
||||
},
|
||||
|
||||
/** @id MochiKit.Color.Color.prototype.toHexString */
|
||||
toHexString: function () {
|
||||
var m = MochiKit.Color;
|
||||
var c = this.rgb;
|
||||
var ccc = MochiKit.Color.clampColorComponent;
|
||||
var rval = this._hexString;
|
||||
if (!rval) {
|
||||
rval = ("#" +
|
||||
m.toColorPart(ccc(c.r, 255)) +
|
||||
m.toColorPart(ccc(c.g, 255)) +
|
||||
m.toColorPart(ccc(c.b, 255))
|
||||
);
|
||||
this._hexString = rval;
|
||||
}
|
||||
return rval;
|
||||
},
|
||||
|
||||
/** @id MochiKit.Color.Color.prototype.asHSV */
|
||||
asHSV: function () {
|
||||
var hsv = this.hsv;
|
||||
var c = this.rgb;
|
||||
if (typeof(hsv) == 'undefined' || hsv === null) {
|
||||
hsv = MochiKit.Color.rgbToHSV(this.rgb);
|
||||
this.hsv = hsv;
|
||||
}
|
||||
return MochiKit.Base.clone(hsv);
|
||||
},
|
||||
|
||||
/** @id MochiKit.Color.Color.prototype.asHSL */
|
||||
asHSL: function () {
|
||||
var hsl = this.hsl;
|
||||
var c = this.rgb;
|
||||
if (typeof(hsl) == 'undefined' || hsl === null) {
|
||||
hsl = MochiKit.Color.rgbToHSL(this.rgb);
|
||||
this.hsl = hsl;
|
||||
}
|
||||
return MochiKit.Base.clone(hsl);
|
||||
},
|
||||
|
||||
/** @id MochiKit.Color.Color.prototype.toString */
|
||||
toString: function () {
|
||||
return this.toRGBString();
|
||||
},
|
||||
|
||||
/** @id MochiKit.Color.Color.prototype.repr */
|
||||
repr: function () {
|
||||
var c = this.rgb;
|
||||
var col = [c.r, c.g, c.b, c.a];
|
||||
return this.__class__.NAME + "(" + col.join(", ") + ")";
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// Constructor methods
|
||||
|
||||
MochiKit.Base.update(MochiKit.Color.Color, {
|
||||
/** @id MochiKit.Color.Color.fromRGB */
|
||||
fromRGB: function (red, green, blue, alpha) {
|
||||
// designated initializer
|
||||
var Color = MochiKit.Color.Color;
|
||||
if (arguments.length == 1) {
|
||||
var rgb = red;
|
||||
red = rgb.r;
|
||||
green = rgb.g;
|
||||
blue = rgb.b;
|
||||
if (typeof(rgb.a) == 'undefined') {
|
||||
alpha = undefined;
|
||||
} else {
|
||||
alpha = rgb.a;
|
||||
}
|
||||
}
|
||||
return new Color(red, green, blue, alpha);
|
||||
},
|
||||
|
||||
/** @id MochiKit.Color.Color.fromHSL */
|
||||
fromHSL: function (hue, saturation, lightness, alpha) {
|
||||
var m = MochiKit.Color;
|
||||
return m.Color.fromRGB(m.hslToRGB.apply(m, arguments));
|
||||
},
|
||||
|
||||
/** @id MochiKit.Color.Color.fromHSV */
|
||||
fromHSV: function (hue, saturation, value, alpha) {
|
||||
var m = MochiKit.Color;
|
||||
return m.Color.fromRGB(m.hsvToRGB.apply(m, arguments));
|
||||
},
|
||||
|
||||
/** @id MochiKit.Color.Color.fromName */
|
||||
fromName: function (name) {
|
||||
var Color = MochiKit.Color.Color;
|
||||
// Opera 9 seems to "quote" named colors(?!)
|
||||
if (name.charAt(0) == '"') {
|
||||
name = name.substr(1, name.length - 2);
|
||||
}
|
||||
var htmlColor = Color._namedColors[name.toLowerCase()];
|
||||
if (typeof(htmlColor) == 'string') {
|
||||
return Color.fromHexString(htmlColor);
|
||||
} else if (name == "transparent") {
|
||||
return Color.transparentColor();
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
/** @id MochiKit.Color.Color.fromString */
|
||||
fromString: function (colorString) {
|
||||
var self = MochiKit.Color.Color;
|
||||
var three = colorString.substr(0, 3);
|
||||
if (three == "rgb") {
|
||||
return self.fromRGBString(colorString);
|
||||
} else if (three == "hsl") {
|
||||
return self.fromHSLString(colorString);
|
||||
} else if (colorString.charAt(0) == "#") {
|
||||
return self.fromHexString(colorString);
|
||||
}
|
||||
return self.fromName(colorString);
|
||||
},
|
||||
|
||||
|
||||
/** @id MochiKit.Color.Color.fromHexString */
|
||||
fromHexString: function (hexCode) {
|
||||
if (hexCode.charAt(0) == '#') {
|
||||
hexCode = hexCode.substring(1);
|
||||
}
|
||||
var components = [];
|
||||
var i, hex;
|
||||
if (hexCode.length == 3) {
|
||||
for (i = 0; i < 3; i++) {
|
||||
hex = hexCode.substr(i, 1);
|
||||
components.push(parseInt(hex + hex, 16) / 255.0);
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < 6; i += 2) {
|
||||
hex = hexCode.substr(i, 2);
|
||||
components.push(parseInt(hex, 16) / 255.0);
|
||||
}
|
||||
}
|
||||
var Color = MochiKit.Color.Color;
|
||||
return Color.fromRGB.apply(Color, components);
|
||||
},
|
||||
|
||||
|
||||
_fromColorString: function (pre, method, scales, colorCode) {
|
||||
// parses either HSL or RGB
|
||||
if (colorCode.indexOf(pre) === 0) {
|
||||
colorCode = colorCode.substring(colorCode.indexOf("(", 3) + 1, colorCode.length - 1);
|
||||
}
|
||||
var colorChunks = colorCode.split(/\s*,\s*/);
|
||||
var colorFloats = [];
|
||||
for (var i = 0; i < colorChunks.length; i++) {
|
||||
var c = colorChunks[i];
|
||||
var val;
|
||||
var three = c.substring(c.length - 3);
|
||||
if (c.charAt(c.length - 1) == '%') {
|
||||
val = 0.01 * parseFloat(c.substring(0, c.length - 1));
|
||||
} else if (three == "deg") {
|
||||
val = parseFloat(c) / 360.0;
|
||||
} else if (three == "rad") {
|
||||
val = parseFloat(c) / (Math.PI * 2);
|
||||
} else {
|
||||
val = scales[i] * parseFloat(c);
|
||||
}
|
||||
colorFloats.push(val);
|
||||
}
|
||||
return this[method].apply(this, colorFloats);
|
||||
},
|
||||
|
||||
/** @id MochiKit.Color.Color.fromComputedStyle */
|
||||
fromComputedStyle: function (elem, style) {
|
||||
var d = MochiKit.DOM;
|
||||
var cls = MochiKit.Color.Color;
|
||||
for (elem = d.getElement(elem); elem; elem = elem.parentNode) {
|
||||
var actualColor = MochiKit.Style.getStyle.apply(d, arguments);
|
||||
if (!actualColor) {
|
||||
continue;
|
||||
}
|
||||
var color = cls.fromString(actualColor);
|
||||
if (!color) {
|
||||
break;
|
||||
}
|
||||
if (color.asRGB().a > 0) {
|
||||
return color;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
/** @id MochiKit.Color.Color.fromBackground */
|
||||
fromBackground: function (elem) {
|
||||
var cls = MochiKit.Color.Color;
|
||||
return cls.fromComputedStyle(
|
||||
elem, "backgroundColor", "background-color") || cls.whiteColor();
|
||||
},
|
||||
|
||||
/** @id MochiKit.Color.Color.fromText */
|
||||
fromText: function (elem) {
|
||||
var cls = MochiKit.Color.Color;
|
||||
return cls.fromComputedStyle(
|
||||
elem, "color", "color") || cls.blackColor();
|
||||
},
|
||||
|
||||
/** @id MochiKit.Color.Color.namedColors */
|
||||
namedColors: function () {
|
||||
return MochiKit.Base.clone(MochiKit.Color.Color._namedColors);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Module level functions
|
||||
|
||||
MochiKit.Base.update(MochiKit.Color, {
|
||||
/** @id MochiKit.Color.clampColorComponent */
|
||||
clampColorComponent: function (v, scale) {
|
||||
v *= scale;
|
||||
if (v < 0) {
|
||||
return 0;
|
||||
} else if (v > scale) {
|
||||
return scale;
|
||||
} else {
|
||||
return v;
|
||||
}
|
||||
},
|
||||
|
||||
_hslValue: function (n1, n2, hue) {
|
||||
if (hue > 6.0) {
|
||||
hue -= 6.0;
|
||||
} else if (hue < 0.0) {
|
||||
hue += 6.0;
|
||||
}
|
||||
var val;
|
||||
if (hue < 1.0) {
|
||||
val = n1 + (n2 - n1) * hue;
|
||||
} else if (hue < 3.0) {
|
||||
val = n2;
|
||||
} else if (hue < 4.0) {
|
||||
val = n1 + (n2 - n1) * (4.0 - hue);
|
||||
} else {
|
||||
val = n1;
|
||||
}
|
||||
return val;
|
||||
},
|
||||
|
||||
/** @id MochiKit.Color.hsvToRGB */
|
||||
hsvToRGB: function (hue, saturation, value, alpha) {
|
||||
if (arguments.length == 1) {
|
||||
var hsv = hue;
|
||||
hue = hsv.h;
|
||||
saturation = hsv.s;
|
||||
value = hsv.v;
|
||||
alpha = hsv.a;
|
||||
}
|
||||
var red;
|
||||
var green;
|
||||
var blue;
|
||||
if (saturation === 0) {
|
||||
red = value;
|
||||
green = value;
|
||||
blue = value;
|
||||
} else {
|
||||
var i = Math.floor(hue * 6);
|
||||
var f = (hue * 6) - i;
|
||||
var p = value * (1 - saturation);
|
||||
var q = value * (1 - (saturation * f));
|
||||
var t = value * (1 - (saturation * (1 - f)));
|
||||
switch (i) {
|
||||
case 1: red = q; green = value; blue = p; break;
|
||||
case 2: red = p; green = value; blue = t; break;
|
||||
case 3: red = p; green = q; blue = value; break;
|
||||
case 4: red = t; green = p; blue = value; break;
|
||||
case 5: red = value; green = p; blue = q; break;
|
||||
case 6: // fall through
|
||||
case 0: red = value; green = t; blue = p; break;
|
||||
}
|
||||
}
|
||||
return {
|
||||
r: red,
|
||||
g: green,
|
||||
b: blue,
|
||||
a: alpha
|
||||
};
|
||||
},
|
||||
|
||||
/** @id MochiKit.Color.hslToRGB */
|
||||
hslToRGB: function (hue, saturation, lightness, alpha) {
|
||||
if (arguments.length == 1) {
|
||||
var hsl = hue;
|
||||
hue = hsl.h;
|
||||
saturation = hsl.s;
|
||||
lightness = hsl.l;
|
||||
alpha = hsl.a;
|
||||
}
|
||||
var red;
|
||||
var green;
|
||||
var blue;
|
||||
if (saturation === 0) {
|
||||
red = lightness;
|
||||
green = lightness;
|
||||
blue = lightness;
|
||||
} else {
|
||||
var m2;
|
||||
if (lightness <= 0.5) {
|
||||
m2 = lightness * (1.0 + saturation);
|
||||
} else {
|
||||
m2 = lightness + saturation - (lightness * saturation);
|
||||
}
|
||||
var m1 = (2.0 * lightness) - m2;
|
||||
var f = MochiKit.Color._hslValue;
|
||||
var h6 = hue * 6.0;
|
||||
red = f(m1, m2, h6 + 2);
|
||||
green = f(m1, m2, h6);
|
||||
blue = f(m1, m2, h6 - 2);
|
||||
}
|
||||
return {
|
||||
r: red,
|
||||
g: green,
|
||||
b: blue,
|
||||
a: alpha
|
||||
};
|
||||
},
|
||||
|
||||
/** @id MochiKit.Color.rgbToHSV */
|
||||
rgbToHSV: function (red, green, blue, alpha) {
|
||||
if (arguments.length == 1) {
|
||||
var rgb = red;
|
||||
red = rgb.r;
|
||||
green = rgb.g;
|
||||
blue = rgb.b;
|
||||
alpha = rgb.a;
|
||||
}
|
||||
var max = Math.max(Math.max(red, green), blue);
|
||||
var min = Math.min(Math.min(red, green), blue);
|
||||
var hue;
|
||||
var saturation;
|
||||
var value = max;
|
||||
if (min == max) {
|
||||
hue = 0;
|
||||
saturation = 0;
|
||||
} else {
|
||||
var delta = (max - min);
|
||||
saturation = delta / max;
|
||||
|
||||
if (red == max) {
|
||||
hue = (green - blue) / delta;
|
||||
} else if (green == max) {
|
||||
hue = 2 + ((blue - red) / delta);
|
||||
} else {
|
||||
hue = 4 + ((red - green) / delta);
|
||||
}
|
||||
hue /= 6;
|
||||
if (hue < 0) {
|
||||
hue += 1;
|
||||
}
|
||||
if (hue > 1) {
|
||||
hue -= 1;
|
||||
}
|
||||
}
|
||||
return {
|
||||
h: hue,
|
||||
s: saturation,
|
||||
v: value,
|
||||
a: alpha
|
||||
};
|
||||
},
|
||||
|
||||
/** @id MochiKit.Color.rgbToHSL */
|
||||
rgbToHSL: function (red, green, blue, alpha) {
|
||||
if (arguments.length == 1) {
|
||||
var rgb = red;
|
||||
red = rgb.r;
|
||||
green = rgb.g;
|
||||
blue = rgb.b;
|
||||
alpha = rgb.a;
|
||||
}
|
||||
var max = Math.max(red, Math.max(green, blue));
|
||||
var min = Math.min(red, Math.min(green, blue));
|
||||
var hue;
|
||||
var saturation;
|
||||
var lightness = (max + min) / 2.0;
|
||||
var delta = max - min;
|
||||
if (delta === 0) {
|
||||
hue = 0;
|
||||
saturation = 0;
|
||||
} else {
|
||||
if (lightness <= 0.5) {
|
||||
saturation = delta / (max + min);
|
||||
} else {
|
||||
saturation = delta / (2 - max - min);
|
||||
}
|
||||
if (red == max) {
|
||||
hue = (green - blue) / delta;
|
||||
} else if (green == max) {
|
||||
hue = 2 + ((blue - red) / delta);
|
||||
} else {
|
||||
hue = 4 + ((red - green) / delta);
|
||||
}
|
||||
hue /= 6;
|
||||
if (hue < 0) {
|
||||
hue += 1;
|
||||
}
|
||||
if (hue > 1) {
|
||||
hue -= 1;
|
||||
}
|
||||
|
||||
}
|
||||
return {
|
||||
h: hue,
|
||||
s: saturation,
|
||||
l: lightness,
|
||||
a: alpha
|
||||
};
|
||||
},
|
||||
|
||||
/** @id MochiKit.Color.toColorPart */
|
||||
toColorPart: function (num) {
|
||||
num = Math.round(num);
|
||||
var digits = num.toString(16);
|
||||
if (num < 16) {
|
||||
return '0' + digits;
|
||||
}
|
||||
return digits;
|
||||
},
|
||||
|
||||
__new__: function () {
|
||||
var m = MochiKit.Base;
|
||||
/** @id MochiKit.Color.Color.fromRGBString */
|
||||
this.Color.fromRGBString = m.bind(
|
||||
this.Color._fromColorString, this.Color, "rgb", "fromRGB",
|
||||
[1.0/255.0, 1.0/255.0, 1.0/255.0, 1]
|
||||
);
|
||||
/** @id MochiKit.Color.Color.fromHSLString */
|
||||
this.Color.fromHSLString = m.bind(
|
||||
this.Color._fromColorString, this.Color, "hsl", "fromHSL",
|
||||
[1.0/360.0, 0.01, 0.01, 1]
|
||||
);
|
||||
|
||||
var third = 1.0 / 3.0;
|
||||
/** @id MochiKit.Color.colors */
|
||||
var colors = {
|
||||
// NSColor colors plus transparent
|
||||
/** @id MochiKit.Color.blackColor */
|
||||
black: [0, 0, 0],
|
||||
/** @id MochiKit.Color.blueColor */
|
||||
blue: [0, 0, 1],
|
||||
/** @id MochiKit.Color.brownColor */
|
||||
brown: [0.6, 0.4, 0.2],
|
||||
/** @id MochiKit.Color.cyanColor */
|
||||
cyan: [0, 1, 1],
|
||||
/** @id MochiKit.Color.darkGrayColor */
|
||||
darkGray: [third, third, third],
|
||||
/** @id MochiKit.Color.grayColor */
|
||||
gray: [0.5, 0.5, 0.5],
|
||||
/** @id MochiKit.Color.greenColor */
|
||||
green: [0, 1, 0],
|
||||
/** @id MochiKit.Color.lightGrayColor */
|
||||
lightGray: [2 * third, 2 * third, 2 * third],
|
||||
/** @id MochiKit.Color.magentaColor */
|
||||
magenta: [1, 0, 1],
|
||||
/** @id MochiKit.Color.orangeColor */
|
||||
orange: [1, 0.5, 0],
|
||||
/** @id MochiKit.Color.purpleColor */
|
||||
purple: [0.5, 0, 0.5],
|
||||
/** @id MochiKit.Color.redColor */
|
||||
red: [1, 0, 0],
|
||||
/** @id MochiKit.Color.transparentColor */
|
||||
transparent: [0, 0, 0, 0],
|
||||
/** @id MochiKit.Color.whiteColor */
|
||||
white: [1, 1, 1],
|
||||
/** @id MochiKit.Color.yellowColor */
|
||||
yellow: [1, 1, 0]
|
||||
};
|
||||
|
||||
for (var k in colors) {
|
||||
var name = k + "Color";
|
||||
var value = this.Color.fromRGB.apply(this.Color, colors[k]);
|
||||
this.Color[name] = m.partial(m.operator.identity, value);
|
||||
}
|
||||
|
||||
var isColor = function () {
|
||||
for (var i = 0; i < arguments.length; i++) {
|
||||
if (!(arguments[i] instanceof MochiKit.Color.Color)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
var compareColor = function (a, b) {
|
||||
return a.compareRGB(b);
|
||||
};
|
||||
|
||||
m.nameFunctions(this);
|
||||
|
||||
m.registerComparator(this.Color.NAME, isColor, compareColor);
|
||||
}
|
||||
});
|
||||
|
||||
MochiKit.Color.__new__();
|
||||
|
||||
// Full table of css3 X11 colors <http://www.w3.org/TR/css3-color/#X11COLORS>
|
||||
|
||||
MochiKit.Color.Color._namedColors = {
|
||||
aliceblue: "#f0f8ff",
|
||||
antiquewhite: "#faebd7",
|
||||
aqua: "#00ffff",
|
||||
aquamarine: "#7fffd4",
|
||||
azure: "#f0ffff",
|
||||
beige: "#f5f5dc",
|
||||
bisque: "#ffe4c4",
|
||||
black: "#000000",
|
||||
blanchedalmond: "#ffebcd",
|
||||
blue: "#0000ff",
|
||||
blueviolet: "#8a2be2",
|
||||
brown: "#a52a2a",
|
||||
burlywood: "#deb887",
|
||||
cadetblue: "#5f9ea0",
|
||||
chartreuse: "#7fff00",
|
||||
chocolate: "#d2691e",
|
||||
coral: "#ff7f50",
|
||||
cornflowerblue: "#6495ed",
|
||||
cornsilk: "#fff8dc",
|
||||
crimson: "#dc143c",
|
||||
cyan: "#00ffff",
|
||||
darkblue: "#00008b",
|
||||
darkcyan: "#008b8b",
|
||||
darkgoldenrod: "#b8860b",
|
||||
darkgray: "#a9a9a9",
|
||||
darkgreen: "#006400",
|
||||
darkgrey: "#a9a9a9",
|
||||
darkkhaki: "#bdb76b",
|
||||
darkmagenta: "#8b008b",
|
||||
darkolivegreen: "#556b2f",
|
||||
darkorange: "#ff8c00",
|
||||
darkorchid: "#9932cc",
|
||||
darkred: "#8b0000",
|
||||
darksalmon: "#e9967a",
|
||||
darkseagreen: "#8fbc8f",
|
||||
darkslateblue: "#483d8b",
|
||||
darkslategray: "#2f4f4f",
|
||||
darkslategrey: "#2f4f4f",
|
||||
darkturquoise: "#00ced1",
|
||||
darkviolet: "#9400d3",
|
||||
deeppink: "#ff1493",
|
||||
deepskyblue: "#00bfff",
|
||||
dimgray: "#696969",
|
||||
dimgrey: "#696969",
|
||||
dodgerblue: "#1e90ff",
|
||||
firebrick: "#b22222",
|
||||
floralwhite: "#fffaf0",
|
||||
forestgreen: "#228b22",
|
||||
fuchsia: "#ff00ff",
|
||||
gainsboro: "#dcdcdc",
|
||||
ghostwhite: "#f8f8ff",
|
||||
gold: "#ffd700",
|
||||
goldenrod: "#daa520",
|
||||
gray: "#808080",
|
||||
green: "#008000",
|
||||
greenyellow: "#adff2f",
|
||||
grey: "#808080",
|
||||
honeydew: "#f0fff0",
|
||||
hotpink: "#ff69b4",
|
||||
indianred: "#cd5c5c",
|
||||
indigo: "#4b0082",
|
||||
ivory: "#fffff0",
|
||||
khaki: "#f0e68c",
|
||||
lavender: "#e6e6fa",
|
||||
lavenderblush: "#fff0f5",
|
||||
lawngreen: "#7cfc00",
|
||||
lemonchiffon: "#fffacd",
|
||||
lightblue: "#add8e6",
|
||||
lightcoral: "#f08080",
|
||||
lightcyan: "#e0ffff",
|
||||
lightgoldenrodyellow: "#fafad2",
|
||||
lightgray: "#d3d3d3",
|
||||
lightgreen: "#90ee90",
|
||||
lightgrey: "#d3d3d3",
|
||||
lightpink: "#ffb6c1",
|
||||
lightsalmon: "#ffa07a",
|
||||
lightseagreen: "#20b2aa",
|
||||
lightskyblue: "#87cefa",
|
||||
lightslategray: "#778899",
|
||||
lightslategrey: "#778899",
|
||||
lightsteelblue: "#b0c4de",
|
||||
lightyellow: "#ffffe0",
|
||||
lime: "#00ff00",
|
||||
limegreen: "#32cd32",
|
||||
linen: "#faf0e6",
|
||||
magenta: "#ff00ff",
|
||||
maroon: "#800000",
|
||||
mediumaquamarine: "#66cdaa",
|
||||
mediumblue: "#0000cd",
|
||||
mediumorchid: "#ba55d3",
|
||||
mediumpurple: "#9370db",
|
||||
mediumseagreen: "#3cb371",
|
||||
mediumslateblue: "#7b68ee",
|
||||
mediumspringgreen: "#00fa9a",
|
||||
mediumturquoise: "#48d1cc",
|
||||
mediumvioletred: "#c71585",
|
||||
midnightblue: "#191970",
|
||||
mintcream: "#f5fffa",
|
||||
mistyrose: "#ffe4e1",
|
||||
moccasin: "#ffe4b5",
|
||||
navajowhite: "#ffdead",
|
||||
navy: "#000080",
|
||||
oldlace: "#fdf5e6",
|
||||
olive: "#808000",
|
||||
olivedrab: "#6b8e23",
|
||||
orange: "#ffa500",
|
||||
orangered: "#ff4500",
|
||||
orchid: "#da70d6",
|
||||
palegoldenrod: "#eee8aa",
|
||||
palegreen: "#98fb98",
|
||||
paleturquoise: "#afeeee",
|
||||
palevioletred: "#db7093",
|
||||
papayawhip: "#ffefd5",
|
||||
peachpuff: "#ffdab9",
|
||||
peru: "#cd853f",
|
||||
pink: "#ffc0cb",
|
||||
plum: "#dda0dd",
|
||||
powderblue: "#b0e0e6",
|
||||
purple: "#800080",
|
||||
red: "#ff0000",
|
||||
rosybrown: "#bc8f8f",
|
||||
royalblue: "#4169e1",
|
||||
saddlebrown: "#8b4513",
|
||||
salmon: "#fa8072",
|
||||
sandybrown: "#f4a460",
|
||||
seagreen: "#2e8b57",
|
||||
seashell: "#fff5ee",
|
||||
sienna: "#a0522d",
|
||||
silver: "#c0c0c0",
|
||||
skyblue: "#87ceeb",
|
||||
slateblue: "#6a5acd",
|
||||
slategray: "#708090",
|
||||
slategrey: "#708090",
|
||||
snow: "#fffafa",
|
||||
springgreen: "#00ff7f",
|
||||
steelblue: "#4682b4",
|
||||
tan: "#d2b48c",
|
||||
teal: "#008080",
|
||||
thistle: "#d8bfd8",
|
||||
tomato: "#ff6347",
|
||||
turquoise: "#40e0d0",
|
||||
violet: "#ee82ee",
|
||||
wheat: "#f5deb3",
|
||||
white: "#ffffff",
|
||||
whitesmoke: "#f5f5f5",
|
||||
yellow: "#ffff00",
|
||||
yellowgreen: "#9acd32"
|
||||
};
|
||||
|
||||
MochiKit.Base._exportSymbols(this, MochiKit.Color);
|
||||
1202
frontend/delta/js/MochiKit/DOM.js
Normal file
1202
frontend/delta/js/MochiKit/DOM.js
Normal file
File diff suppressed because it is too large
Load Diff
199
frontend/delta/js/MochiKit/DateTime.js
Normal file
199
frontend/delta/js/MochiKit/DateTime.js
Normal file
@@ -0,0 +1,199 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
/***
|
||||
|
||||
MochiKit.DateTime 1.5
|
||||
|
||||
See <http://mochikit.com/> for documentation, downloads, license, etc.
|
||||
|
||||
(c) 2005 Bob Ippolito. All rights Reserved.
|
||||
|
||||
***/
|
||||
|
||||
MochiKit.Base.module(MochiKit, 'DateTime', '1.5', ['Base']);
|
||||
|
||||
/** @id MochiKit.DateTime.isoDate */
|
||||
MochiKit.DateTime.isoDate = function (str) {
|
||||
str = str + "";
|
||||
if (typeof(str) != "string" || str.length === 0) {
|
||||
return null;
|
||||
}
|
||||
var iso = str.split('-');
|
||||
if (iso.length === 0) {
|
||||
return null;
|
||||
}
|
||||
var date = new Date(parseInt(iso[0], 10), parseInt(iso[1], 10) - 1, parseInt(iso[2], 10));
|
||||
date.setFullYear(iso[0]);
|
||||
date.setMonth(iso[1] - 1);
|
||||
date.setDate(iso[2]);
|
||||
return date;
|
||||
};
|
||||
|
||||
MochiKit.DateTime._isoRegexp = /(\d{4,})(?:-(\d{1,2})(?:-(\d{1,2})(?:[T ](\d{1,2}):(\d{1,2})(?::(\d{1,2})(?:\.(\d+))?)?(?:(Z)|([+-])(\d{1,2})(?::(\d{1,2}))?)?)?)?)?/;
|
||||
|
||||
/** @id MochiKit.DateTime.isoTimestamp */
|
||||
MochiKit.DateTime.isoTimestamp = function (str) {
|
||||
str = str + "";
|
||||
if (typeof(str) != "string" || str.length === 0) {
|
||||
return null;
|
||||
}
|
||||
var res = str.match(MochiKit.DateTime._isoRegexp);
|
||||
if (typeof(res) == "undefined" || res === null) {
|
||||
return null;
|
||||
}
|
||||
var year, month, day, hour, min, sec, msec;
|
||||
year = parseInt(res[1], 10);
|
||||
if (typeof(res[2]) == "undefined" || res[2] === '') {
|
||||
return new Date(year);
|
||||
}
|
||||
month = parseInt(res[2], 10) - 1;
|
||||
day = parseInt(res[3], 10);
|
||||
if (typeof(res[4]) == "undefined" || res[4] === '') {
|
||||
return new Date(year, month, day);
|
||||
}
|
||||
hour = parseInt(res[4], 10);
|
||||
min = parseInt(res[5], 10);
|
||||
sec = (typeof(res[6]) != "undefined" && res[6] !== '') ? parseInt(res[6], 10) : 0;
|
||||
if (typeof(res[7]) != "undefined" && res[7] !== '') {
|
||||
msec = Math.round(1000.0 * parseFloat("0." + res[7]));
|
||||
} else {
|
||||
msec = 0;
|
||||
}
|
||||
if ((typeof(res[8]) == "undefined" || res[8] === '') && (typeof(res[9]) == "undefined" || res[9] === '')) {
|
||||
return new Date(year, month, day, hour, min, sec, msec);
|
||||
}
|
||||
var ofs;
|
||||
if (typeof(res[9]) != "undefined" && res[9] !== '') {
|
||||
ofs = parseInt(res[10], 10) * 3600000;
|
||||
if (typeof(res[11]) != "undefined" && res[11] !== '') {
|
||||
ofs += parseInt(res[11], 10) * 60000;
|
||||
}
|
||||
if (res[9] == "-") {
|
||||
ofs = -ofs;
|
||||
}
|
||||
} else {
|
||||
ofs = 0;
|
||||
}
|
||||
return new Date(Date.UTC(year, month, day, hour, min, sec, msec) - ofs);
|
||||
};
|
||||
|
||||
/** @id MochiKit.DateTime.toISOTime */
|
||||
MochiKit.DateTime.toISOTime = function (date, realISO/* = false */) {
|
||||
if (typeof(date) == "undefined" || date === null) {
|
||||
return null;
|
||||
}
|
||||
var _padTwo = MochiKit.DateTime._padTwo;
|
||||
if (realISO) {
|
||||
// adjust date for UTC timezone
|
||||
date = new Date(date.getTime() + (date.getTimezoneOffset() * 60000));
|
||||
}
|
||||
var lst = [
|
||||
(realISO ? _padTwo(date.getHours()) : date.getHours()),
|
||||
_padTwo(date.getMinutes()),
|
||||
_padTwo(date.getSeconds())
|
||||
];
|
||||
return lst.join(":") + (realISO ? "Z" : "");
|
||||
};
|
||||
|
||||
/** @id MochiKit.DateTime.toISOTimeStamp */
|
||||
MochiKit.DateTime.toISOTimestamp = function (date, realISO/* = false*/) {
|
||||
if (typeof(date) == "undefined" || date === null) {
|
||||
return null;
|
||||
}
|
||||
var time = MochiKit.DateTime.toISOTime(date, realISO);
|
||||
var sep = realISO ? "T" : " ";
|
||||
if (realISO) {
|
||||
// adjust date for UTC timezone
|
||||
date = new Date(date.getTime() + (date.getTimezoneOffset() * 60000));
|
||||
}
|
||||
return MochiKit.DateTime.toISODate(date) + sep + time;
|
||||
};
|
||||
|
||||
/** @id MochiKit.DateTime.toISODate */
|
||||
MochiKit.DateTime.toISODate = function (date) {
|
||||
if (typeof(date) == "undefined" || date === null) {
|
||||
return null;
|
||||
}
|
||||
var _padTwo = MochiKit.DateTime._padTwo;
|
||||
var _padFour = MochiKit.DateTime._padFour;
|
||||
return [
|
||||
_padFour(date.getFullYear()),
|
||||
_padTwo(date.getMonth() + 1),
|
||||
_padTwo(date.getDate())
|
||||
].join("-");
|
||||
};
|
||||
|
||||
/** @id MochiKit.DateTime.americanDate */
|
||||
MochiKit.DateTime.americanDate = function (d) {
|
||||
d = d + "";
|
||||
if (typeof(d) != "string" || d.length === 0) {
|
||||
return null;
|
||||
}
|
||||
var a = d.split('/');
|
||||
return new Date(a[2], a[0] - 1, a[1]);
|
||||
};
|
||||
|
||||
MochiKit.DateTime._padTwo = function (n) {
|
||||
return (n > 9) ? n : "0" + n;
|
||||
};
|
||||
|
||||
MochiKit.DateTime._padFour = function(n) {
|
||||
switch(n.toString().length) {
|
||||
case 1: return "000" + n; break;
|
||||
case 2: return "00" + n; break;
|
||||
case 3: return "0" + n; break;
|
||||
case 4:
|
||||
default:
|
||||
return n;
|
||||
}
|
||||
};
|
||||
|
||||
/** @id MochiKit.DateTime.toPaddedAmericanDate */
|
||||
MochiKit.DateTime.toPaddedAmericanDate = function (d) {
|
||||
if (typeof(d) == "undefined" || d === null) {
|
||||
return null;
|
||||
}
|
||||
var _padTwo = MochiKit.DateTime._padTwo;
|
||||
return [
|
||||
_padTwo(d.getMonth() + 1),
|
||||
_padTwo(d.getDate()),
|
||||
d.getFullYear()
|
||||
].join('/');
|
||||
};
|
||||
|
||||
/** @id MochiKit.DateTime.toAmericanDate */
|
||||
MochiKit.DateTime.toAmericanDate = function (d) {
|
||||
if (typeof(d) == "undefined" || d === null) {
|
||||
return null;
|
||||
}
|
||||
return [d.getMonth() + 1, d.getDate(), d.getFullYear()].join('/');
|
||||
};
|
||||
|
||||
MochiKit.DateTime.__new__ = function () {
|
||||
MochiKit.Base.nameFunctions(this);
|
||||
};
|
||||
|
||||
MochiKit.DateTime.__new__();
|
||||
|
||||
MochiKit.Base._exportSymbols(this, MochiKit.DateTime);
|
||||
789
frontend/delta/js/MochiKit/DragAndDrop.js
Normal file
789
frontend/delta/js/MochiKit/DragAndDrop.js
Normal file
@@ -0,0 +1,789 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
/***
|
||||
MochiKit.DragAndDrop 1.5
|
||||
|
||||
See <http://mochikit.com/> for documentation, downloads, license, etc.
|
||||
|
||||
Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
|
||||
Mochi-ized By Thomas Herve (_firstname_@nimail.org)
|
||||
|
||||
***/
|
||||
|
||||
MochiKit.Base.module(MochiKit, 'DragAndDrop', '1.5', ['Base', 'Iter', 'DOM', 'Signal', 'Visual', 'Position']);
|
||||
|
||||
MochiKit.DragAndDrop.Droppables = {
|
||||
/***
|
||||
|
||||
Manage all droppables. Shouldn't be used, use the Droppable object instead.
|
||||
|
||||
***/
|
||||
drops: [],
|
||||
|
||||
remove: function (element) {
|
||||
this.drops = MochiKit.Base.filter(function (d) {
|
||||
return d.element != MochiKit.DOM.getElement(element);
|
||||
}, this.drops);
|
||||
},
|
||||
|
||||
register: function (drop) {
|
||||
this.drops.push(drop);
|
||||
},
|
||||
|
||||
unregister: function (drop) {
|
||||
this.drops = MochiKit.Base.filter(function (d) {
|
||||
return d != drop;
|
||||
}, this.drops);
|
||||
},
|
||||
|
||||
prepare: function (element) {
|
||||
MochiKit.Base.map(function (drop) {
|
||||
if (drop.isAccepted(element)) {
|
||||
if (drop.options.activeclass) {
|
||||
MochiKit.DOM.addElementClass(drop.element,
|
||||
drop.options.activeclass);
|
||||
}
|
||||
drop.options.onactive(drop.element, element);
|
||||
}
|
||||
}, this.drops);
|
||||
},
|
||||
|
||||
findDeepestChild: function (drops) {
|
||||
var deepest = drops[0];
|
||||
|
||||
for (var i = 1; i < drops.length; ++i) {
|
||||
if (MochiKit.DOM.isChildNode(drops[i].element, deepest.element)) {
|
||||
deepest = drops[i];
|
||||
}
|
||||
}
|
||||
return deepest;
|
||||
},
|
||||
|
||||
show: function (point, element) {
|
||||
if (!this.drops.length) {
|
||||
return;
|
||||
}
|
||||
var affected = [];
|
||||
|
||||
if (this.last_active) {
|
||||
this.last_active.deactivate();
|
||||
}
|
||||
MochiKit.Iter.forEach(this.drops, function (drop) {
|
||||
if (drop.isAffected(point, element)) {
|
||||
affected.push(drop);
|
||||
}
|
||||
});
|
||||
if (affected.length > 0) {
|
||||
var drop = this.findDeepestChild(affected);
|
||||
MochiKit.Position.within(drop.element, point.page.x, point.page.y);
|
||||
drop.options.onhover(element, drop.element,
|
||||
MochiKit.Position.overlap(drop.options.overlap, drop.element));
|
||||
drop.activate();
|
||||
}
|
||||
},
|
||||
|
||||
fire: function (event, element) {
|
||||
if (!this.last_active) {
|
||||
return;
|
||||
}
|
||||
MochiKit.Position.prepare();
|
||||
|
||||
if (this.last_active.isAffected(event.mouse(), element)) {
|
||||
this.last_active.options.ondrop(element,
|
||||
this.last_active.element, event);
|
||||
}
|
||||
},
|
||||
|
||||
reset: function (element) {
|
||||
MochiKit.Base.map(function (drop) {
|
||||
if (drop.options.activeclass) {
|
||||
MochiKit.DOM.removeElementClass(drop.element,
|
||||
drop.options.activeclass);
|
||||
}
|
||||
drop.options.ondesactive(drop.element, element);
|
||||
}, this.drops);
|
||||
if (this.last_active) {
|
||||
this.last_active.deactivate();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/** @id MochiKit.DragAndDrop.Droppable */
|
||||
MochiKit.DragAndDrop.Droppable = function (element, options) {
|
||||
var cls = arguments.callee;
|
||||
if (!(this instanceof cls)) {
|
||||
return new cls(element, options);
|
||||
}
|
||||
this.__init__(element, options);
|
||||
};
|
||||
|
||||
MochiKit.DragAndDrop.Droppable.prototype = {
|
||||
/***
|
||||
|
||||
A droppable object. Simple use is to create giving an element:
|
||||
|
||||
new MochiKit.DragAndDrop.Droppable('myelement');
|
||||
|
||||
Generally you'll want to define the 'ondrop' function and maybe the
|
||||
'accept' option to filter draggables.
|
||||
|
||||
***/
|
||||
__class__: MochiKit.DragAndDrop.Droppable,
|
||||
|
||||
__init__: function (element, /* optional */options) {
|
||||
var d = MochiKit.DOM;
|
||||
var b = MochiKit.Base;
|
||||
this.element = d.getElement(element);
|
||||
this.options = b.update({
|
||||
|
||||
/** @id MochiKit.DragAndDrop.greedy */
|
||||
greedy: true,
|
||||
|
||||
/** @id MochiKit.DragAndDrop.hoverclass */
|
||||
hoverclass: null,
|
||||
|
||||
/** @id MochiKit.DragAndDrop.activeclass */
|
||||
activeclass: null,
|
||||
|
||||
/** @id MochiKit.DragAndDrop.hoverfunc */
|
||||
hoverfunc: b.noop,
|
||||
|
||||
/** @id MochiKit.DragAndDrop.accept */
|
||||
accept: null,
|
||||
|
||||
/** @id MochiKit.DragAndDrop.onactive */
|
||||
onactive: b.noop,
|
||||
|
||||
/** @id MochiKit.DragAndDrop.ondesactive */
|
||||
ondesactive: b.noop,
|
||||
|
||||
/** @id MochiKit.DragAndDrop.onhover */
|
||||
onhover: b.noop,
|
||||
|
||||
/** @id MochiKit.DragAndDrop.ondrop */
|
||||
ondrop: b.noop,
|
||||
|
||||
/** @id MochiKit.DragAndDrop.containment */
|
||||
containment: [],
|
||||
tree: false
|
||||
}, options);
|
||||
|
||||
// cache containers
|
||||
this.options._containers = [];
|
||||
b.map(MochiKit.Base.bind(function (c) {
|
||||
this.options._containers.push(d.getElement(c));
|
||||
}, this), this.options.containment);
|
||||
|
||||
MochiKit.Style.makePositioned(this.element); // fix IE
|
||||
|
||||
MochiKit.DragAndDrop.Droppables.register(this);
|
||||
},
|
||||
|
||||
/** @id MochiKit.DragAndDrop.isContained */
|
||||
isContained: function (element) {
|
||||
if (this.options._containers.length) {
|
||||
var containmentNode;
|
||||
if (this.options.tree) {
|
||||
containmentNode = element.treeNode;
|
||||
} else {
|
||||
containmentNode = element.parentNode;
|
||||
}
|
||||
return MochiKit.Iter.some(this.options._containers, function (c) {
|
||||
return containmentNode == c;
|
||||
});
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
},
|
||||
|
||||
/** @id MochiKit.DragAndDrop.isAccepted */
|
||||
isAccepted: function (element) {
|
||||
return ((!this.options.accept) || MochiKit.Iter.some(
|
||||
this.options.accept, function (c) {
|
||||
return MochiKit.DOM.hasElementClass(element, c);
|
||||
}));
|
||||
},
|
||||
|
||||
/** @id MochiKit.DragAndDrop.isAffected */
|
||||
isAffected: function (point, element) {
|
||||
return ((this.element != element) &&
|
||||
this.isContained(element) &&
|
||||
this.isAccepted(element) &&
|
||||
MochiKit.Position.within(this.element, point.page.x,
|
||||
point.page.y));
|
||||
},
|
||||
|
||||
/** @id MochiKit.DragAndDrop.deactivate */
|
||||
deactivate: function () {
|
||||
/***
|
||||
|
||||
A droppable is deactivate when a draggable has been over it and left.
|
||||
|
||||
***/
|
||||
if (this.options.hoverclass) {
|
||||
MochiKit.DOM.removeElementClass(this.element,
|
||||
this.options.hoverclass);
|
||||
}
|
||||
this.options.hoverfunc(this.element, false);
|
||||
MochiKit.DragAndDrop.Droppables.last_active = null;
|
||||
},
|
||||
|
||||
/** @id MochiKit.DragAndDrop.activate */
|
||||
activate: function () {
|
||||
/***
|
||||
|
||||
A droppable is active when a draggable is over it.
|
||||
|
||||
***/
|
||||
if (this.options.hoverclass) {
|
||||
MochiKit.DOM.addElementClass(this.element, this.options.hoverclass);
|
||||
}
|
||||
this.options.hoverfunc(this.element, true);
|
||||
MochiKit.DragAndDrop.Droppables.last_active = this;
|
||||
},
|
||||
|
||||
/** @id MochiKit.DragAndDrop.destroy */
|
||||
destroy: function () {
|
||||
/***
|
||||
|
||||
Delete this droppable.
|
||||
|
||||
***/
|
||||
MochiKit.DragAndDrop.Droppables.unregister(this);
|
||||
},
|
||||
|
||||
/** @id MochiKit.DragAndDrop.repr */
|
||||
repr: function () {
|
||||
return '[' + this.__class__.NAME + ", options:" + MochiKit.Base.repr(this.options) + "]";
|
||||
}
|
||||
};
|
||||
|
||||
MochiKit.DragAndDrop.Draggables = {
|
||||
/***
|
||||
|
||||
Manage draggables elements. Not intended to direct use.
|
||||
|
||||
***/
|
||||
drags: [],
|
||||
|
||||
register: function (draggable) {
|
||||
if (this.drags.length === 0) {
|
||||
var conn = MochiKit.Signal.connect;
|
||||
this.eventMouseUp = conn(document, 'onmouseup', this, this.endDrag);
|
||||
this.eventMouseMove = conn(document, 'onmousemove', this,
|
||||
this.updateDrag);
|
||||
this.eventKeypress = conn(document, 'onkeypress', this,
|
||||
this.keyPress);
|
||||
}
|
||||
this.drags.push(draggable);
|
||||
},
|
||||
|
||||
unregister: function (draggable) {
|
||||
this.drags = MochiKit.Base.filter(function (d) {
|
||||
return d != draggable;
|
||||
}, this.drags);
|
||||
if (this.drags.length === 0) {
|
||||
var disc = MochiKit.Signal.disconnect;
|
||||
disc(this.eventMouseUp);
|
||||
disc(this.eventMouseMove);
|
||||
disc(this.eventKeypress);
|
||||
}
|
||||
},
|
||||
|
||||
activate: function (draggable) {
|
||||
// allows keypress events if window is not currently focused
|
||||
// fails for Safari
|
||||
window.focus();
|
||||
this.activeDraggable = draggable;
|
||||
},
|
||||
|
||||
deactivate: function () {
|
||||
this.activeDraggable = null;
|
||||
},
|
||||
|
||||
updateDrag: function (event) {
|
||||
if (!this.activeDraggable) {
|
||||
return;
|
||||
}
|
||||
var pointer = event.mouse();
|
||||
// Mozilla-based browsers fire successive mousemove events with
|
||||
// the same coordinates, prevent needless redrawing (moz bug?)
|
||||
if (this._lastPointer &&
|
||||
this._lastPointer.page.x == pointer.page.x &&
|
||||
this._lastPointer.page.y == pointer.page.y) {
|
||||
return;
|
||||
}
|
||||
this._lastPointer = pointer;
|
||||
this.activeDraggable.updateDrag(event, pointer);
|
||||
},
|
||||
|
||||
endDrag: function (event) {
|
||||
if (!this.activeDraggable) {
|
||||
return;
|
||||
}
|
||||
this._lastPointer = null;
|
||||
this.activeDraggable.endDrag(event);
|
||||
this.activeDraggable = null;
|
||||
},
|
||||
|
||||
keyPress: function (event) {
|
||||
if (this.activeDraggable) {
|
||||
this.activeDraggable.keyPress(event);
|
||||
}
|
||||
},
|
||||
|
||||
notify: function (eventName, draggable, event) {
|
||||
MochiKit.Signal.signal(this, eventName, draggable, event);
|
||||
}
|
||||
};
|
||||
|
||||
/** @id MochiKit.DragAndDrop.Draggable */
|
||||
MochiKit.DragAndDrop.Draggable = function (element, options) {
|
||||
var cls = arguments.callee;
|
||||
if (!(this instanceof cls)) {
|
||||
return new cls(element, options);
|
||||
}
|
||||
this.__init__(element, options);
|
||||
};
|
||||
|
||||
MochiKit.DragAndDrop.Draggable.prototype = {
|
||||
/***
|
||||
|
||||
A draggable object. Simple instantiate :
|
||||
|
||||
new MochiKit.DragAndDrop.Draggable('myelement');
|
||||
|
||||
***/
|
||||
__class__ : MochiKit.DragAndDrop.Draggable,
|
||||
|
||||
__init__: function (element, /* optional */options) {
|
||||
var v = MochiKit.Visual;
|
||||
var b = MochiKit.Base;
|
||||
options = b.update({
|
||||
|
||||
/** @id MochiKit.DragAndDrop.handle */
|
||||
handle: false,
|
||||
|
||||
/** @id MochiKit.DragAndDrop.starteffect */
|
||||
starteffect: function (innerelement) {
|
||||
this._savedOpacity = MochiKit.Style.getStyle(innerelement, 'opacity') || 1.0;
|
||||
new v.Opacity(innerelement, {duration:0.2, from:this._savedOpacity, to:0.7});
|
||||
},
|
||||
/** @id MochiKit.DragAndDrop.reverteffect */
|
||||
reverteffect: function (innerelement, top_offset, left_offset) {
|
||||
var dur = Math.sqrt(Math.abs(top_offset^2) +
|
||||
Math.abs(left_offset^2))*0.02;
|
||||
return new v.Move(innerelement,
|
||||
{x: -left_offset, y: -top_offset, duration: dur});
|
||||
},
|
||||
|
||||
/** @id MochiKit.DragAndDrop.endeffect */
|
||||
endeffect: function (innerelement) {
|
||||
new v.Opacity(innerelement, {duration:0.2, from:0.7, to:this._savedOpacity});
|
||||
},
|
||||
|
||||
/** @id MochiKit.DragAndDrop.onchange */
|
||||
onchange: b.noop,
|
||||
|
||||
/** @id MochiKit.DragAndDrop.zindex */
|
||||
zindex: 1000,
|
||||
|
||||
/** @id MochiKit.DragAndDrop.revert */
|
||||
revert: false,
|
||||
|
||||
/** @id MochiKit.DragAndDrop.scroll */
|
||||
scroll: false,
|
||||
|
||||
/** @id MochiKit.DragAndDrop.scrollSensitivity */
|
||||
scrollSensitivity: 20,
|
||||
|
||||
/** @id MochiKit.DragAndDrop.scrollSpeed */
|
||||
scrollSpeed: 15,
|
||||
// false, or xy or [x, y] or function (x, y){return [x, y];}
|
||||
|
||||
/** @id MochiKit.DragAndDrop.snap */
|
||||
snap: false
|
||||
}, options);
|
||||
|
||||
var d = MochiKit.DOM;
|
||||
this.element = d.getElement(element);
|
||||
|
||||
if (options.handle && (typeof(options.handle) == 'string')) {
|
||||
this.handle = d.getFirstElementByTagAndClassName(null,
|
||||
options.handle, this.element);
|
||||
}
|
||||
if (!this.handle) {
|
||||
this.handle = d.getElement(options.handle);
|
||||
}
|
||||
if (!this.handle) {
|
||||
this.handle = this.element;
|
||||
}
|
||||
|
||||
if (options.scroll && !options.scroll.scrollTo && !options.scroll.outerHTML) {
|
||||
options.scroll = d.getElement(options.scroll);
|
||||
this._isScrollChild = MochiKit.DOM.isChildNode(this.element, options.scroll);
|
||||
}
|
||||
|
||||
MochiKit.Style.makePositioned(this.element); // fix IE
|
||||
|
||||
this.delta = this.currentDelta();
|
||||
this.options = options;
|
||||
this.dragging = false;
|
||||
|
||||
this.eventMouseDown = MochiKit.Signal.connect(this.handle,
|
||||
'onmousedown', this, this.initDrag);
|
||||
MochiKit.DragAndDrop.Draggables.register(this);
|
||||
},
|
||||
|
||||
/** @id MochiKit.DragAndDrop.destroy */
|
||||
destroy: function () {
|
||||
MochiKit.Signal.disconnect(this.eventMouseDown);
|
||||
MochiKit.DragAndDrop.Draggables.unregister(this);
|
||||
},
|
||||
|
||||
/** @id MochiKit.DragAndDrop.currentDelta */
|
||||
currentDelta: function () {
|
||||
var s = MochiKit.Style.getStyle;
|
||||
return [
|
||||
parseInt(s(this.element, 'left') || '0', 10),
|
||||
parseInt(s(this.element, 'top') || '0', 10)];
|
||||
},
|
||||
|
||||
/** @id MochiKit.DragAndDrop.initDrag */
|
||||
initDrag: function (event) {
|
||||
if (!event.mouse().button.left) {
|
||||
return;
|
||||
}
|
||||
// abort on form elements, fixes a Firefox issue
|
||||
var src = event.target();
|
||||
var tagName = (src.tagName || '').toUpperCase();
|
||||
if (tagName === 'INPUT' || tagName === 'SELECT' ||
|
||||
tagName === 'OPTION' || tagName === 'BUTTON' ||
|
||||
tagName === 'TEXTAREA') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._revert) {
|
||||
this._revert.cancel();
|
||||
this._revert = null;
|
||||
}
|
||||
|
||||
var pointer = event.mouse();
|
||||
var pos = MochiKit.Position.cumulativeOffset(this.element);
|
||||
this.offset = [pointer.page.x - pos.x, pointer.page.y - pos.y];
|
||||
|
||||
MochiKit.DragAndDrop.Draggables.activate(this);
|
||||
event.stop();
|
||||
},
|
||||
|
||||
/** @id MochiKit.DragAndDrop.startDrag */
|
||||
startDrag: function (event) {
|
||||
this.dragging = true;
|
||||
if (this.options.selectclass) {
|
||||
MochiKit.DOM.addElementClass(this.element,
|
||||
this.options.selectclass);
|
||||
}
|
||||
if (this.options.zindex) {
|
||||
this.originalZ = MochiKit.Style.getStyle(this.element, 'z-index');
|
||||
this.element.style.zIndex = this.options.zindex;
|
||||
}
|
||||
|
||||
if (this.options.ghosting) {
|
||||
this._clone = this.element.cloneNode(true);
|
||||
this.ghostPosition = MochiKit.Position.absolutize(this.element);
|
||||
this.element.parentNode.insertBefore(this._clone, this.element);
|
||||
}
|
||||
|
||||
if (this.options.scroll) {
|
||||
if (this.options.scroll == window) {
|
||||
var where = this._getWindowScroll(this.options.scroll);
|
||||
this.originalScrollLeft = where.left;
|
||||
this.originalScrollTop = where.top;
|
||||
} else {
|
||||
this.originalScrollLeft = this.options.scroll.scrollLeft;
|
||||
this.originalScrollTop = this.options.scroll.scrollTop;
|
||||
}
|
||||
}
|
||||
|
||||
MochiKit.DragAndDrop.Droppables.prepare(this.element);
|
||||
MochiKit.DragAndDrop.Draggables.notify('start', this, event);
|
||||
if (this.options.starteffect) {
|
||||
this.options.starteffect(this.element);
|
||||
}
|
||||
},
|
||||
|
||||
/** @id MochiKit.DragAndDrop.updateDrag */
|
||||
updateDrag: function (event, pointer) {
|
||||
if (!this.dragging) {
|
||||
this.startDrag(event);
|
||||
}
|
||||
MochiKit.Position.prepare();
|
||||
MochiKit.DragAndDrop.Droppables.show(pointer, this.element);
|
||||
MochiKit.DragAndDrop.Draggables.notify('drag', this, event);
|
||||
this.draw(pointer);
|
||||
this.options.onchange(this);
|
||||
|
||||
if (this.options.scroll) {
|
||||
this.stopScrolling();
|
||||
var p, q;
|
||||
if (this.options.scroll == window) {
|
||||
var s = this._getWindowScroll(this.options.scroll);
|
||||
p = new MochiKit.Style.Coordinates(s.left, s.top);
|
||||
q = new MochiKit.Style.Coordinates(s.left + s.width,
|
||||
s.top + s.height);
|
||||
} else {
|
||||
p = MochiKit.Position.page(this.options.scroll);
|
||||
p.x += this.options.scroll.scrollLeft;
|
||||
p.y += this.options.scroll.scrollTop;
|
||||
p.x += (window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft || 0);
|
||||
p.y += (window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0);
|
||||
q = new MochiKit.Style.Coordinates(p.x + this.options.scroll.offsetWidth,
|
||||
p.y + this.options.scroll.offsetHeight);
|
||||
}
|
||||
var speed = [0, 0];
|
||||
if (pointer.page.x > (q.x - this.options.scrollSensitivity)) {
|
||||
speed[0] = pointer.page.x - (q.x - this.options.scrollSensitivity);
|
||||
} else if (pointer.page.x < (p.x + this.options.scrollSensitivity)) {
|
||||
speed[0] = pointer.page.x - (p.x + this.options.scrollSensitivity);
|
||||
}
|
||||
if (pointer.page.y > (q.y - this.options.scrollSensitivity)) {
|
||||
speed[1] = pointer.page.y - (q.y - this.options.scrollSensitivity);
|
||||
} else if (pointer.page.y < (p.y + this.options.scrollSensitivity)) {
|
||||
speed[1] = pointer.page.y - (p.y + this.options.scrollSensitivity);
|
||||
}
|
||||
this.startScrolling(speed);
|
||||
}
|
||||
|
||||
// fix AppleWebKit rendering
|
||||
if (/AppleWebKit/.test(navigator.appVersion)) {
|
||||
window.scrollBy(0, 0);
|
||||
}
|
||||
event.stop();
|
||||
},
|
||||
|
||||
/** @id MochiKit.DragAndDrop.finishDrag */
|
||||
finishDrag: function (event, success) {
|
||||
var dr = MochiKit.DragAndDrop;
|
||||
this.dragging = false;
|
||||
if (this.options.selectclass) {
|
||||
MochiKit.DOM.removeElementClass(this.element,
|
||||
this.options.selectclass);
|
||||
}
|
||||
|
||||
if (this.options.ghosting) {
|
||||
// XXX: from a user point of view, it would be better to remove
|
||||
// the node only *after* the MochiKit.Visual.Move end when used
|
||||
// with revert.
|
||||
MochiKit.Position.relativize(this.element, this.ghostPosition);
|
||||
MochiKit.DOM.removeElement(this._clone);
|
||||
this._clone = null;
|
||||
}
|
||||
|
||||
if (success) {
|
||||
dr.Droppables.fire(event, this.element);
|
||||
}
|
||||
dr.Draggables.notify('end', this, event);
|
||||
|
||||
var revert = this.options.revert;
|
||||
if (revert && typeof(revert) == 'function') {
|
||||
revert = revert(this.element);
|
||||
}
|
||||
|
||||
var d = this.currentDelta();
|
||||
if (revert && this.options.reverteffect) {
|
||||
this._revert = this.options.reverteffect(this.element,
|
||||
d[1] - this.delta[1], d[0] - this.delta[0]);
|
||||
} else {
|
||||
this.delta = d;
|
||||
}
|
||||
|
||||
if (this.options.zindex) {
|
||||
this.element.style.zIndex = this.originalZ;
|
||||
}
|
||||
|
||||
if (this.options.endeffect) {
|
||||
this.options.endeffect(this.element);
|
||||
}
|
||||
|
||||
dr.Draggables.deactivate();
|
||||
dr.Droppables.reset(this.element);
|
||||
},
|
||||
|
||||
/** @id MochiKit.DragAndDrop.keyPress */
|
||||
keyPress: function (event) {
|
||||
if (event.key().string != "KEY_ESCAPE") {
|
||||
return;
|
||||
}
|
||||
this.finishDrag(event, false);
|
||||
event.stop();
|
||||
},
|
||||
|
||||
/** @id MochiKit.DragAndDrop.endDrag */
|
||||
endDrag: function (event) {
|
||||
if (!this.dragging) {
|
||||
return;
|
||||
}
|
||||
this.stopScrolling();
|
||||
this.finishDrag(event, true);
|
||||
event.stop();
|
||||
},
|
||||
|
||||
/** @id MochiKit.DragAndDrop.draw */
|
||||
draw: function (point) {
|
||||
var pos = MochiKit.Position.cumulativeOffset(this.element);
|
||||
var d = this.currentDelta();
|
||||
pos.x -= d[0];
|
||||
pos.y -= d[1];
|
||||
|
||||
if (this.options.scroll && (this.options.scroll != window && this._isScrollChild)) {
|
||||
pos.x -= this.options.scroll.scrollLeft - this.originalScrollLeft;
|
||||
pos.y -= this.options.scroll.scrollTop - this.originalScrollTop;
|
||||
}
|
||||
|
||||
var p = [point.page.x - pos.x - this.offset[0],
|
||||
point.page.y - pos.y - this.offset[1]];
|
||||
|
||||
if (this.options.snap) {
|
||||
if (typeof(this.options.snap) == 'function') {
|
||||
p = this.options.snap(p[0], p[1]);
|
||||
} else {
|
||||
if (this.options.snap instanceof Array) {
|
||||
var i = -1;
|
||||
p = MochiKit.Base.map(MochiKit.Base.bind(function (v) {
|
||||
i += 1;
|
||||
return Math.round(v/this.options.snap[i]) *
|
||||
this.options.snap[i];
|
||||
}, this), p);
|
||||
} else {
|
||||
p = MochiKit.Base.map(MochiKit.Base.bind(function (v) {
|
||||
return Math.round(v/this.options.snap) *
|
||||
this.options.snap;
|
||||
}, this), p);
|
||||
}
|
||||
}
|
||||
}
|
||||
var style = this.element.style;
|
||||
if ((!this.options.constraint) ||
|
||||
(this.options.constraint == 'horizontal')) {
|
||||
style.left = p[0] + 'px';
|
||||
}
|
||||
if ((!this.options.constraint) ||
|
||||
(this.options.constraint == 'vertical')) {
|
||||
style.top = p[1] + 'px';
|
||||
}
|
||||
if (style.visibility == 'hidden') {
|
||||
style.visibility = ''; // fix gecko rendering
|
||||
}
|
||||
},
|
||||
|
||||
/** @id MochiKit.DragAndDrop.stopScrolling */
|
||||
stopScrolling: function () {
|
||||
if (this.scrollInterval) {
|
||||
clearInterval(this.scrollInterval);
|
||||
this.scrollInterval = null;
|
||||
MochiKit.DragAndDrop.Draggables._lastScrollPointer = null;
|
||||
}
|
||||
},
|
||||
|
||||
/** @id MochiKit.DragAndDrop.startScrolling */
|
||||
startScrolling: function (speed) {
|
||||
if (!speed[0] && !speed[1]) {
|
||||
return;
|
||||
}
|
||||
this.scrollSpeed = [speed[0] * this.options.scrollSpeed,
|
||||
speed[1] * this.options.scrollSpeed];
|
||||
this.lastScrolled = new Date();
|
||||
this.scrollInterval = setInterval(MochiKit.Base.bind(this.scroll, this), 10);
|
||||
},
|
||||
|
||||
/** @id MochiKit.DragAndDrop.scroll */
|
||||
scroll: function () {
|
||||
var current = new Date();
|
||||
var delta = current - this.lastScrolled;
|
||||
this.lastScrolled = current;
|
||||
|
||||
if (this.options.scroll == window) {
|
||||
var s = this._getWindowScroll(this.options.scroll);
|
||||
if (this.scrollSpeed[0] || this.scrollSpeed[1]) {
|
||||
var dm = delta / 1000;
|
||||
this.options.scroll.scrollTo(s.left + dm * this.scrollSpeed[0],
|
||||
s.top + dm * this.scrollSpeed[1]);
|
||||
}
|
||||
} else {
|
||||
this.options.scroll.scrollLeft += this.scrollSpeed[0] * delta / 1000;
|
||||
this.options.scroll.scrollTop += this.scrollSpeed[1] * delta / 1000;
|
||||
}
|
||||
|
||||
var d = MochiKit.DragAndDrop;
|
||||
|
||||
MochiKit.Position.prepare();
|
||||
d.Droppables.show(d.Draggables._lastPointer, this.element);
|
||||
d.Draggables.notify('drag', this);
|
||||
if (this._isScrollChild) {
|
||||
d.Draggables._lastScrollPointer = d.Draggables._lastScrollPointer || d.Draggables._lastPointer;
|
||||
d.Draggables._lastScrollPointer.x += this.scrollSpeed[0] * delta / 1000;
|
||||
d.Draggables._lastScrollPointer.y += this.scrollSpeed[1] * delta / 1000;
|
||||
if (d.Draggables._lastScrollPointer.x < 0) {
|
||||
d.Draggables._lastScrollPointer.x = 0;
|
||||
}
|
||||
if (d.Draggables._lastScrollPointer.y < 0) {
|
||||
d.Draggables._lastScrollPointer.y = 0;
|
||||
}
|
||||
this.draw(d.Draggables._lastScrollPointer);
|
||||
}
|
||||
|
||||
this.options.onchange(this);
|
||||
},
|
||||
|
||||
_getWindowScroll: function (win) {
|
||||
var vp, w, h;
|
||||
MochiKit.DOM.withWindow(win, function () {
|
||||
vp = MochiKit.Style.getViewportPosition(win.document);
|
||||
});
|
||||
if (win.innerWidth) {
|
||||
w = win.innerWidth;
|
||||
h = win.innerHeight;
|
||||
} else if (win.document.documentElement && win.document.documentElement.clientWidth) {
|
||||
w = win.document.documentElement.clientWidth;
|
||||
h = win.document.documentElement.clientHeight;
|
||||
} else {
|
||||
w = win.document.body.offsetWidth;
|
||||
h = win.document.body.offsetHeight;
|
||||
}
|
||||
return {top: vp.y, left: vp.x, width: w, height: h};
|
||||
},
|
||||
|
||||
/** @id MochiKit.DragAndDrop.repr */
|
||||
repr: function () {
|
||||
return '[' + this.__class__.NAME + ", options:" + MochiKit.Base.repr(this.options) + "]";
|
||||
}
|
||||
};
|
||||
|
||||
MochiKit.DragAndDrop.__new__ = function () {
|
||||
MochiKit.Base.nameFunctions(this);
|
||||
};
|
||||
|
||||
MochiKit.DragAndDrop.__new__();
|
||||
|
||||
MochiKit.Base._exportSymbols(this, MochiKit.DragAndDrop);
|
||||
332
frontend/delta/js/MochiKit/Format.js
Normal file
332
frontend/delta/js/MochiKit/Format.js
Normal file
@@ -0,0 +1,332 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
/***
|
||||
|
||||
MochiKit.Format 1.5
|
||||
|
||||
See <http://mochikit.com/> for documentation, downloads, license, etc.
|
||||
|
||||
(c) 2005 Bob Ippolito. All rights Reserved.
|
||||
|
||||
***/
|
||||
|
||||
MochiKit.Base.module(MochiKit, 'Format', '1.5', ['Base']);
|
||||
|
||||
MochiKit.Format._numberFormatter = function (placeholder, header, footer, locale, isPercent, precision, leadingZeros, separatorAt, trailingZeros) {
|
||||
return function (num) {
|
||||
num = parseFloat(num);
|
||||
if (typeof(num) == "undefined" || num === null || isNaN(num)) {
|
||||
return placeholder;
|
||||
}
|
||||
var curheader = header;
|
||||
var curfooter = footer;
|
||||
if (num < 0) {
|
||||
num = -num;
|
||||
} else {
|
||||
curheader = curheader.replace(/-/, "");
|
||||
}
|
||||
var me = arguments.callee;
|
||||
var fmt = MochiKit.Format.formatLocale(locale);
|
||||
if (isPercent) {
|
||||
num = num * 100.0;
|
||||
curfooter = fmt.percent + curfooter;
|
||||
}
|
||||
num = MochiKit.Format.roundToFixed(num, precision);
|
||||
var parts = num.split(/\./);
|
||||
var whole = parts[0];
|
||||
var frac = (parts.length == 1) ? "" : parts[1];
|
||||
var res = "";
|
||||
while (whole.length < leadingZeros) {
|
||||
whole = "0" + whole;
|
||||
}
|
||||
if (separatorAt) {
|
||||
while (whole.length > separatorAt) {
|
||||
var i = whole.length - separatorAt;
|
||||
//res = res + fmt.separator + whole.substring(i, whole.length);
|
||||
res = fmt.separator + whole.substring(i, whole.length) + res;
|
||||
whole = whole.substring(0, i);
|
||||
}
|
||||
}
|
||||
res = whole + res;
|
||||
if (precision > 0) {
|
||||
while (frac.length < trailingZeros) {
|
||||
frac = frac + "0";
|
||||
}
|
||||
res = res + fmt.decimal + frac;
|
||||
}
|
||||
return curheader + res + curfooter;
|
||||
};
|
||||
};
|
||||
|
||||
/** @id MochiKit.Format.numberFormatter */
|
||||
MochiKit.Format.numberFormatter = function (pattern, placeholder/* = "" */, locale/* = "default" */) {
|
||||
// http://java.sun.com/docs/books/tutorial/i18n/format/numberpattern.html
|
||||
// | 0 | leading or trailing zeros
|
||||
// | # | just the number
|
||||
// | , | separator
|
||||
// | . | decimal separator
|
||||
// | % | Multiply by 100 and format as percent
|
||||
if (typeof(placeholder) == "undefined") {
|
||||
placeholder = "";
|
||||
}
|
||||
var match = pattern.match(/((?:[0#]+,)?[0#]+)(?:\.([0#]+))?(%)?/);
|
||||
if (!match) {
|
||||
throw TypeError("Invalid pattern");
|
||||
}
|
||||
var header = pattern.substr(0, match.index);
|
||||
var footer = pattern.substr(match.index + match[0].length);
|
||||
if (header.search(/-/) == -1) {
|
||||
header = header + "-";
|
||||
}
|
||||
var whole = match[1];
|
||||
var frac = (typeof(match[2]) == "string" && match[2] != "") ? match[2] : "";
|
||||
var isPercent = (typeof(match[3]) == "string" && match[3] != "");
|
||||
var tmp = whole.split(/,/);
|
||||
var separatorAt;
|
||||
if (typeof(locale) == "undefined") {
|
||||
locale = "default";
|
||||
}
|
||||
if (tmp.length == 1) {
|
||||
separatorAt = null;
|
||||
} else {
|
||||
separatorAt = tmp[1].length;
|
||||
}
|
||||
var leadingZeros = whole.length - whole.replace(/0/g, "").length;
|
||||
var trailingZeros = frac.length - frac.replace(/0/g, "").length;
|
||||
var precision = frac.length;
|
||||
var rval = MochiKit.Format._numberFormatter(
|
||||
placeholder, header, footer, locale, isPercent, precision,
|
||||
leadingZeros, separatorAt, trailingZeros
|
||||
);
|
||||
var m = MochiKit.Base;
|
||||
if (m) {
|
||||
var fn = arguments.callee;
|
||||
var args = m.concat(arguments);
|
||||
rval.repr = function () {
|
||||
return [
|
||||
self.NAME,
|
||||
"(",
|
||||
m.map(m.repr, args).join(", "),
|
||||
")"
|
||||
].join("");
|
||||
};
|
||||
}
|
||||
return rval;
|
||||
};
|
||||
|
||||
/** @id MochiKit.Format.formatLocale */
|
||||
MochiKit.Format.formatLocale = function (locale) {
|
||||
if (typeof(locale) == "undefined" || locale === null) {
|
||||
locale = "default";
|
||||
}
|
||||
if (typeof(locale) == "string") {
|
||||
var rval = MochiKit.Format.LOCALE[locale];
|
||||
if (typeof(rval) == "string") {
|
||||
rval = arguments.callee(rval);
|
||||
MochiKit.Format.LOCALE[locale] = rval;
|
||||
}
|
||||
return rval;
|
||||
} else {
|
||||
return locale;
|
||||
}
|
||||
};
|
||||
|
||||
/** @id MochiKit.Format.twoDigitAverage */
|
||||
MochiKit.Format.twoDigitAverage = function (numerator, denominator) {
|
||||
if (denominator) {
|
||||
var res = numerator / denominator;
|
||||
if (!isNaN(res)) {
|
||||
return MochiKit.Format.twoDigitFloat(res);
|
||||
}
|
||||
}
|
||||
return "0";
|
||||
};
|
||||
|
||||
/** @id MochiKit.Format.twoDigitFloat */
|
||||
MochiKit.Format.twoDigitFloat = function (aNumber) {
|
||||
var res = MochiKit.Format.roundToFixed(aNumber, 2);
|
||||
if (res.indexOf(".00") > 0) {
|
||||
return res.substring(0, res.length - 3);
|
||||
} else if (res.charAt(res.length - 1) == "0") {
|
||||
return res.substring(0, res.length - 1);
|
||||
} else {
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
||||
/** @id MochiKit.Format.lstrip */
|
||||
MochiKit.Format.lstrip = function (str, /* optional */chars) {
|
||||
str = str + "";
|
||||
if (typeof(str) != "string") {
|
||||
return null;
|
||||
}
|
||||
if (!chars) {
|
||||
return str.replace(/^\s+/, "");
|
||||
} else {
|
||||
return str.replace(new RegExp("^[" + chars + "]+"), "");
|
||||
}
|
||||
};
|
||||
|
||||
/** @id MochiKit.Format.rstrip */
|
||||
MochiKit.Format.rstrip = function (str, /* optional */chars) {
|
||||
str = str + "";
|
||||
if (typeof(str) != "string") {
|
||||
return null;
|
||||
}
|
||||
if (!chars) {
|
||||
return str.replace(/\s+$/, "");
|
||||
} else {
|
||||
return str.replace(new RegExp("[" + chars + "]+$"), "");
|
||||
}
|
||||
};
|
||||
|
||||
/** @id MochiKit.Format.strip */
|
||||
MochiKit.Format.strip = function (str, /* optional */chars) {
|
||||
var self = MochiKit.Format;
|
||||
return self.rstrip(self.lstrip(str, chars), chars);
|
||||
};
|
||||
|
||||
/** @id MochiKit.Format.truncToFixed */
|
||||
MochiKit.Format.truncToFixed = function (aNumber, precision) {
|
||||
var fixed = MochiKit.Format._numberToFixed(aNumber, precision);
|
||||
var fracPos = fixed.indexOf(".");
|
||||
if (fracPos > 0 && fracPos + precision + 1 < fixed.length) {
|
||||
fixed = fixed.substring(0, fracPos + precision + 1);
|
||||
fixed = MochiKit.Format._shiftNumber(fixed, 0);
|
||||
}
|
||||
return fixed;
|
||||
};
|
||||
|
||||
/** @id MochiKit.Format.roundToFixed */
|
||||
MochiKit.Format.roundToFixed = function (aNumber, precision) {
|
||||
var fixed = MochiKit.Format._numberToFixed(aNumber, precision);
|
||||
var fracPos = fixed.indexOf(".");
|
||||
if (fracPos > 0 && fracPos + precision + 1 < fixed.length) {
|
||||
var str = MochiKit.Format._shiftNumber(fixed, precision);
|
||||
str = MochiKit.Format._numberToFixed(Math.round(parseFloat(str)), 0);
|
||||
fixed = MochiKit.Format._shiftNumber(str, -precision);
|
||||
}
|
||||
return fixed;
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts a number to a fixed format string. This function handles
|
||||
* conversion of exponents by shifting the decimal point to the left
|
||||
* or the right. It also guarantees a specified minimum number of
|
||||
* fractional digits (but no maximum).
|
||||
*
|
||||
* @param {Number} aNumber the number to convert
|
||||
* @param {Number} precision the minimum number of decimal digits
|
||||
*
|
||||
* @return {String} the fixed format number string
|
||||
*/
|
||||
MochiKit.Format._numberToFixed = function (aNumber, precision) {
|
||||
var str = aNumber.toString();
|
||||
var parts = str.split(/[eE]/);
|
||||
var exp = (parts.length === 1) ? 0 : parseInt(parts[1], 10) || 0;
|
||||
var fixed = MochiKit.Format._shiftNumber(parts[0], exp);
|
||||
parts = fixed.split(/\./);
|
||||
var whole = parts[0];
|
||||
var frac = (parts.length === 1) ? "" : parts[1];
|
||||
while (frac.length < precision) {
|
||||
frac += "0";
|
||||
}
|
||||
if (frac.length > 0) {
|
||||
return whole + "." + frac;
|
||||
} else {
|
||||
return whole;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Shifts the decimal dot location in a fixed format number string.
|
||||
* This function handles negative values and will add and remove
|
||||
* leading and trailing zeros as needed.
|
||||
*
|
||||
* @param {String} num the fixed format number string
|
||||
* @param {Number} exp the base-10 exponent to apply
|
||||
*
|
||||
* @return {String} the new fixed format number string
|
||||
*/
|
||||
MochiKit.Format._shiftNumber = function (num, exp) {
|
||||
var pos = num.indexOf(".");
|
||||
if (pos < 0) {
|
||||
pos = num.length;
|
||||
} else {
|
||||
num = num.substring(0, pos) + num.substring(pos + 1);
|
||||
}
|
||||
pos += exp;
|
||||
while (pos <= 0 || (pos <= 1 && num.charAt(0) === "-")) {
|
||||
if (num.charAt(0) === "-") {
|
||||
num = "-0" + num.substring(1);
|
||||
} else {
|
||||
num = "0" + num;
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
while (pos > num.length) {
|
||||
num += "0";
|
||||
}
|
||||
if (pos < num.length) {
|
||||
num = num.substring(0, pos) + "." + num.substring(pos);
|
||||
}
|
||||
while (/^0[^.]/.test(num)) {
|
||||
num = num.substring(1);
|
||||
}
|
||||
while (/^-0[^.]/.test(num)) {
|
||||
num = "-" + num.substring(2);
|
||||
}
|
||||
return num;
|
||||
};
|
||||
|
||||
/** @id MochiKit.Format.percentFormat */
|
||||
MochiKit.Format.percentFormat = function (aNumber) {
|
||||
return MochiKit.Format.twoDigitFloat(100 * aNumber) + '%';
|
||||
};
|
||||
|
||||
MochiKit.Format.LOCALE = {
|
||||
en_US: {separator: ",", decimal: ".", percent: "%"},
|
||||
de_DE: {separator: ".", decimal: ",", percent: "%"},
|
||||
pt_BR: {separator: ".", decimal: ",", percent: "%"},
|
||||
fr_FR: {separator: " ", decimal: ",", percent: "%"},
|
||||
"default": "en_US",
|
||||
__export__: false
|
||||
};
|
||||
|
||||
MochiKit.Format.__new__ = function () {
|
||||
MochiKit.Base.nameFunctions(this);
|
||||
var base = this.NAME + ".";
|
||||
var k, v, o;
|
||||
for (k in this.LOCALE) {
|
||||
o = this.LOCALE[k];
|
||||
if (typeof(o) == "object") {
|
||||
o.repr = function () { return this.NAME; };
|
||||
o.NAME = base + "LOCALE." + k;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
MochiKit.Format.__new__();
|
||||
|
||||
MochiKit.Base._exportSymbols(this, MochiKit.Format);
|
||||
811
frontend/delta/js/MochiKit/Iter.js
Normal file
811
frontend/delta/js/MochiKit/Iter.js
Normal file
@@ -0,0 +1,811 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
/***
|
||||
|
||||
MochiKit.Iter 1.5
|
||||
|
||||
See <http://mochikit.com/> for documentation, downloads, license, etc.
|
||||
|
||||
(c) 2005 Bob Ippolito. All rights Reserved.
|
||||
|
||||
***/
|
||||
|
||||
MochiKit.Base.module(MochiKit, 'Iter', '1.5', ['Base']);
|
||||
|
||||
MochiKit.Base.update(MochiKit.Iter, {
|
||||
/** @id MochiKit.Iter.registerIteratorFactory */
|
||||
registerIteratorFactory: function (name, check, iterfactory, /* optional */ override) {
|
||||
MochiKit.Iter.iteratorRegistry.register(name, check, iterfactory, override);
|
||||
},
|
||||
|
||||
/** @id MochiKit.Iter.isIterable */
|
||||
isIterable: function(o) {
|
||||
return o != null &&
|
||||
(typeof(o.next) == "function" || typeof(o.iter) == "function");
|
||||
},
|
||||
|
||||
/** @id MochiKit.Iter.iter */
|
||||
iter: function (iterable, /* optional */ sentinel) {
|
||||
var self = MochiKit.Iter;
|
||||
if (arguments.length == 2) {
|
||||
return self.takewhile(
|
||||
function (a) { return a != sentinel; },
|
||||
iterable
|
||||
);
|
||||
}
|
||||
if (typeof(iterable.next) == 'function') {
|
||||
return iterable;
|
||||
} else if (typeof(iterable.iter) == 'function') {
|
||||
return iterable.iter();
|
||||
/*
|
||||
} else if (typeof(iterable.__iterator__) == 'function') {
|
||||
//
|
||||
// XXX: We can't support JavaScript 1.7 __iterator__ directly
|
||||
// because of Object.prototype.__iterator__
|
||||
//
|
||||
return iterable.__iterator__();
|
||||
*/
|
||||
}
|
||||
|
||||
try {
|
||||
return self.iteratorRegistry.match(iterable);
|
||||
} catch (e) {
|
||||
var m = MochiKit.Base;
|
||||
if (e == m.NotFound) {
|
||||
e = new TypeError(typeof(iterable) + ": " + m.repr(iterable) + " is not iterable");
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
},
|
||||
|
||||
/** @id MochiKit.Iter.count */
|
||||
count: function (n) {
|
||||
if (!n) {
|
||||
n = 0;
|
||||
}
|
||||
var m = MochiKit.Base;
|
||||
return {
|
||||
repr: function () { return "count(" + n + ")"; },
|
||||
toString: m.forwardCall("repr"),
|
||||
next: m.counter(n)
|
||||
};
|
||||
},
|
||||
|
||||
/** @id MochiKit.Iter.cycle */
|
||||
cycle: function (p) {
|
||||
var self = MochiKit.Iter;
|
||||
var m = MochiKit.Base;
|
||||
var lst = [];
|
||||
var iterator = self.iter(p);
|
||||
return {
|
||||
repr: function () { return "cycle(...)"; },
|
||||
toString: m.forwardCall("repr"),
|
||||
next: function () {
|
||||
try {
|
||||
var rval = iterator.next();
|
||||
lst.push(rval);
|
||||
return rval;
|
||||
} catch (e) {
|
||||
if (e != self.StopIteration) {
|
||||
throw e;
|
||||
}
|
||||
if (lst.length === 0) {
|
||||
this.next = function () {
|
||||
throw self.StopIteration;
|
||||
};
|
||||
} else {
|
||||
var i = -1;
|
||||
this.next = function () {
|
||||
i = (i + 1) % lst.length;
|
||||
return lst[i];
|
||||
};
|
||||
}
|
||||
return this.next();
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
/** @id MochiKit.Iter.repeat */
|
||||
repeat: function (elem, /* optional */n) {
|
||||
var m = MochiKit.Base;
|
||||
if (typeof(n) == 'undefined') {
|
||||
return {
|
||||
repr: function () {
|
||||
return "repeat(" + m.repr(elem) + ")";
|
||||
},
|
||||
toString: m.forwardCall("repr"),
|
||||
next: function () {
|
||||
return elem;
|
||||
}
|
||||
};
|
||||
}
|
||||
return {
|
||||
repr: function () {
|
||||
return "repeat(" + m.repr(elem) + ", " + n + ")";
|
||||
},
|
||||
toString: m.forwardCall("repr"),
|
||||
next: function () {
|
||||
if (n <= 0) {
|
||||
throw MochiKit.Iter.StopIteration;
|
||||
}
|
||||
n -= 1;
|
||||
return elem;
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
/** @id MochiKit.Iter.next */
|
||||
next: function (iterator) {
|
||||
return iterator.next();
|
||||
},
|
||||
|
||||
/** @id MochiKit.Iter.izip */
|
||||
izip: function (p, q/*, ...*/) {
|
||||
var m = MochiKit.Base;
|
||||
var self = MochiKit.Iter;
|
||||
var next = self.next;
|
||||
var iterables = m.map(self.iter, arguments);
|
||||
return {
|
||||
repr: function () { return "izip(...)"; },
|
||||
toString: m.forwardCall("repr"),
|
||||
next: function () { return m.map(next, iterables); }
|
||||
};
|
||||
},
|
||||
|
||||
/** @id MochiKit.Iter.ifilter */
|
||||
ifilter: function (pred, seq) {
|
||||
var m = MochiKit.Base;
|
||||
seq = MochiKit.Iter.iter(seq);
|
||||
if (pred === null) {
|
||||
pred = m.operator.truth;
|
||||
}
|
||||
return {
|
||||
repr: function () { return "ifilter(...)"; },
|
||||
toString: m.forwardCall("repr"),
|
||||
next: function () {
|
||||
while (true) {
|
||||
var rval = seq.next();
|
||||
if (pred(rval)) {
|
||||
return rval;
|
||||
}
|
||||
}
|
||||
// mozilla warnings aren't too bright
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
/** @id MochiKit.Iter.ifilterfalse */
|
||||
ifilterfalse: function (pred, seq) {
|
||||
var m = MochiKit.Base;
|
||||
seq = MochiKit.Iter.iter(seq);
|
||||
if (pred === null) {
|
||||
pred = m.operator.truth;
|
||||
}
|
||||
return {
|
||||
repr: function () { return "ifilterfalse(...)"; },
|
||||
toString: m.forwardCall("repr"),
|
||||
next: function () {
|
||||
while (true) {
|
||||
var rval = seq.next();
|
||||
if (!pred(rval)) {
|
||||
return rval;
|
||||
}
|
||||
}
|
||||
// mozilla warnings aren't too bright
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
/** @id MochiKit.Iter.islice */
|
||||
islice: function (seq/*, [start,] stop[, step] */) {
|
||||
var self = MochiKit.Iter;
|
||||
var m = MochiKit.Base;
|
||||
seq = self.iter(seq);
|
||||
var start = 0;
|
||||
var stop = 0;
|
||||
var step = 1;
|
||||
var i = -1;
|
||||
if (arguments.length == 2) {
|
||||
stop = arguments[1];
|
||||
} else if (arguments.length == 3) {
|
||||
start = arguments[1];
|
||||
stop = arguments[2];
|
||||
} else {
|
||||
start = arguments[1];
|
||||
stop = arguments[2];
|
||||
step = arguments[3];
|
||||
}
|
||||
return {
|
||||
repr: function () {
|
||||
return "islice(" + ["...", start, stop, step].join(", ") + ")";
|
||||
},
|
||||
toString: m.forwardCall("repr"),
|
||||
next: function () {
|
||||
if (start >= stop) {
|
||||
throw self.StopIteration;
|
||||
}
|
||||
|
||||
var rval;
|
||||
while (i < start) {
|
||||
rval = seq.next();
|
||||
i++;
|
||||
}
|
||||
start += step;
|
||||
return rval;
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
/** @id MochiKit.Iter.imap */
|
||||
imap: function (fun, p, q/*, ...*/) {
|
||||
var m = MochiKit.Base;
|
||||
var self = MochiKit.Iter;
|
||||
var iterables = m.map(self.iter, m.extend(null, arguments, 1));
|
||||
var map = m.map;
|
||||
var next = self.next;
|
||||
return {
|
||||
repr: function () { return "imap(...)"; },
|
||||
toString: m.forwardCall("repr"),
|
||||
next: function () {
|
||||
return fun.apply(this, map(next, iterables));
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
/** @id MochiKit.Iter.applymap */
|
||||
applymap: function (fun, seq, self) {
|
||||
seq = MochiKit.Iter.iter(seq);
|
||||
var m = MochiKit.Base;
|
||||
return {
|
||||
repr: function () { return "applymap(...)"; },
|
||||
toString: m.forwardCall("repr"),
|
||||
next: function () {
|
||||
return fun.apply(self, seq.next());
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
/** @id MochiKit.Iter.chain */
|
||||
chain: function (p, q/*, ...*/) {
|
||||
// dumb fast path
|
||||
var self = MochiKit.Iter;
|
||||
var m = MochiKit.Base;
|
||||
if (arguments.length == 1) {
|
||||
return self.iter(arguments[0]);
|
||||
}
|
||||
var argiter = m.map(self.iter, arguments);
|
||||
return {
|
||||
repr: function () { return "chain(...)"; },
|
||||
toString: m.forwardCall("repr"),
|
||||
next: function () {
|
||||
while (argiter.length > 1) {
|
||||
try {
|
||||
return argiter[0].next();
|
||||
} catch (e) {
|
||||
if (e != self.StopIteration) {
|
||||
throw e;
|
||||
}
|
||||
argiter.shift();
|
||||
}
|
||||
}
|
||||
if (argiter.length == 1) {
|
||||
// optimize last element
|
||||
var arg = argiter.shift();
|
||||
this.next = m.bind("next", arg);
|
||||
return this.next();
|
||||
}
|
||||
throw self.StopIteration;
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
/** @id MochiKit.Iter.takewhile */
|
||||
takewhile: function (pred, seq) {
|
||||
var self = MochiKit.Iter;
|
||||
seq = self.iter(seq);
|
||||
return {
|
||||
repr: function () { return "takewhile(...)"; },
|
||||
toString: MochiKit.Base.forwardCall("repr"),
|
||||
next: function () {
|
||||
var rval = seq.next();
|
||||
if (!pred(rval)) {
|
||||
this.next = function () {
|
||||
throw self.StopIteration;
|
||||
};
|
||||
this.next();
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
/** @id MochiKit.Iter.dropwhile */
|
||||
dropwhile: function (pred, seq) {
|
||||
seq = MochiKit.Iter.iter(seq);
|
||||
var m = MochiKit.Base;
|
||||
var bind = m.bind;
|
||||
return {
|
||||
"repr": function () { return "dropwhile(...)"; },
|
||||
"toString": m.forwardCall("repr"),
|
||||
"next": function () {
|
||||
while (true) {
|
||||
var rval = seq.next();
|
||||
if (!pred(rval)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.next = bind("next", seq);
|
||||
return rval;
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
_tee: function (ident, sync, iterable) {
|
||||
sync.pos[ident] = -1;
|
||||
var m = MochiKit.Base;
|
||||
var listMin = m.listMin;
|
||||
return {
|
||||
repr: function () { return "tee(" + ident + ", ...)"; },
|
||||
toString: m.forwardCall("repr"),
|
||||
next: function () {
|
||||
var rval;
|
||||
var i = sync.pos[ident];
|
||||
|
||||
if (i == sync.max) {
|
||||
rval = iterable.next();
|
||||
sync.deque.push(rval);
|
||||
sync.max += 1;
|
||||
sync.pos[ident] += 1;
|
||||
} else {
|
||||
rval = sync.deque[i - sync.min];
|
||||
sync.pos[ident] += 1;
|
||||
if (i == sync.min && listMin(sync.pos) != sync.min) {
|
||||
sync.min += 1;
|
||||
sync.deque.shift();
|
||||
}
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
/** @id MochiKit.Iter.tee */
|
||||
tee: function (iterable, n/* = 2 */) {
|
||||
var rval = [];
|
||||
var sync = {
|
||||
"pos": [],
|
||||
"deque": [],
|
||||
"max": -1,
|
||||
"min": -1
|
||||
};
|
||||
if (arguments.length == 1 || typeof(n) == "undefined" || n === null) {
|
||||
n = 2;
|
||||
}
|
||||
var self = MochiKit.Iter;
|
||||
iterable = self.iter(iterable);
|
||||
var _tee = self._tee;
|
||||
for (var i = 0; i < n; i++) {
|
||||
rval.push(_tee(i, sync, iterable));
|
||||
}
|
||||
return rval;
|
||||
},
|
||||
|
||||
/** @id MochiKit.Iter.list */
|
||||
list: function (iterable) {
|
||||
// Fast-path for Array and Array-like
|
||||
var rval;
|
||||
if (iterable instanceof Array) {
|
||||
return iterable.slice();
|
||||
}
|
||||
// this is necessary to avoid a Safari crash
|
||||
if (typeof(iterable) == "function" &&
|
||||
!(iterable instanceof Function) &&
|
||||
typeof(iterable.length) == 'number') {
|
||||
rval = [];
|
||||
for (var i = 0; i < iterable.length; i++) {
|
||||
rval.push(iterable[i]);
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
|
||||
var self = MochiKit.Iter;
|
||||
iterable = self.iter(iterable);
|
||||
rval = [];
|
||||
var a_val;
|
||||
try {
|
||||
while (true) {
|
||||
a_val = iterable.next();
|
||||
rval.push(a_val);
|
||||
}
|
||||
} catch (e) {
|
||||
if (e != self.StopIteration) {
|
||||
throw e;
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
// mozilla warnings aren't too bright
|
||||
return undefined;
|
||||
},
|
||||
|
||||
|
||||
/** @id MochiKit.Iter.reduce */
|
||||
reduce: function (fn, iterable, /* optional */initial) {
|
||||
var i = 0;
|
||||
var x = initial;
|
||||
var self = MochiKit.Iter;
|
||||
iterable = self.iter(iterable);
|
||||
if (arguments.length < 3) {
|
||||
try {
|
||||
x = iterable.next();
|
||||
} catch (e) {
|
||||
if (e == self.StopIteration) {
|
||||
e = new TypeError("reduce() of empty sequence with no initial value");
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
try {
|
||||
while (true) {
|
||||
x = fn(x, iterable.next());
|
||||
}
|
||||
} catch (e) {
|
||||
if (e != self.StopIteration) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
return x;
|
||||
},
|
||||
|
||||
/** @id MochiKit.Iter.range */
|
||||
range: function (/* [start,] stop[, step] */) {
|
||||
var start = 0;
|
||||
var stop = 0;
|
||||
var step = 1;
|
||||
if (arguments.length == 1) {
|
||||
stop = arguments[0];
|
||||
} else if (arguments.length == 2) {
|
||||
start = arguments[0];
|
||||
stop = arguments[1];
|
||||
} else if (arguments.length == 3) {
|
||||
start = arguments[0];
|
||||
stop = arguments[1];
|
||||
step = arguments[2];
|
||||
} else {
|
||||
throw new TypeError("range() takes 1, 2, or 3 arguments!");
|
||||
}
|
||||
if (step === 0) {
|
||||
throw new TypeError("range() step must not be 0");
|
||||
}
|
||||
return {
|
||||
next: function () {
|
||||
if ((step > 0 && start >= stop) || (step < 0 && start <= stop)) {
|
||||
throw MochiKit.Iter.StopIteration;
|
||||
}
|
||||
var rval = start;
|
||||
start += step;
|
||||
return rval;
|
||||
},
|
||||
repr: function () {
|
||||
return "range(" + [start, stop, step].join(", ") + ")";
|
||||
},
|
||||
toString: MochiKit.Base.forwardCall("repr")
|
||||
};
|
||||
},
|
||||
|
||||
/** @id MochiKit.Iter.sum */
|
||||
sum: function (iterable, start/* = 0 */) {
|
||||
if (typeof(start) == "undefined" || start === null) {
|
||||
start = 0;
|
||||
}
|
||||
var x = start;
|
||||
var self = MochiKit.Iter;
|
||||
iterable = self.iter(iterable);
|
||||
try {
|
||||
while (true) {
|
||||
x += iterable.next();
|
||||
}
|
||||
} catch (e) {
|
||||
if (e != self.StopIteration) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
return x;
|
||||
},
|
||||
|
||||
/** @id MochiKit.Iter.exhaust */
|
||||
exhaust: function (iterable) {
|
||||
var self = MochiKit.Iter;
|
||||
iterable = self.iter(iterable);
|
||||
try {
|
||||
while (true) {
|
||||
iterable.next();
|
||||
}
|
||||
} catch (e) {
|
||||
if (e != self.StopIteration) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/** @id MochiKit.Iter.forEach */
|
||||
forEach: function (iterable, func, /* optional */obj) {
|
||||
var m = MochiKit.Base;
|
||||
var self = MochiKit.Iter;
|
||||
if (arguments.length > 2) {
|
||||
func = m.bind(func, obj);
|
||||
}
|
||||
// fast path for array
|
||||
if (m.isArrayLike(iterable) && !self.isIterable(iterable)) {
|
||||
try {
|
||||
for (var i = 0; i < iterable.length; i++) {
|
||||
func(iterable[i]);
|
||||
}
|
||||
} catch (e) {
|
||||
if (e != self.StopIteration) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.exhaust(self.imap(func, iterable));
|
||||
}
|
||||
},
|
||||
|
||||
/** @id MochiKit.Iter.every */
|
||||
every: function (iterable, func) {
|
||||
var self = MochiKit.Iter;
|
||||
try {
|
||||
self.ifilterfalse(func, iterable).next();
|
||||
return false;
|
||||
} catch (e) {
|
||||
if (e != self.StopIteration) {
|
||||
throw e;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
},
|
||||
|
||||
/** @id MochiKit.Iter.sorted */
|
||||
sorted: function (iterable, /* optional */cmp) {
|
||||
var rval = MochiKit.Iter.list(iterable);
|
||||
if (arguments.length == 1) {
|
||||
cmp = MochiKit.Base.compare;
|
||||
}
|
||||
rval.sort(cmp);
|
||||
return rval;
|
||||
},
|
||||
|
||||
/** @id MochiKit.Iter.reversed */
|
||||
reversed: function (iterable) {
|
||||
var rval = MochiKit.Iter.list(iterable);
|
||||
rval.reverse();
|
||||
return rval;
|
||||
},
|
||||
|
||||
/** @id MochiKit.Iter.some */
|
||||
some: function (iterable, func) {
|
||||
var self = MochiKit.Iter;
|
||||
try {
|
||||
self.ifilter(func, iterable).next();
|
||||
return true;
|
||||
} catch (e) {
|
||||
if (e != self.StopIteration) {
|
||||
throw e;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
/** @id MochiKit.Iter.iextend */
|
||||
iextend: function (lst, iterable) {
|
||||
var m = MochiKit.Base;
|
||||
var self = MochiKit.Iter;
|
||||
if (m.isArrayLike(iterable) && !self.isIterable(iterable)) {
|
||||
// fast-path for array-like
|
||||
for (var i = 0; i < iterable.length; i++) {
|
||||
lst.push(iterable[i]);
|
||||
}
|
||||
} else {
|
||||
iterable = self.iter(iterable);
|
||||
try {
|
||||
while (true) {
|
||||
lst.push(iterable.next());
|
||||
}
|
||||
} catch (e) {
|
||||
if (e != self.StopIteration) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
return lst;
|
||||
},
|
||||
|
||||
/** @id MochiKit.Iter.groupby */
|
||||
groupby: function(iterable, /* optional */ keyfunc) {
|
||||
var m = MochiKit.Base;
|
||||
var self = MochiKit.Iter;
|
||||
if (arguments.length < 2) {
|
||||
keyfunc = m.operator.identity;
|
||||
}
|
||||
iterable = self.iter(iterable);
|
||||
|
||||
// shared
|
||||
var pk = undefined;
|
||||
var k = undefined;
|
||||
var v;
|
||||
|
||||
function fetch() {
|
||||
v = iterable.next();
|
||||
k = keyfunc(v);
|
||||
};
|
||||
|
||||
function eat() {
|
||||
var ret = v;
|
||||
v = undefined;
|
||||
return ret;
|
||||
};
|
||||
|
||||
var first = true;
|
||||
var compare = m.compare;
|
||||
return {
|
||||
repr: function () { return "groupby(...)"; },
|
||||
next: function() {
|
||||
// iterator-next
|
||||
|
||||
// iterate until meet next group
|
||||
while (compare(k, pk) === 0) {
|
||||
fetch();
|
||||
if (first) {
|
||||
first = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
pk = k;
|
||||
return [k, {
|
||||
next: function() {
|
||||
// subiterator-next
|
||||
if (v == undefined) { // Is there something to eat?
|
||||
fetch();
|
||||
}
|
||||
if (compare(k, pk) !== 0) {
|
||||
throw self.StopIteration;
|
||||
}
|
||||
return eat();
|
||||
}
|
||||
}];
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
/** @id MochiKit.Iter.groupby_as_array */
|
||||
groupby_as_array: function (iterable, /* optional */ keyfunc) {
|
||||
var m = MochiKit.Base;
|
||||
var self = MochiKit.Iter;
|
||||
if (arguments.length < 2) {
|
||||
keyfunc = m.operator.identity;
|
||||
}
|
||||
|
||||
iterable = self.iter(iterable);
|
||||
var result = [];
|
||||
var first = true;
|
||||
var prev_key;
|
||||
var compare = m.compare;
|
||||
while (true) {
|
||||
try {
|
||||
var value = iterable.next();
|
||||
var key = keyfunc(value);
|
||||
} catch (e) {
|
||||
if (e == self.StopIteration) {
|
||||
break;
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
if (first || compare(key, prev_key) !== 0) {
|
||||
var values = [];
|
||||
result.push([key, values]);
|
||||
}
|
||||
values.push(value);
|
||||
first = false;
|
||||
prev_key = key;
|
||||
}
|
||||
return result;
|
||||
},
|
||||
|
||||
/** @id MochiKit.Iter.arrayLikeIter */
|
||||
arrayLikeIter: function (iterable) {
|
||||
var i = 0;
|
||||
return {
|
||||
repr: function () { return "arrayLikeIter(...)"; },
|
||||
toString: MochiKit.Base.forwardCall("repr"),
|
||||
next: function () {
|
||||
if (i >= iterable.length) {
|
||||
throw MochiKit.Iter.StopIteration;
|
||||
}
|
||||
return iterable[i++];
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
/** @id MochiKit.Iter.hasIterateNext */
|
||||
hasIterateNext: function (iterable) {
|
||||
return (iterable && typeof(iterable.iterateNext) == "function");
|
||||
},
|
||||
|
||||
/** @id MochiKit.Iter.iterateNextIter */
|
||||
iterateNextIter: function (iterable) {
|
||||
return {
|
||||
repr: function () { return "iterateNextIter(...)"; },
|
||||
toString: MochiKit.Base.forwardCall("repr"),
|
||||
next: function () {
|
||||
var rval = iterable.iterateNext();
|
||||
if (rval === null || rval === undefined) {
|
||||
throw MochiKit.Iter.StopIteration;
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
MochiKit.Iter.__new__ = function () {
|
||||
var m = MochiKit.Base;
|
||||
// Re-use StopIteration if exists (e.g. SpiderMonkey)
|
||||
if (typeof(StopIteration) != "undefined") {
|
||||
this.StopIteration = StopIteration;
|
||||
} else {
|
||||
/** @id MochiKit.Iter.StopIteration */
|
||||
this.StopIteration = new m.NamedError("StopIteration");
|
||||
}
|
||||
this.iteratorRegistry = new m.AdapterRegistry();
|
||||
// Register the iterator factory for arrays
|
||||
this.registerIteratorFactory(
|
||||
"arrayLike",
|
||||
m.isArrayLike,
|
||||
this.arrayLikeIter
|
||||
);
|
||||
|
||||
this.registerIteratorFactory(
|
||||
"iterateNext",
|
||||
this.hasIterateNext,
|
||||
this.iterateNextIter
|
||||
);
|
||||
|
||||
m.nameFunctions(this);
|
||||
|
||||
};
|
||||
|
||||
MochiKit.Iter.__new__();
|
||||
|
||||
//
|
||||
// XXX: Internet Explorer blows
|
||||
//
|
||||
if (MochiKit.__export__) {
|
||||
reduce = MochiKit.Iter.reduce;
|
||||
}
|
||||
|
||||
MochiKit.Base._exportSymbols(this, MochiKit.Iter);
|
||||
285
frontend/delta/js/MochiKit/Logging.js
Normal file
285
frontend/delta/js/MochiKit/Logging.js
Normal file
@@ -0,0 +1,285 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
/***
|
||||
|
||||
MochiKit.Logging 1.5
|
||||
|
||||
See <http://mochikit.com/> for documentation, downloads, license, etc.
|
||||
|
||||
(c) 2005 Bob Ippolito. All rights Reserved.
|
||||
|
||||
***/
|
||||
|
||||
MochiKit.Base.module(MochiKit, 'Logging', '1.5', ['Base']);
|
||||
|
||||
/** @id MochiKit.Logging.LogMessage */
|
||||
MochiKit.Logging.LogMessage = function (num, level, info) {
|
||||
this.num = num;
|
||||
this.level = level;
|
||||
this.info = info;
|
||||
this.timestamp = new Date();
|
||||
};
|
||||
|
||||
MochiKit.Logging.LogMessage.prototype = {
|
||||
/** @id MochiKit.Logging.LogMessage.prototype.repr */
|
||||
repr: function () {
|
||||
var m = MochiKit.Base;
|
||||
return 'LogMessage(' +
|
||||
m.map(
|
||||
m.repr,
|
||||
[this.num, this.level, this.info]
|
||||
).join(', ') + ')';
|
||||
},
|
||||
/** @id MochiKit.Logging.LogMessage.prototype.toString */
|
||||
toString: MochiKit.Base.forwardCall("repr")
|
||||
};
|
||||
|
||||
MochiKit.Base.update(MochiKit.Logging, {
|
||||
/** @id MochiKit.Logging.logLevelAtLeast */
|
||||
logLevelAtLeast: function (minLevel) {
|
||||
var self = MochiKit.Logging;
|
||||
if (typeof(minLevel) == 'string') {
|
||||
minLevel = self.LogLevel[minLevel];
|
||||
}
|
||||
return function (msg) {
|
||||
var msgLevel = msg.level;
|
||||
if (typeof(msgLevel) == 'string') {
|
||||
msgLevel = self.LogLevel[msgLevel];
|
||||
}
|
||||
return msgLevel >= minLevel;
|
||||
};
|
||||
},
|
||||
|
||||
/** @id MochiKit.Logging.isLogMessage */
|
||||
isLogMessage: function (/* ... */) {
|
||||
var LogMessage = MochiKit.Logging.LogMessage;
|
||||
for (var i = 0; i < arguments.length; i++) {
|
||||
if (!(arguments[i] instanceof LogMessage)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
/** @id MochiKit.Logging.compareLogMessage */
|
||||
compareLogMessage: function (a, b) {
|
||||
return MochiKit.Base.compare([a.level, a.info], [b.level, b.info]);
|
||||
},
|
||||
|
||||
/** @id MochiKit.Logging.alertListener */
|
||||
alertListener: function (msg) {
|
||||
alert(
|
||||
"num: " + msg.num +
|
||||
"\nlevel: " + msg.level +
|
||||
"\ninfo: " + msg.info.join(" ")
|
||||
);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
/** @id MochiKit.Logging.Logger */
|
||||
MochiKit.Logging.Logger = function (/* optional */maxSize) {
|
||||
this.counter = 0;
|
||||
if (typeof(maxSize) == 'undefined' || maxSize === null) {
|
||||
maxSize = -1;
|
||||
}
|
||||
this.maxSize = maxSize;
|
||||
this._messages = [];
|
||||
this.listeners = {};
|
||||
this.useNativeConsole = false;
|
||||
};
|
||||
|
||||
MochiKit.Logging.Logger.prototype = {
|
||||
/** @id MochiKit.Logging.Logger.prototype.clear */
|
||||
clear: function () {
|
||||
this._messages.splice(0, this._messages.length);
|
||||
},
|
||||
|
||||
/** @id MochiKit.Logging.Logger.prototype.logToConsole */
|
||||
logToConsole: function (msg) {
|
||||
if (typeof(window) != "undefined" && window.console
|
||||
&& window.console.log) {
|
||||
// Safari and FireBug 0.4
|
||||
// Percent replacement is a workaround for cute Safari crashing bug
|
||||
window.console.log(msg.replace(/%/g, '\uFF05'));
|
||||
} else if (typeof(opera) != "undefined" && opera.postError) {
|
||||
// Opera
|
||||
opera.postError(msg);
|
||||
} else if (typeof(Debug) != "undefined" && Debug.writeln) {
|
||||
// IE Web Development Helper (?)
|
||||
// http://www.nikhilk.net/Entry.aspx?id=93
|
||||
Debug.writeln(msg);
|
||||
} else if (typeof(debug) != "undefined" && debug.trace) {
|
||||
// Atlas framework (?)
|
||||
// http://www.nikhilk.net/Entry.aspx?id=93
|
||||
debug.trace(msg);
|
||||
}
|
||||
},
|
||||
|
||||
/** @id MochiKit.Logging.Logger.prototype.dispatchListeners */
|
||||
dispatchListeners: function (msg) {
|
||||
for (var k in this.listeners) {
|
||||
var pair = this.listeners[k];
|
||||
if (pair.ident != k || (pair[0] && !pair[0](msg))) {
|
||||
continue;
|
||||
}
|
||||
pair[1](msg);
|
||||
}
|
||||
},
|
||||
|
||||
/** @id MochiKit.Logging.Logger.prototype.addListener */
|
||||
addListener: function (ident, filter, listener) {
|
||||
if (typeof(filter) == 'string') {
|
||||
filter = MochiKit.Logging.logLevelAtLeast(filter);
|
||||
}
|
||||
var entry = [filter, listener];
|
||||
entry.ident = ident;
|
||||
this.listeners[ident] = entry;
|
||||
},
|
||||
|
||||
/** @id MochiKit.Logging.Logger.prototype.removeListener */
|
||||
removeListener: function (ident) {
|
||||
delete this.listeners[ident];
|
||||
},
|
||||
|
||||
/** @id MochiKit.Logging.Logger.prototype.baseLog */
|
||||
baseLog: function (level, message/*, ...*/) {
|
||||
if (typeof(level) == "number") {
|
||||
if (level >= MochiKit.Logging.LogLevel.FATAL) {
|
||||
level = 'FATAL';
|
||||
} else if (level >= MochiKit.Logging.LogLevel.ERROR) {
|
||||
level = 'ERROR';
|
||||
} else if (level >= MochiKit.Logging.LogLevel.WARNING) {
|
||||
level = 'WARNING';
|
||||
} else if (level >= MochiKit.Logging.LogLevel.INFO) {
|
||||
level = 'INFO';
|
||||
} else {
|
||||
level = 'DEBUG';
|
||||
}
|
||||
}
|
||||
var msg = new MochiKit.Logging.LogMessage(
|
||||
this.counter,
|
||||
level,
|
||||
MochiKit.Base.extend(null, arguments, 1)
|
||||
);
|
||||
this._messages.push(msg);
|
||||
this.dispatchListeners(msg);
|
||||
if (this.useNativeConsole) {
|
||||
this.logToConsole(msg.level + ": " + msg.info.join(" "));
|
||||
}
|
||||
this.counter += 1;
|
||||
while (this.maxSize >= 0 && this._messages.length > this.maxSize) {
|
||||
this._messages.shift();
|
||||
}
|
||||
},
|
||||
|
||||
/** @id MochiKit.Logging.Logger.prototype.getMessages */
|
||||
getMessages: function (howMany) {
|
||||
var firstMsg = 0;
|
||||
if (!(typeof(howMany) == 'undefined' || howMany === null)) {
|
||||
firstMsg = Math.max(0, this._messages.length - howMany);
|
||||
}
|
||||
return this._messages.slice(firstMsg);
|
||||
},
|
||||
|
||||
/** @id MochiKit.Logging.Logger.prototype.getMessageText */
|
||||
getMessageText: function (howMany) {
|
||||
if (typeof(howMany) == 'undefined' || howMany === null) {
|
||||
howMany = 30;
|
||||
}
|
||||
var messages = this.getMessages(howMany);
|
||||
if (messages.length) {
|
||||
var lst = MochiKit.Base.map(function (m) {
|
||||
return '\n [' + m.num + '] ' + m.level + ': ' + m.info.join(' ');
|
||||
}, messages);
|
||||
lst.unshift('LAST ' + messages.length + ' MESSAGES:');
|
||||
return lst.join('');
|
||||
}
|
||||
return '';
|
||||
},
|
||||
|
||||
/** @id MochiKit.Logging.Logger.prototype.debuggingBookmarklet */
|
||||
debuggingBookmarklet: function (inline) {
|
||||
if (typeof(MochiKit.LoggingPane) == "undefined") {
|
||||
alert(this.getMessageText());
|
||||
} else {
|
||||
MochiKit.LoggingPane.createLoggingPane(inline || false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
MochiKit.Logging.__new__ = function () {
|
||||
this.LogLevel = {
|
||||
ERROR: 40,
|
||||
FATAL: 50,
|
||||
WARNING: 30,
|
||||
INFO: 20,
|
||||
DEBUG: 10
|
||||
};
|
||||
|
||||
var m = MochiKit.Base;
|
||||
m.registerComparator("LogMessage",
|
||||
this.isLogMessage,
|
||||
this.compareLogMessage
|
||||
);
|
||||
|
||||
var partial = m.partial;
|
||||
|
||||
var Logger = this.Logger;
|
||||
var baseLog = Logger.prototype.baseLog;
|
||||
m.update(this.Logger.prototype, {
|
||||
debug: partial(baseLog, 'DEBUG'),
|
||||
log: partial(baseLog, 'INFO'),
|
||||
error: partial(baseLog, 'ERROR'),
|
||||
fatal: partial(baseLog, 'FATAL'),
|
||||
warning: partial(baseLog, 'WARNING')
|
||||
});
|
||||
|
||||
// indirectly find logger so it can be replaced
|
||||
var self = this;
|
||||
var connectLog = function (name) {
|
||||
return function () {
|
||||
self.logger[name].apply(self.logger, arguments);
|
||||
};
|
||||
};
|
||||
|
||||
/** @id MochiKit.Logging.log */
|
||||
this.log = connectLog('log');
|
||||
/** @id MochiKit.Logging.logError */
|
||||
this.logError = connectLog('error');
|
||||
/** @id MochiKit.Logging.logDebug */
|
||||
this.logDebug = connectLog('debug');
|
||||
/** @id MochiKit.Logging.logFatal */
|
||||
this.logFatal = connectLog('fatal');
|
||||
/** @id MochiKit.Logging.logWarning */
|
||||
this.logWarning = connectLog('warning');
|
||||
this.logger = new Logger();
|
||||
this.logger.useNativeConsole = true;
|
||||
|
||||
m.nameFunctions(this);
|
||||
};
|
||||
|
||||
MochiKit.Logging.__new__();
|
||||
|
||||
MochiKit.Base._exportSymbols(this, MochiKit.Logging);
|
||||
353
frontend/delta/js/MochiKit/LoggingPane.js
Normal file
353
frontend/delta/js/MochiKit/LoggingPane.js
Normal file
@@ -0,0 +1,353 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
/***
|
||||
|
||||
MochiKit.LoggingPane 1.5
|
||||
|
||||
See <http://mochikit.com/> for documentation, downloads, license, etc.
|
||||
|
||||
(c) 2005 Bob Ippolito. All rights Reserved.
|
||||
|
||||
***/
|
||||
|
||||
MochiKit.Base.module(MochiKit, 'LoggingPane', '1.5', ['Base', 'Logging']);
|
||||
|
||||
/** @id MochiKit.LoggingPane.createLoggingPane */
|
||||
MochiKit.LoggingPane.createLoggingPane = function (inline/* = false */) {
|
||||
var m = MochiKit.LoggingPane;
|
||||
inline = !(!inline);
|
||||
if (m._loggingPane && m._loggingPane.inline != inline) {
|
||||
m._loggingPane.closePane();
|
||||
m._loggingPane = null;
|
||||
}
|
||||
if (!m._loggingPane || m._loggingPane.closed) {
|
||||
m._loggingPane = new m.LoggingPane(inline, MochiKit.Logging.logger);
|
||||
}
|
||||
return m._loggingPane;
|
||||
};
|
||||
|
||||
/**
|
||||
* @id MochiKit.LoggingPane.LoggingPane
|
||||
* @constructor
|
||||
*/
|
||||
MochiKit.LoggingPane.LoggingPane = function (inline/* = false */, logger/* = MochiKit.Logging.logger */) {
|
||||
|
||||
/* Use a div if inline, pop up a window if not */
|
||||
/* Create the elements */
|
||||
if (typeof(logger) == "undefined" || logger === null) {
|
||||
logger = MochiKit.Logging.logger;
|
||||
}
|
||||
this.logger = logger;
|
||||
var update = MochiKit.Base.update;
|
||||
var updatetree = MochiKit.Base.updatetree;
|
||||
var bind = MochiKit.Base.bind;
|
||||
var clone = MochiKit.Base.clone;
|
||||
var win = window;
|
||||
var uid = "_MochiKit_LoggingPane";
|
||||
if (typeof(MochiKit.DOM) != "undefined") {
|
||||
win = MochiKit.DOM.currentWindow();
|
||||
}
|
||||
if (!inline) {
|
||||
// name the popup with the base URL for uniqueness
|
||||
var url = win.location.href.split("?")[0].replace(/[#:\/.><&%-]/g, "_");
|
||||
var name = uid + "_" + url;
|
||||
var nwin = win.open("", name, "dependent,resizable,height=200");
|
||||
if (!nwin) {
|
||||
alert("Not able to open debugging window due to pop-up blocking.");
|
||||
return undefined;
|
||||
}
|
||||
nwin.document.write(
|
||||
'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" '
|
||||
+ '"http://www.w3.org/TR/html4/loose.dtd">'
|
||||
+ '<html><head><title>[MochiKit.LoggingPane]</title></head>'
|
||||
+ '<body></body></html>'
|
||||
);
|
||||
nwin.document.close();
|
||||
nwin.document.title += ' ' + win.document.title;
|
||||
win = nwin;
|
||||
}
|
||||
var doc = win.document;
|
||||
this.doc = doc;
|
||||
|
||||
// Connect to the debug pane if it already exists (i.e. in a window orphaned by the page being refreshed)
|
||||
var debugPane = doc.getElementById(uid);
|
||||
var existing_pane = !!debugPane;
|
||||
if (debugPane && typeof(debugPane.loggingPane) != "undefined") {
|
||||
debugPane.loggingPane.logger = this.logger;
|
||||
debugPane.loggingPane.buildAndApplyFilter();
|
||||
return debugPane.loggingPane;
|
||||
}
|
||||
|
||||
if (existing_pane) {
|
||||
// clear any existing contents
|
||||
var child;
|
||||
while ((child = debugPane.firstChild)) {
|
||||
debugPane.removeChild(child);
|
||||
}
|
||||
} else {
|
||||
debugPane = doc.createElement("div");
|
||||
debugPane.id = uid;
|
||||
}
|
||||
debugPane.loggingPane = this;
|
||||
var levelFilterField = doc.createElement("input");
|
||||
var infoFilterField = doc.createElement("input");
|
||||
var filterButton = doc.createElement("button");
|
||||
var loadButton = doc.createElement("button");
|
||||
var clearButton = doc.createElement("button");
|
||||
var closeButton = doc.createElement("button");
|
||||
var logPaneArea = doc.createElement("div");
|
||||
var logPane = doc.createElement("div");
|
||||
|
||||
/* Set up the functions */
|
||||
var listenerId = uid + "_Listener";
|
||||
this.colorTable = clone(this.colorTable);
|
||||
var messages = [];
|
||||
var messageFilter = null;
|
||||
|
||||
/** @id MochiKit.LoggingPane.messageLevel */
|
||||
var messageLevel = function (msg) {
|
||||
var level = msg.level;
|
||||
if (typeof(level) == "number") {
|
||||
level = MochiKit.Logging.LogLevel[level];
|
||||
}
|
||||
return level;
|
||||
};
|
||||
|
||||
/** @id MochiKit.LoggingPane.messageText */
|
||||
var messageText = function (msg) {
|
||||
return msg.info.join(" ");
|
||||
};
|
||||
|
||||
/** @id MochiKit.LoggingPane.addMessageText */
|
||||
var addMessageText = bind(function (msg) {
|
||||
var level = messageLevel(msg);
|
||||
var text = messageText(msg);
|
||||
var c = this.colorTable[level];
|
||||
var p = doc.createElement("span");
|
||||
p.className = "MochiKit-LogMessage MochiKit-LogLevel-" + level;
|
||||
p.style.cssText = "margin: 0px; white-space: -moz-pre-wrap; white-space: -o-pre-wrap; white-space: pre-wrap; white-space: pre-line; word-wrap: break-word; wrap-option: emergency; color: " + c;
|
||||
p.appendChild(doc.createTextNode(level + ": " + text));
|
||||
logPane.appendChild(p);
|
||||
logPane.appendChild(doc.createElement("br"));
|
||||
if (logPaneArea.offsetHeight > logPaneArea.scrollHeight) {
|
||||
logPaneArea.scrollTop = 0;
|
||||
} else {
|
||||
logPaneArea.scrollTop = logPaneArea.scrollHeight;
|
||||
}
|
||||
}, this);
|
||||
|
||||
/** @id MochiKit.LoggingPane.addMessage */
|
||||
var addMessage = function (msg) {
|
||||
messages[messages.length] = msg;
|
||||
addMessageText(msg);
|
||||
};
|
||||
|
||||
/** @id MochiKit.LoggingPane.buildMessageFilter */
|
||||
var buildMessageFilter = function () {
|
||||
var levelre, infore;
|
||||
try {
|
||||
/* Catch any exceptions that might arise due to invalid regexes */
|
||||
levelre = new RegExp(levelFilterField.value);
|
||||
infore = new RegExp(infoFilterField.value);
|
||||
} catch(e) {
|
||||
/* If there was an error with the regexes, do no filtering */
|
||||
MochiKit.Logging.logDebug("Error in filter regex: " + e.message);
|
||||
return null;
|
||||
}
|
||||
|
||||
return function (msg) {
|
||||
return (
|
||||
levelre.test(messageLevel(msg)) &&
|
||||
infore.test(messageText(msg))
|
||||
);
|
||||
};
|
||||
};
|
||||
|
||||
/** @id MochiKit.LoggingPane.clearMessagePane */
|
||||
var clearMessagePane = function () {
|
||||
while (logPane.firstChild) {
|
||||
logPane.removeChild(logPane.firstChild);
|
||||
}
|
||||
};
|
||||
|
||||
/** @id MochiKit.LoggingPane.clearMessages */
|
||||
var clearMessages = function () {
|
||||
messages = [];
|
||||
clearMessagePane();
|
||||
};
|
||||
|
||||
/** @id MochiKit.LoggingPane.closePane */
|
||||
var closePane = bind(function () {
|
||||
if (this.closed) {
|
||||
return;
|
||||
}
|
||||
this.closed = true;
|
||||
if (MochiKit.LoggingPane._loggingPane == this) {
|
||||
MochiKit.LoggingPane._loggingPane = null;
|
||||
}
|
||||
this.logger.removeListener(listenerId);
|
||||
try {
|
||||
try {
|
||||
debugPane.loggingPane = null;
|
||||
} catch(e) { MochiKit.Logging.logFatal("Bookmarklet was closed incorrectly."); }
|
||||
if (inline) {
|
||||
debugPane.parentNode.removeChild(debugPane);
|
||||
} else {
|
||||
this.win.close();
|
||||
}
|
||||
} catch(e) {}
|
||||
}, this);
|
||||
|
||||
/** @id MochiKit.LoggingPane.filterMessages */
|
||||
var filterMessages = function () {
|
||||
clearMessagePane();
|
||||
|
||||
for (var i = 0; i < messages.length; i++) {
|
||||
var msg = messages[i];
|
||||
if (messageFilter === null || messageFilter(msg)) {
|
||||
addMessageText(msg);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.buildAndApplyFilter = function () {
|
||||
messageFilter = buildMessageFilter();
|
||||
|
||||
filterMessages();
|
||||
|
||||
this.logger.removeListener(listenerId);
|
||||
this.logger.addListener(listenerId, messageFilter, addMessage);
|
||||
};
|
||||
|
||||
|
||||
/** @id MochiKit.LoggingPane.loadMessages */
|
||||
var loadMessages = bind(function () {
|
||||
messages = this.logger.getMessages();
|
||||
filterMessages();
|
||||
}, this);
|
||||
|
||||
/** @id MochiKit.LoggingPane.filterOnEnter */
|
||||
var filterOnEnter = bind(function (event) {
|
||||
event = event || window.event;
|
||||
var key = event.which || event.keyCode;
|
||||
if (key == 13) {
|
||||
this.buildAndApplyFilter();
|
||||
}
|
||||
}, this);
|
||||
|
||||
/* Create the debug pane */
|
||||
var style = "display: block; z-index: 1000; left: 0px; bottom: 0px; position: fixed; width: 100%; background-color: white; font: " + this.logFont;
|
||||
if (inline) {
|
||||
style += "; height: 10em; border-top: 2px solid black";
|
||||
} else {
|
||||
style += "; height: 100%;";
|
||||
}
|
||||
debugPane.style.cssText = style;
|
||||
|
||||
if (!existing_pane) {
|
||||
doc.body.appendChild(debugPane);
|
||||
}
|
||||
|
||||
/* Create the filter fields */
|
||||
style = {"cssText": "width: 33%; display: inline; font: " + this.logFont};
|
||||
|
||||
updatetree(levelFilterField, {
|
||||
"value": "FATAL|ERROR|WARNING|INFO|DEBUG",
|
||||
"onkeypress": filterOnEnter,
|
||||
"style": style
|
||||
});
|
||||
debugPane.appendChild(levelFilterField);
|
||||
|
||||
updatetree(infoFilterField, {
|
||||
"value": ".*",
|
||||
"onkeypress": filterOnEnter,
|
||||
"style": style
|
||||
});
|
||||
debugPane.appendChild(infoFilterField);
|
||||
|
||||
/* Create the buttons */
|
||||
style = "width: 8%; display:inline; font: " + this.logFont;
|
||||
|
||||
filterButton.appendChild(doc.createTextNode("Filter"));
|
||||
filterButton.onclick = bind("buildAndApplyFilter", this);
|
||||
filterButton.style.cssText = style;
|
||||
debugPane.appendChild(filterButton);
|
||||
|
||||
loadButton.appendChild(doc.createTextNode("Load"));
|
||||
loadButton.onclick = loadMessages;
|
||||
loadButton.style.cssText = style;
|
||||
debugPane.appendChild(loadButton);
|
||||
|
||||
clearButton.appendChild(doc.createTextNode("Clear"));
|
||||
clearButton.onclick = clearMessages;
|
||||
clearButton.style.cssText = style;
|
||||
debugPane.appendChild(clearButton);
|
||||
|
||||
closeButton.appendChild(doc.createTextNode("Close"));
|
||||
closeButton.onclick = closePane;
|
||||
closeButton.style.cssText = style;
|
||||
debugPane.appendChild(closeButton);
|
||||
|
||||
/* Create the logging pane */
|
||||
logPaneArea.style.cssText = "overflow: auto; width: 100%";
|
||||
logPane.style.cssText = "width: 100%; height: " + (inline ? "8em" : "100%");
|
||||
|
||||
logPaneArea.appendChild(logPane);
|
||||
debugPane.appendChild(logPaneArea);
|
||||
|
||||
this.buildAndApplyFilter();
|
||||
loadMessages();
|
||||
|
||||
if (inline) {
|
||||
this.win = undefined;
|
||||
} else {
|
||||
this.win = win;
|
||||
}
|
||||
this.inline = inline;
|
||||
this.closePane = closePane;
|
||||
this.closed = false;
|
||||
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
MochiKit.LoggingPane.LoggingPane.prototype = {
|
||||
"logFont": "8pt Verdana,sans-serif",
|
||||
"colorTable": {
|
||||
"ERROR": "red",
|
||||
"FATAL": "darkred",
|
||||
"WARNING": "blue",
|
||||
"INFO": "black",
|
||||
"DEBUG": "green"
|
||||
}
|
||||
};
|
||||
|
||||
MochiKit.LoggingPane.__new__ = function () {
|
||||
MochiKit.Base.nameFunctions(this);
|
||||
MochiKit.LoggingPane._loggingPane = null;
|
||||
};
|
||||
|
||||
MochiKit.LoggingPane.__new__();
|
||||
|
||||
MochiKit.Base._exportSymbols(this, MochiKit.LoggingPane);
|
||||
156
frontend/delta/js/MochiKit/MochiKit.js
vendored
Normal file
156
frontend/delta/js/MochiKit/MochiKit.js
vendored
Normal file
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
/***
|
||||
|
||||
MochiKit.MochiKit 1.5
|
||||
|
||||
See <http://mochikit.com/> for documentation, downloads, license, etc.
|
||||
|
||||
(c) 2005 Bob Ippolito. All rights Reserved.
|
||||
|
||||
***/
|
||||
|
||||
var MochiKit = MochiKit || {};
|
||||
|
||||
/** @id MochiKit.MochiKit */
|
||||
MochiKit.MochiKit = MochiKit.MochiKit || {};
|
||||
|
||||
MochiKit.MochiKit.NAME = "MochiKit.MochiKit";
|
||||
MochiKit.MochiKit.VERSION = "1.5";
|
||||
MochiKit.MochiKit.__export__ = false;
|
||||
MochiKit.MochiKit.__repr__ = function () {
|
||||
return "[" + this.NAME + " " + this.VERSION + "]";
|
||||
};
|
||||
|
||||
/** @id MochiKit.MochiKit.toString */
|
||||
MochiKit.MochiKit.toString = function () {
|
||||
return this.__repr__();
|
||||
};
|
||||
|
||||
/** @id MochiKit.MochiKit.SUBMODULES */
|
||||
MochiKit.MochiKit.SUBMODULES = [
|
||||
"Base",
|
||||
"Iter",
|
||||
"Logging",
|
||||
"DateTime",
|
||||
"Format",
|
||||
"Text",
|
||||
"Async",
|
||||
"DOM",
|
||||
"Selector",
|
||||
"Style",
|
||||
"LoggingPane",
|
||||
"Color",
|
||||
"Signal",
|
||||
"Position",
|
||||
"Visual",
|
||||
"DragAndDrop",
|
||||
"Sortable"
|
||||
];
|
||||
|
||||
(function () {
|
||||
if (typeof(document) == "undefined") {
|
||||
return;
|
||||
}
|
||||
var scripts = document.getElementsByTagName("script");
|
||||
var kXHTMLNSURI = "http://www.w3.org/1999/xhtml";
|
||||
var kSVGNSURI = "http://www.w3.org/2000/svg";
|
||||
var kXLINKNSURI = "http://www.w3.org/1999/xlink";
|
||||
var kXULNSURI = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||
var base = null;
|
||||
var baseElem = null;
|
||||
var allScripts = {};
|
||||
var i;
|
||||
var src;
|
||||
for (i = 0; i < scripts.length; i++) {
|
||||
src = null;
|
||||
switch (scripts[i].namespaceURI) {
|
||||
case kSVGNSURI:
|
||||
src = scripts[i].getAttributeNS(kXLINKNSURI, "href");
|
||||
break;
|
||||
/*
|
||||
case null: // HTML
|
||||
case '': // HTML
|
||||
case kXHTMLNSURI:
|
||||
case kXULNSURI:
|
||||
*/
|
||||
default:
|
||||
src = scripts[i].getAttribute("src");
|
||||
break;
|
||||
}
|
||||
if (!src) {
|
||||
continue;
|
||||
}
|
||||
allScripts[src] = true;
|
||||
if (src.match(/MochiKit.js(\?.*)?$/)) {
|
||||
base = src.substring(0, src.lastIndexOf('MochiKit.js'));
|
||||
baseElem = scripts[i];
|
||||
}
|
||||
}
|
||||
if (base === null) {
|
||||
return;
|
||||
}
|
||||
var modules = MochiKit.MochiKit.SUBMODULES;
|
||||
for (var i = 0; i < modules.length; i++) {
|
||||
if (MochiKit[modules[i]]) {
|
||||
continue;
|
||||
}
|
||||
var uri = base + modules[i] + '.js';
|
||||
if (uri in allScripts) {
|
||||
continue;
|
||||
}
|
||||
if (baseElem.namespaceURI == kSVGNSURI ||
|
||||
baseElem.namespaceURI == kXULNSURI) {
|
||||
// SVG, XUL
|
||||
/*
|
||||
SVG does not support document.write, so if Safari wants to
|
||||
support SVG tests it should fix its deferred loading bug
|
||||
(see following below).
|
||||
*/
|
||||
var s = document.createElementNS(baseElem.namespaceURI, 'script');
|
||||
s.setAttribute("id", "MochiKit_" + base + modules[i]);
|
||||
if (baseElem.namespaceURI == kSVGNSURI) {
|
||||
s.setAttributeNS(kXLINKNSURI, 'href', uri);
|
||||
} else {
|
||||
s.setAttribute('src', uri);
|
||||
}
|
||||
s.setAttribute("type", "application/x-javascript");
|
||||
baseElem.parentNode.appendChild(s);
|
||||
} else {
|
||||
// HTML, XHTML
|
||||
/*
|
||||
DOM can not be used here because Safari does
|
||||
deferred loading of scripts unless they are
|
||||
in the document or inserted with document.write
|
||||
|
||||
This is not XHTML compliant. If you want XHTML
|
||||
compliance then you must use the packed version of MochiKit
|
||||
or include each script individually (basically unroll
|
||||
these document.write calls into your XHTML source)
|
||||
*/
|
||||
document.write('<' + baseElem.nodeName + ' src="' + uri +
|
||||
'" type="text/javascript"></script>');
|
||||
}
|
||||
};
|
||||
})();
|
||||
135
frontend/delta/js/MochiKit/MockDOM.js
Normal file
135
frontend/delta/js/MochiKit/MockDOM.js
Normal file
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
/***
|
||||
|
||||
MochiKit.MockDOM 1.5
|
||||
|
||||
See <http://mochikit.com/> for documentation, downloads, license, etc.
|
||||
|
||||
(c) 2005 Bob Ippolito. All rights Reserved.
|
||||
|
||||
***/
|
||||
|
||||
var MochiKit = MochiKit || {};
|
||||
|
||||
MochiKit.MockDOM = MochiKit.MockDOM || {};
|
||||
|
||||
MochiKit.MockDOM.NAME = "MochiKit.MockDOM";
|
||||
MochiKit.MockDOM.VERSION = "1.5";
|
||||
MochiKit.MockDOM.__export__ = false;
|
||||
|
||||
MochiKit.MockDOM.__repr__ = function () {
|
||||
return "[" + this.NAME + " " + this.VERSION + "]";
|
||||
};
|
||||
|
||||
/** @id MochiKit.MockDOM.toString */
|
||||
MochiKit.MockDOM.toString = function () {
|
||||
return this.__repr__();
|
||||
};
|
||||
|
||||
/** @id MochiKit.MockDOM.createDocument */
|
||||
MochiKit.MockDOM.createDocument = function () {
|
||||
var doc = new MochiKit.MockDOM.MockElement("DOCUMENT");
|
||||
doc.body = doc.createElement("BODY");
|
||||
doc.appendChild(doc.body);
|
||||
return doc;
|
||||
};
|
||||
|
||||
/** @id MochiKit.MockDOM.MockElement */
|
||||
MochiKit.MockDOM.MockElement = function (name, data, ownerDocument) {
|
||||
this.tagName = this.nodeName = name.toUpperCase();
|
||||
this.ownerDocument = ownerDocument || null;
|
||||
if (name == "DOCUMENT") {
|
||||
this.nodeType = 9;
|
||||
this.childNodes = [];
|
||||
} else if (typeof(data) == "string") {
|
||||
this.nodeValue = data;
|
||||
this.nodeType = 3;
|
||||
} else {
|
||||
this.nodeType = 1;
|
||||
this.childNodes = [];
|
||||
}
|
||||
if (name.substring(0, 1) == "<") {
|
||||
var nameattr = name.substring(
|
||||
name.indexOf('"') + 1, name.lastIndexOf('"'));
|
||||
name = name.substring(1, name.indexOf(" "));
|
||||
this.tagName = this.nodeName = name.toUpperCase();
|
||||
this.setAttribute("name", nameattr);
|
||||
}
|
||||
};
|
||||
|
||||
MochiKit.MockDOM.MockElement.prototype = {
|
||||
/** @id MochiKit.MockDOM.MockElement.prototype.createElement */
|
||||
createElement: function (tagName) {
|
||||
return new MochiKit.MockDOM.MockElement(tagName, null, this.nodeType == 9 ? this : this.ownerDocument);
|
||||
},
|
||||
/** @id MochiKit.MockDOM.MockElement.prototype.createTextNode */
|
||||
createTextNode: function (text) {
|
||||
return new MochiKit.MockDOM.MockElement("text", text, this.nodeType == 9 ? this : this.ownerDocument);
|
||||
},
|
||||
/** @id MochiKit.MockDOM.MockElement.prototype.setAttribute */
|
||||
setAttribute: function (name, value) {
|
||||
this[name] = value;
|
||||
},
|
||||
/** @id MochiKit.MockDOM.MockElement.prototype.getAttribute */
|
||||
getAttribute: function (name) {
|
||||
return this[name];
|
||||
},
|
||||
/** @id MochiKit.MockDOM.MockElement.prototype.appendChild */
|
||||
appendChild: function (child) {
|
||||
this.childNodes.push(child);
|
||||
},
|
||||
/** @id MochiKit.MockDOM.MockElement.prototype.toString */
|
||||
toString: function () {
|
||||
return "MockElement(" + this.tagName + ")";
|
||||
},
|
||||
/** @id MochiKit.MockDOM.MockElement.prototype.getElementsByTagName */
|
||||
getElementsByTagName: function (tagName) {
|
||||
var foundElements = [];
|
||||
MochiKit.Base.nodeWalk(this, function(node){
|
||||
if (tagName == '*' || tagName == node.tagName) {
|
||||
foundElements.push(node);
|
||||
return node.childNodes;
|
||||
}
|
||||
});
|
||||
return foundElements;
|
||||
}
|
||||
};
|
||||
|
||||
/** @id MochiKit.MockDOM.EXPORT_OK */
|
||||
MochiKit.MockDOM.EXPORT_OK = [
|
||||
"mockElement",
|
||||
"createDocument"
|
||||
];
|
||||
|
||||
/** @id MochiKit.MockDOM.EXPORT */
|
||||
MochiKit.MockDOM.EXPORT = [
|
||||
"document"
|
||||
];
|
||||
|
||||
MochiKit.MockDOM.__new__ = function () {
|
||||
this.document = this.createDocument();
|
||||
};
|
||||
|
||||
MochiKit.MockDOM.__new__();
|
||||
241
frontend/delta/js/MochiKit/Position.js
Normal file
241
frontend/delta/js/MochiKit/Position.js
Normal file
@@ -0,0 +1,241 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
/***
|
||||
|
||||
MochiKit.Position 1.5
|
||||
|
||||
See <http://mochikit.com/> for documentation, downloads, license, etc.
|
||||
|
||||
(c) 2005-2006 Bob Ippolito and others. All rights Reserved.
|
||||
|
||||
***/
|
||||
|
||||
MochiKit.Base.module(MochiKit, 'Position', '1.5', ['Base', 'DOM', 'Style']);
|
||||
|
||||
MochiKit.Base.update(MochiKit.Position, {
|
||||
// Don't export from this module
|
||||
__export__: false,
|
||||
|
||||
// set to true if needed, warning: firefox performance problems
|
||||
// NOT neeeded for page scrolling, only if draggable contained in
|
||||
// scrollable elements
|
||||
includeScrollOffsets: false,
|
||||
|
||||
/** @id MochiKit.Position.prepare */
|
||||
prepare: function () {
|
||||
var deltaX = window.pageXOffset
|
||||
|| document.documentElement.scrollLeft
|
||||
|| document.body.scrollLeft
|
||||
|| 0;
|
||||
var deltaY = window.pageYOffset
|
||||
|| document.documentElement.scrollTop
|
||||
|| document.body.scrollTop
|
||||
|| 0;
|
||||
this.windowOffset = new MochiKit.Style.Coordinates(deltaX, deltaY);
|
||||
},
|
||||
|
||||
/** @id MochiKit.Position.cumulativeOffset */
|
||||
cumulativeOffset: function (element) {
|
||||
var valueT = 0;
|
||||
var valueL = 0;
|
||||
do {
|
||||
valueT += element.offsetTop || 0;
|
||||
valueL += element.offsetLeft || 0;
|
||||
element = element.offsetParent;
|
||||
} while (element);
|
||||
return new MochiKit.Style.Coordinates(valueL, valueT);
|
||||
},
|
||||
|
||||
/** @id MochiKit.Position.realOffset */
|
||||
realOffset: function (element) {
|
||||
var valueT = 0;
|
||||
var valueL = 0;
|
||||
do {
|
||||
valueT += element.scrollTop || 0;
|
||||
valueL += element.scrollLeft || 0;
|
||||
element = element.parentNode;
|
||||
} while (element);
|
||||
return new MochiKit.Style.Coordinates(valueL, valueT);
|
||||
},
|
||||
|
||||
/** @id MochiKit.Position.within */
|
||||
within: function (element, x, y) {
|
||||
if (this.includeScrollOffsets) {
|
||||
return this.withinIncludingScrolloffsets(element, x, y);
|
||||
}
|
||||
this.xcomp = x;
|
||||
this.ycomp = y;
|
||||
this.offset = this.cumulativeOffset(element);
|
||||
if (element.style.position == "fixed") {
|
||||
this.offset.x += this.windowOffset.x;
|
||||
this.offset.y += this.windowOffset.y;
|
||||
}
|
||||
|
||||
return (y >= this.offset.y &&
|
||||
y < this.offset.y + element.offsetHeight &&
|
||||
x >= this.offset.x &&
|
||||
x < this.offset.x + element.offsetWidth);
|
||||
},
|
||||
|
||||
/** @id MochiKit.Position.withinIncludingScrolloffsets */
|
||||
withinIncludingScrolloffsets: function (element, x, y) {
|
||||
var offsetcache = this.realOffset(element);
|
||||
|
||||
this.xcomp = x + offsetcache.x - this.windowOffset.x;
|
||||
this.ycomp = y + offsetcache.y - this.windowOffset.y;
|
||||
this.offset = this.cumulativeOffset(element);
|
||||
|
||||
return (this.ycomp >= this.offset.y &&
|
||||
this.ycomp < this.offset.y + element.offsetHeight &&
|
||||
this.xcomp >= this.offset.x &&
|
||||
this.xcomp < this.offset.x + element.offsetWidth);
|
||||
},
|
||||
|
||||
// within must be called directly before
|
||||
/** @id MochiKit.Position.overlap */
|
||||
overlap: function (mode, element) {
|
||||
if (!mode) {
|
||||
return 0;
|
||||
}
|
||||
if (mode == 'vertical') {
|
||||
return ((this.offset.y + element.offsetHeight) - this.ycomp) /
|
||||
element.offsetHeight;
|
||||
}
|
||||
if (mode == 'horizontal') {
|
||||
return ((this.offset.x + element.offsetWidth) - this.xcomp) /
|
||||
element.offsetWidth;
|
||||
}
|
||||
},
|
||||
|
||||
/** @id MochiKit.Position.absolutize */
|
||||
absolutize: function (element) {
|
||||
element = MochiKit.DOM.getElement(element);
|
||||
if (element.style.position == 'absolute') {
|
||||
return;
|
||||
}
|
||||
MochiKit.Position.prepare();
|
||||
|
||||
var offsets = MochiKit.Position.positionedOffset(element);
|
||||
var width = element.clientWidth;
|
||||
var height = element.clientHeight;
|
||||
|
||||
var oldStyle = {
|
||||
'position': element.style.position,
|
||||
'left': offsets.x - parseFloat(element.style.left || 0),
|
||||
'top': offsets.y - parseFloat(element.style.top || 0),
|
||||
'width': element.style.width,
|
||||
'height': element.style.height
|
||||
};
|
||||
|
||||
element.style.position = 'absolute';
|
||||
element.style.top = offsets.y + 'px';
|
||||
element.style.left = offsets.x + 'px';
|
||||
element.style.width = width + 'px';
|
||||
element.style.height = height + 'px';
|
||||
|
||||
return oldStyle;
|
||||
},
|
||||
|
||||
/** @id MochiKit.Position.positionedOffset */
|
||||
positionedOffset: function (element) {
|
||||
var valueT = 0, valueL = 0;
|
||||
do {
|
||||
valueT += element.offsetTop || 0;
|
||||
valueL += element.offsetLeft || 0;
|
||||
element = element.offsetParent;
|
||||
if (element) {
|
||||
var p = MochiKit.Style.getStyle(element, 'position');
|
||||
if (p == 'relative' || p == 'absolute') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while (element);
|
||||
return new MochiKit.Style.Coordinates(valueL, valueT);
|
||||
},
|
||||
|
||||
/** @id MochiKit.Position.relativize */
|
||||
relativize: function (element, oldPos) {
|
||||
element = MochiKit.DOM.getElement(element);
|
||||
if (element.style.position == 'relative') {
|
||||
return;
|
||||
}
|
||||
MochiKit.Position.prepare();
|
||||
|
||||
var top = parseFloat(element.style.top || 0) -
|
||||
(oldPos['top'] || 0);
|
||||
var left = parseFloat(element.style.left || 0) -
|
||||
(oldPos['left'] || 0);
|
||||
|
||||
element.style.position = oldPos['position'];
|
||||
element.style.top = top + 'px';
|
||||
element.style.left = left + 'px';
|
||||
element.style.width = oldPos['width'];
|
||||
element.style.height = oldPos['height'];
|
||||
},
|
||||
|
||||
/** @id MochiKit.Position.clone */
|
||||
clone: function (source, target) {
|
||||
source = MochiKit.DOM.getElement(source);
|
||||
target = MochiKit.DOM.getElement(target);
|
||||
target.style.position = 'absolute';
|
||||
var offsets = this.cumulativeOffset(source);
|
||||
target.style.top = offsets.y + 'px';
|
||||
target.style.left = offsets.x + 'px';
|
||||
target.style.width = source.offsetWidth + 'px';
|
||||
target.style.height = source.offsetHeight + 'px';
|
||||
},
|
||||
|
||||
/** @id MochiKit.Position.page */
|
||||
page: function (forElement) {
|
||||
var valueT = 0;
|
||||
var valueL = 0;
|
||||
|
||||
var element = forElement;
|
||||
do {
|
||||
valueT += element.offsetTop || 0;
|
||||
valueL += element.offsetLeft || 0;
|
||||
|
||||
// Safari fix
|
||||
if (element.offsetParent == document.body && MochiKit.Style.getStyle(element, 'position') == 'absolute') {
|
||||
break;
|
||||
}
|
||||
} while (element = element.offsetParent);
|
||||
|
||||
element = forElement;
|
||||
do {
|
||||
valueT -= element.scrollTop || 0;
|
||||
valueL -= element.scrollLeft || 0;
|
||||
} while (element = element.parentNode);
|
||||
|
||||
return new MochiKit.Style.Coordinates(valueL, valueT);
|
||||
}
|
||||
});
|
||||
|
||||
MochiKit.Position.__new__ = function (win) {
|
||||
MochiKit.Base.nameFunctions(this);
|
||||
};
|
||||
|
||||
MochiKit.Position.__new__(this);
|
||||
|
||||
MochiKit.Base._exportSymbols(this, MochiKit.Position);
|
||||
416
frontend/delta/js/MochiKit/Selector.js
Normal file
416
frontend/delta/js/MochiKit/Selector.js
Normal file
@@ -0,0 +1,416 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
/***
|
||||
|
||||
MochiKit.Selector 1.5
|
||||
|
||||
See <http://mochikit.com/> for documentation, downloads, license, etc.
|
||||
|
||||
(c) 2005 Bob Ippolito and others. All rights Reserved.
|
||||
|
||||
***/
|
||||
|
||||
MochiKit.Base.module(MochiKit, 'Selector', '1.5', ['Base', 'DOM', 'Iter']);
|
||||
|
||||
MochiKit.Selector.Selector = function (expression) {
|
||||
this.params = {classNames: [], pseudoClassNames: []};
|
||||
this.expression = expression.toString().replace(/(^\s+|\s+$)/g, '');
|
||||
this.parseExpression();
|
||||
this.compileMatcher();
|
||||
};
|
||||
|
||||
MochiKit.Selector.Selector.prototype = {
|
||||
/***
|
||||
|
||||
Selector class: convenient object to make CSS selections.
|
||||
|
||||
***/
|
||||
__class__: MochiKit.Selector.Selector,
|
||||
|
||||
/** @id MochiKit.Selector.Selector.prototype.parseExpression */
|
||||
parseExpression: function () {
|
||||
function abort(message) {
|
||||
throw 'Parse error in selector: ' + message;
|
||||
}
|
||||
|
||||
if (this.expression == '') {
|
||||
abort('empty expression');
|
||||
}
|
||||
|
||||
var repr = MochiKit.Base.repr;
|
||||
var params = this.params;
|
||||
var expr = this.expression;
|
||||
var match, modifier, clause, rest;
|
||||
while (match = expr.match(/^(.*)\[([a-z0-9_:-]+?)(?:([~\|!^$*]?=)(?:"([^"]*)"|([^\]\s]*)))?\]$/i)) {
|
||||
params.attributes = params.attributes || [];
|
||||
params.attributes.push({name: match[2], operator: match[3], value: match[4] || match[5] || ''});
|
||||
expr = match[1];
|
||||
}
|
||||
|
||||
if (expr == '*') {
|
||||
return this.params.wildcard = true;
|
||||
}
|
||||
|
||||
while (match = expr.match(/^([^a-z0-9_-])?([a-z0-9_-]+(?:\([^)]*\))?)(.*)/i)) {
|
||||
modifier = match[1];
|
||||
clause = match[2];
|
||||
rest = match[3];
|
||||
switch (modifier) {
|
||||
case '#':
|
||||
params.id = clause;
|
||||
break;
|
||||
case '.':
|
||||
params.classNames.push(clause);
|
||||
break;
|
||||
case ':':
|
||||
params.pseudoClassNames.push(clause);
|
||||
break;
|
||||
case '':
|
||||
case undefined:
|
||||
params.tagName = clause.toUpperCase();
|
||||
break;
|
||||
default:
|
||||
abort(repr(expr));
|
||||
}
|
||||
expr = rest;
|
||||
}
|
||||
|
||||
if (expr.length > 0) {
|
||||
abort(repr(expr));
|
||||
}
|
||||
},
|
||||
|
||||
/** @id MochiKit.Selector.Selector.prototype.buildMatchExpression */
|
||||
buildMatchExpression: function () {
|
||||
var repr = MochiKit.Base.repr;
|
||||
var params = this.params;
|
||||
var conditions = [];
|
||||
var clause, i;
|
||||
|
||||
function childElements(element) {
|
||||
return "MochiKit.Base.filter(function (node) { return node.nodeType == 1; }, " + element + ".childNodes)";
|
||||
}
|
||||
|
||||
if (params.wildcard) {
|
||||
conditions.push('true');
|
||||
}
|
||||
if (clause = params.id) {
|
||||
conditions.push('element.id == ' + repr(clause));
|
||||
}
|
||||
if (clause = params.tagName) {
|
||||
conditions.push('element.tagName.toUpperCase() == ' + repr(clause));
|
||||
}
|
||||
if ((clause = params.classNames).length > 0) {
|
||||
for (i = 0; i < clause.length; i++) {
|
||||
conditions.push('MochiKit.DOM.hasElementClass(element, ' + repr(clause[i]) + ')');
|
||||
}
|
||||
}
|
||||
if ((clause = params.pseudoClassNames).length > 0) {
|
||||
for (i = 0; i < clause.length; i++) {
|
||||
var match = clause[i].match(/^([^(]+)(?:\((.*)\))?$/);
|
||||
var pseudoClass = match[1];
|
||||
var pseudoClassArgument = match[2];
|
||||
switch (pseudoClass) {
|
||||
case 'root':
|
||||
conditions.push('element.nodeType == 9 || element === element.ownerDocument.documentElement'); break;
|
||||
case 'nth-child':
|
||||
case 'nth-last-child':
|
||||
case 'nth-of-type':
|
||||
case 'nth-last-of-type':
|
||||
match = pseudoClassArgument.match(/^((?:(\d+)n\+)?(\d+)|odd|even)$/);
|
||||
if (!match) {
|
||||
throw "Invalid argument to pseudo element nth-child: " + pseudoClassArgument;
|
||||
}
|
||||
var a, b;
|
||||
if (match[0] == 'odd') {
|
||||
a = 2;
|
||||
b = 1;
|
||||
} else if (match[0] == 'even') {
|
||||
a = 2;
|
||||
b = 0;
|
||||
} else {
|
||||
a = match[2] && parseInt(match, 10) || null;
|
||||
b = parseInt(match[3], 10);
|
||||
}
|
||||
conditions.push('this.nthChild(element,' + a + ',' + b
|
||||
+ ',' + !!pseudoClass.match('^nth-last') // Reverse
|
||||
+ ',' + !!pseudoClass.match('of-type$') // Restrict to same tagName
|
||||
+ ')');
|
||||
break;
|
||||
case 'first-child':
|
||||
conditions.push('this.nthChild(element, null, 1)');
|
||||
break;
|
||||
case 'last-child':
|
||||
conditions.push('this.nthChild(element, null, 1, true)');
|
||||
break;
|
||||
case 'first-of-type':
|
||||
conditions.push('this.nthChild(element, null, 1, false, true)');
|
||||
break;
|
||||
case 'last-of-type':
|
||||
conditions.push('this.nthChild(element, null, 1, true, true)');
|
||||
break;
|
||||
case 'only-child':
|
||||
conditions.push(childElements('element.parentNode') + '.length == 1');
|
||||
break;
|
||||
case 'only-of-type':
|
||||
conditions.push('MochiKit.Base.filter(function (node) { return node.tagName == element.tagName; }, ' + childElements('element.parentNode') + ').length == 1');
|
||||
break;
|
||||
case 'empty':
|
||||
conditions.push('element.childNodes.length == 0');
|
||||
break;
|
||||
case 'enabled':
|
||||
conditions.push('(this.isUIElement(element) && element.disabled === false)');
|
||||
break;
|
||||
case 'disabled':
|
||||
conditions.push('(this.isUIElement(element) && element.disabled === true)');
|
||||
break;
|
||||
case 'checked':
|
||||
conditions.push('(this.isUIElement(element) && element.checked === true)');
|
||||
break;
|
||||
case 'not':
|
||||
var subselector = new MochiKit.Selector.Selector(pseudoClassArgument);
|
||||
conditions.push('!( ' + subselector.buildMatchExpression() + ')');
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (clause = params.attributes) {
|
||||
MochiKit.Base.map(function (attribute) {
|
||||
var value = 'MochiKit.DOM.getNodeAttribute(element, ' + repr(attribute.name) + ')';
|
||||
var splitValueBy = function (delimiter) {
|
||||
return value + '.split(' + repr(delimiter) + ')';
|
||||
};
|
||||
conditions.push(value + ' != null');
|
||||
switch (attribute.operator) {
|
||||
case '=':
|
||||
conditions.push(value + ' == ' + repr(attribute.value));
|
||||
break;
|
||||
case '~=':
|
||||
conditions.push('MochiKit.Base.findValue(' + splitValueBy(' ') + ', ' + repr(attribute.value) + ') > -1');
|
||||
break;
|
||||
case '^=':
|
||||
conditions.push(value + '.substring(0, ' + attribute.value.length + ') == ' + repr(attribute.value));
|
||||
break;
|
||||
case '$=':
|
||||
conditions.push(value + '.substring(' + value + '.length - ' + attribute.value.length + ') == ' + repr(attribute.value));
|
||||
break;
|
||||
case '*=':
|
||||
conditions.push(value + '.match(' + repr(attribute.value) + ')');
|
||||
break;
|
||||
case '|=':
|
||||
conditions.push(splitValueBy('-') + '[0].toUpperCase() == ' + repr(attribute.value.toUpperCase()));
|
||||
break;
|
||||
case '!=':
|
||||
conditions.push(value + ' != ' + repr(attribute.value));
|
||||
break;
|
||||
case '':
|
||||
case undefined:
|
||||
// Condition already added above
|
||||
break;
|
||||
default:
|
||||
throw 'Unknown operator ' + attribute.operator + ' in selector';
|
||||
}
|
||||
}, clause);
|
||||
}
|
||||
|
||||
return conditions.join(' && ');
|
||||
},
|
||||
|
||||
/** @id MochiKit.Selector.Selector.prototype.compileMatcher */
|
||||
compileMatcher: function () {
|
||||
var code = 'return (!element.tagName) ? false : ' +
|
||||
this.buildMatchExpression() + ';';
|
||||
this.match = new Function('element', code);
|
||||
},
|
||||
|
||||
/** @id MochiKit.Selector.Selector.prototype.nthChild */
|
||||
nthChild: function (element, a, b, reverse, sametag){
|
||||
var siblings = MochiKit.Base.filter(function (node) {
|
||||
return node.nodeType == 1;
|
||||
}, element.parentNode.childNodes);
|
||||
if (sametag) {
|
||||
siblings = MochiKit.Base.filter(function (node) {
|
||||
return node.tagName == element.tagName;
|
||||
}, siblings);
|
||||
}
|
||||
if (reverse) {
|
||||
siblings = MochiKit.Iter.reversed(siblings);
|
||||
}
|
||||
if (a) {
|
||||
var actualIndex = MochiKit.Base.findIdentical(siblings, element);
|
||||
return ((actualIndex + 1 - b) / a) % 1 == 0;
|
||||
} else {
|
||||
return b == MochiKit.Base.findIdentical(siblings, element) + 1;
|
||||
}
|
||||
},
|
||||
|
||||
/** @id MochiKit.Selector.Selector.prototype.isUIElement */
|
||||
isUIElement: function (element) {
|
||||
return MochiKit.Base.findValue(['input', 'button', 'select', 'option', 'textarea', 'object'],
|
||||
element.tagName.toLowerCase()) > -1;
|
||||
},
|
||||
|
||||
/** @id MochiKit.Selector.Selector.prototype.findElements */
|
||||
findElements: function (scope, axis) {
|
||||
var element;
|
||||
|
||||
if (axis == undefined) {
|
||||
axis = "";
|
||||
}
|
||||
|
||||
function inScope(element, scope) {
|
||||
if (axis == "") {
|
||||
return MochiKit.DOM.isChildNode(element, scope);
|
||||
} else if (axis == ">") {
|
||||
return element.parentNode === scope;
|
||||
} else if (axis == "+") {
|
||||
return element === nextSiblingElement(scope);
|
||||
} else if (axis == "~") {
|
||||
var sibling = scope;
|
||||
while (sibling = nextSiblingElement(sibling)) {
|
||||
if (element === sibling) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
throw "Invalid axis: " + axis;
|
||||
}
|
||||
}
|
||||
|
||||
if (element = MochiKit.DOM.getElement(this.params.id)) {
|
||||
if (this.match(element)) {
|
||||
if (!scope || inScope(element, scope)) {
|
||||
return [element];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function nextSiblingElement(node) {
|
||||
node = node.nextSibling;
|
||||
while (node && node.nodeType != 1) {
|
||||
node = node.nextSibling;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
if (axis == "") {
|
||||
scope = (scope || MochiKit.DOM.currentDocument()).getElementsByTagName(this.params.tagName || '*');
|
||||
} else if (axis == ">") {
|
||||
if (!scope) {
|
||||
throw "> combinator not allowed without preceeding expression";
|
||||
}
|
||||
scope = MochiKit.Base.filter(function (node) {
|
||||
return node.nodeType == 1;
|
||||
}, scope.childNodes);
|
||||
} else if (axis == "+") {
|
||||
if (!scope) {
|
||||
throw "+ combinator not allowed without preceeding expression";
|
||||
}
|
||||
scope = nextSiblingElement(scope) && [nextSiblingElement(scope)];
|
||||
} else if (axis == "~") {
|
||||
if (!scope) {
|
||||
throw "~ combinator not allowed without preceeding expression";
|
||||
}
|
||||
var newscope = [];
|
||||
while (nextSiblingElement(scope)) {
|
||||
scope = nextSiblingElement(scope);
|
||||
newscope.push(scope);
|
||||
}
|
||||
scope = newscope;
|
||||
}
|
||||
|
||||
if (!scope) {
|
||||
return [];
|
||||
}
|
||||
|
||||
var results = MochiKit.Base.filter(MochiKit.Base.bind(function (scopeElt) {
|
||||
return this.match(scopeElt);
|
||||
}, this), scope);
|
||||
|
||||
return results;
|
||||
},
|
||||
|
||||
/** @id MochiKit.Selector.Selector.prototype.repr */
|
||||
repr: function () {
|
||||
return 'Selector(' + this.expression + ')';
|
||||
},
|
||||
|
||||
toString: MochiKit.Base.forwardCall("repr")
|
||||
};
|
||||
|
||||
MochiKit.Base.update(MochiKit.Selector, {
|
||||
|
||||
/** @id MochiKit.Selector.findChildElements */
|
||||
findChildElements: function (element, expressions) {
|
||||
element = MochiKit.DOM.getElement(element);
|
||||
var uniq = function(arr) {
|
||||
var res = [];
|
||||
for (var i = 0; i < arr.length; i++) {
|
||||
if (MochiKit.Base.findIdentical(res, arr[i]) < 0) {
|
||||
res.push(arr[i]);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
};
|
||||
return MochiKit.Base.flattenArray(MochiKit.Base.map(function (expression) {
|
||||
try {
|
||||
var res = element.querySelectorAll(expression);
|
||||
return Array.prototype.slice.call(res, 0);
|
||||
} catch (ignore) {
|
||||
// No querySelectorAll or extended expression syntax used
|
||||
}
|
||||
var nextScope = "";
|
||||
var reducer = function (results, expr) {
|
||||
var match = expr.match(/^[>+~]$/);
|
||||
if (match) {
|
||||
nextScope = match[0];
|
||||
return results;
|
||||
} else {
|
||||
var selector = new MochiKit.Selector.Selector(expr);
|
||||
var elements = MochiKit.Iter.reduce(function (elements, result) {
|
||||
return MochiKit.Base.extend(elements, selector.findElements(result || element, nextScope));
|
||||
}, results, []);
|
||||
nextScope = "";
|
||||
return elements;
|
||||
}
|
||||
};
|
||||
var exprs = expression.replace(/(^\s+|\s+$)/g, '').split(/\s+/);
|
||||
return uniq(MochiKit.Iter.reduce(reducer, exprs, [null]));
|
||||
}, expressions));
|
||||
},
|
||||
|
||||
findDocElements: function () {
|
||||
return MochiKit.Selector.findChildElements(MochiKit.DOM.currentDocument(), arguments);
|
||||
},
|
||||
|
||||
__new__: function () {
|
||||
this.$$ = this.findDocElements;
|
||||
MochiKit.Base.nameFunctions(this);
|
||||
}
|
||||
});
|
||||
|
||||
MochiKit.Selector.__new__();
|
||||
|
||||
MochiKit.Base._exportSymbols(this, MochiKit.Selector);
|
||||
924
frontend/delta/js/MochiKit/Signal.js
Normal file
924
frontend/delta/js/MochiKit/Signal.js
Normal file
@@ -0,0 +1,924 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
/***
|
||||
|
||||
MochiKit.Signal 1.5
|
||||
|
||||
See <http://mochikit.com/> for documentation, downloads, license, etc.
|
||||
|
||||
(c) 2006 Jonathan Gardner, Beau Hartshorne, Bob Ippolito. All rights Reserved.
|
||||
|
||||
***/
|
||||
|
||||
MochiKit.Base.module(MochiKit, 'Signal', '1.5', ['Base', 'DOM']);
|
||||
|
||||
MochiKit.Signal._observers = [];
|
||||
|
||||
/** @id MochiKit.Signal.Event */
|
||||
MochiKit.Signal.Event = function (src, e) {
|
||||
this._event = e || window.event;
|
||||
this._src = src;
|
||||
};
|
||||
MochiKit.Signal.Event.__export__ = false;
|
||||
|
||||
MochiKit.Base.update(MochiKit.Signal.Event.prototype, {
|
||||
|
||||
__repr__: function () {
|
||||
var repr = MochiKit.Base.repr;
|
||||
var str = '{event(): ' + repr(this.event()) +
|
||||
', src(): ' + repr(this.src()) +
|
||||
', type(): ' + repr(this.type()) +
|
||||
', target(): ' + repr(this.target());
|
||||
|
||||
if (this.type() &&
|
||||
this.type().indexOf('key') === 0 ||
|
||||
this.type().indexOf('mouse') === 0 ||
|
||||
this.type().indexOf('click') != -1 ||
|
||||
this.type() == 'contextmenu') {
|
||||
str += ', modifier(): ' + '{alt: ' + repr(this.modifier().alt) +
|
||||
', ctrl: ' + repr(this.modifier().ctrl) +
|
||||
', meta: ' + repr(this.modifier().meta) +
|
||||
', shift: ' + repr(this.modifier().shift) +
|
||||
', any: ' + repr(this.modifier().any) + '}';
|
||||
}
|
||||
|
||||
if (this.type() && this.type().indexOf('key') === 0) {
|
||||
str += ', key(): {code: ' + repr(this.key().code) +
|
||||
', string: ' + repr(this.key().string) + '}';
|
||||
}
|
||||
|
||||
if (this.type() && (
|
||||
this.type().indexOf('mouse') === 0 ||
|
||||
this.type().indexOf('click') != -1 ||
|
||||
this.type() == 'contextmenu')) {
|
||||
|
||||
str += ', mouse(): {page: ' + repr(this.mouse().page) +
|
||||
', client: ' + repr(this.mouse().client);
|
||||
|
||||
if (this.type() != 'mousemove' && this.type() != 'mousewheel') {
|
||||
str += ', button: {left: ' + repr(this.mouse().button.left) +
|
||||
', middle: ' + repr(this.mouse().button.middle) +
|
||||
', right: ' + repr(this.mouse().button.right) + '}';
|
||||
}
|
||||
if (this.type() == 'mousewheel') {
|
||||
str += ', wheel: ' + repr(this.mouse().wheel);
|
||||
}
|
||||
str += '}';
|
||||
}
|
||||
if (this.type() == 'mouseover' || this.type() == 'mouseout' ||
|
||||
this.type() == 'mouseenter' || this.type() == 'mouseleave') {
|
||||
str += ', relatedTarget(): ' + repr(this.relatedTarget());
|
||||
}
|
||||
str += '}';
|
||||
return str;
|
||||
},
|
||||
|
||||
/** @id MochiKit.Signal.Event.prototype.toString */
|
||||
toString: function () {
|
||||
return this.__repr__();
|
||||
},
|
||||
|
||||
/** @id MochiKit.Signal.Event.prototype.src */
|
||||
src: function () {
|
||||
return this._src;
|
||||
},
|
||||
|
||||
/** @id MochiKit.Signal.Event.prototype.event */
|
||||
event: function () {
|
||||
return this._event;
|
||||
},
|
||||
|
||||
/** @id MochiKit.Signal.Event.prototype.type */
|
||||
type: function () {
|
||||
if (this._event.type === "DOMMouseScroll") {
|
||||
return "mousewheel";
|
||||
} else {
|
||||
return this._event.type || undefined;
|
||||
}
|
||||
},
|
||||
|
||||
/** @id MochiKit.Signal.Event.prototype.target */
|
||||
target: function () {
|
||||
return this._event.target || this._event.srcElement;
|
||||
},
|
||||
|
||||
_relatedTarget: null,
|
||||
/** @id MochiKit.Signal.Event.prototype.relatedTarget */
|
||||
relatedTarget: function () {
|
||||
if (this._relatedTarget !== null) {
|
||||
return this._relatedTarget;
|
||||
}
|
||||
|
||||
var elem = null;
|
||||
if (this.type() == 'mouseover' || this.type() == 'mouseenter') {
|
||||
elem = (this._event.relatedTarget ||
|
||||
this._event.fromElement);
|
||||
} else if (this.type() == 'mouseout' || this.type() == 'mouseleave') {
|
||||
elem = (this._event.relatedTarget ||
|
||||
this._event.toElement);
|
||||
}
|
||||
try {
|
||||
if (elem !== null && elem.nodeType !== null) {
|
||||
this._relatedTarget = elem;
|
||||
return elem;
|
||||
}
|
||||
} catch (ignore) {
|
||||
// Firefox 3 throws a permission denied error when accessing
|
||||
// any property on XUL elements (e.g. scrollbars)...
|
||||
}
|
||||
|
||||
return undefined;
|
||||
},
|
||||
|
||||
_modifier: null,
|
||||
/** @id MochiKit.Signal.Event.prototype.modifier */
|
||||
modifier: function () {
|
||||
if (this._modifier !== null) {
|
||||
return this._modifier;
|
||||
}
|
||||
var m = {};
|
||||
m.alt = this._event.altKey;
|
||||
m.ctrl = this._event.ctrlKey;
|
||||
m.meta = this._event.metaKey || false; // IE and Opera punt here
|
||||
m.shift = this._event.shiftKey;
|
||||
m.any = m.alt || m.ctrl || m.shift || m.meta;
|
||||
this._modifier = m;
|
||||
return m;
|
||||
},
|
||||
|
||||
_key: null,
|
||||
/** @id MochiKit.Signal.Event.prototype.key */
|
||||
key: function () {
|
||||
if (this._key !== null) {
|
||||
return this._key;
|
||||
}
|
||||
var k = {};
|
||||
if (this.type() && this.type().indexOf('key') === 0) {
|
||||
|
||||
/*
|
||||
|
||||
If you're looking for a special key, look for it in keydown or
|
||||
keyup, but never keypress. If you're looking for a Unicode
|
||||
chracter, look for it with keypress, but never keyup or
|
||||
keydown.
|
||||
|
||||
Notes:
|
||||
|
||||
FF key event behavior:
|
||||
key event charCode keyCode
|
||||
DOWN ku,kd 0 40
|
||||
DOWN kp 0 40
|
||||
ESC ku,kd 0 27
|
||||
ESC kp 0 27
|
||||
a ku,kd 0 65
|
||||
a kp 97 0
|
||||
shift+a ku,kd 0 65
|
||||
shift+a kp 65 0
|
||||
1 ku,kd 0 49
|
||||
1 kp 49 0
|
||||
shift+1 ku,kd 0 0
|
||||
shift+1 kp 33 0
|
||||
|
||||
IE key event behavior:
|
||||
(IE doesn't fire keypress events for special keys.)
|
||||
key event keyCode
|
||||
DOWN ku,kd 40
|
||||
DOWN kp undefined
|
||||
ESC ku,kd 27
|
||||
ESC kp 27
|
||||
a ku,kd 65
|
||||
a kp 97
|
||||
shift+a ku,kd 65
|
||||
shift+a kp 65
|
||||
1 ku,kd 49
|
||||
1 kp 49
|
||||
shift+1 ku,kd 49
|
||||
shift+1 kp 33
|
||||
|
||||
Safari key event behavior:
|
||||
(Safari sets charCode and keyCode to something crazy for
|
||||
special keys.)
|
||||
key event charCode keyCode
|
||||
DOWN ku,kd 63233 40
|
||||
DOWN kp 63233 63233
|
||||
ESC ku,kd 27 27
|
||||
ESC kp 27 27
|
||||
a ku,kd 97 65
|
||||
a kp 97 97
|
||||
shift+a ku,kd 65 65
|
||||
shift+a kp 65 65
|
||||
1 ku,kd 49 49
|
||||
1 kp 49 49
|
||||
shift+1 ku,kd 33 49
|
||||
shift+1 kp 33 33
|
||||
|
||||
*/
|
||||
|
||||
/* look for special keys here */
|
||||
if (this.type() == 'keydown' || this.type() == 'keyup') {
|
||||
k.code = this._event.keyCode;
|
||||
k.string = (MochiKit.Signal._specialKeys[k.code] ||
|
||||
'KEY_UNKNOWN');
|
||||
this._key = k;
|
||||
return k;
|
||||
|
||||
/* look for characters here */
|
||||
} else if (this.type() == 'keypress') {
|
||||
|
||||
/*
|
||||
|
||||
Special key behavior:
|
||||
|
||||
IE: does not fire keypress events for special keys
|
||||
FF: sets charCode to 0, and sets the correct keyCode
|
||||
Safari: sets keyCode and charCode to something stupid
|
||||
|
||||
*/
|
||||
|
||||
k.code = 0;
|
||||
k.string = '';
|
||||
|
||||
if (typeof(this._event.charCode) != 'undefined' &&
|
||||
this._event.charCode !== 0 &&
|
||||
!MochiKit.Signal._specialMacKeys[this._event.charCode]) {
|
||||
k.code = this._event.charCode;
|
||||
k.string = String.fromCharCode(k.code);
|
||||
} else if (this._event.keyCode &&
|
||||
typeof(this._event.charCode) == 'undefined') { // IE
|
||||
k.code = this._event.keyCode;
|
||||
k.string = String.fromCharCode(k.code);
|
||||
}
|
||||
|
||||
this._key = k;
|
||||
return k;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
|
||||
_mouse: null,
|
||||
/** @id MochiKit.Signal.Event.prototype.mouse */
|
||||
mouse: function () {
|
||||
if (this._mouse !== null) {
|
||||
return this._mouse;
|
||||
}
|
||||
|
||||
var m = {};
|
||||
var e = this._event;
|
||||
|
||||
if (this.type() && (
|
||||
this.type().indexOf('mouse') === 0 ||
|
||||
this.type().indexOf('drag') === 0 ||
|
||||
this.type().indexOf('click') != -1 ||
|
||||
this.type() == 'contextmenu')) {
|
||||
|
||||
m.client = { x: 0, y: 0 };
|
||||
if (e.clientX || e.clientY) {
|
||||
m.client.x = (!e.clientX || e.clientX < 0) ? 0 : e.clientX;
|
||||
m.client.y = (!e.clientY || e.clientY < 0) ? 0 : e.clientY;
|
||||
}
|
||||
|
||||
m.page = { x: 0, y: 0 };
|
||||
if (e.pageX || e.pageY) {
|
||||
m.page.x = (!e.pageX || e.pageX < 0) ? 0 : e.pageX;
|
||||
m.page.y = (!e.pageY || e.pageY < 0) ? 0 : e.pageY;
|
||||
} else {
|
||||
/*
|
||||
|
||||
The IE shortcut can be off by two. We fix it. See:
|
||||
http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/getboundingclientrect.asp
|
||||
|
||||
This is similar to the method used in
|
||||
MochiKit.Style.getElementPosition().
|
||||
|
||||
*/
|
||||
var de = MochiKit.DOM._document.documentElement;
|
||||
var b = MochiKit.DOM._document.body;
|
||||
|
||||
m.page.x = e.clientX +
|
||||
(de.scrollLeft || b.scrollLeft) -
|
||||
(de.clientLeft || 0);
|
||||
|
||||
m.page.y = e.clientY +
|
||||
(de.scrollTop || b.scrollTop) -
|
||||
(de.clientTop || 0);
|
||||
|
||||
}
|
||||
if (this.type() != 'mousemove' && this.type() != 'mousewheel') {
|
||||
m.button = {};
|
||||
m.button.left = false;
|
||||
m.button.right = false;
|
||||
m.button.middle = false;
|
||||
|
||||
/* we could check e.button, but which is more consistent */
|
||||
if (e.which) {
|
||||
m.button.left = (e.which == 1);
|
||||
m.button.middle = (e.which == 2);
|
||||
m.button.right = (e.which == 3);
|
||||
|
||||
/*
|
||||
|
||||
Mac browsers and right click:
|
||||
|
||||
- Safari doesn't fire any click events on a right
|
||||
click:
|
||||
http://bugs.webkit.org/show_bug.cgi?id=6595
|
||||
|
||||
- Firefox fires the event, and sets ctrlKey = true
|
||||
|
||||
- Opera fires the event, and sets metaKey = true
|
||||
|
||||
oncontextmenu is fired on right clicks between
|
||||
browsers and across platforms.
|
||||
|
||||
*/
|
||||
|
||||
} else {
|
||||
m.button.left = !!(e.button & 1);
|
||||
m.button.right = !!(e.button & 2);
|
||||
m.button.middle = !!(e.button & 4);
|
||||
}
|
||||
}
|
||||
if (this.type() == 'mousewheel') {
|
||||
m.wheel = { x: 0, y: 0 };
|
||||
if (e.wheelDeltaX || e.wheelDeltaY) {
|
||||
m.wheel.x = e.wheelDeltaX / -40 || 0;
|
||||
m.wheel.y = e.wheelDeltaY / -40 || 0;
|
||||
} else if (e.wheelDelta) {
|
||||
m.wheel.y = e.wheelDelta / -40;
|
||||
} else {
|
||||
m.wheel.y = e.detail || 0;
|
||||
}
|
||||
}
|
||||
this._mouse = m;
|
||||
return m;
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
|
||||
/** @id MochiKit.Signal.Event.prototype.stop */
|
||||
stop: function () {
|
||||
this.stopPropagation();
|
||||
this.preventDefault();
|
||||
},
|
||||
|
||||
/** @id MochiKit.Signal.Event.prototype.stopPropagation */
|
||||
stopPropagation: function () {
|
||||
if (this._event.stopPropagation) {
|
||||
this._event.stopPropagation();
|
||||
} else {
|
||||
this._event.cancelBubble = true;
|
||||
}
|
||||
},
|
||||
|
||||
/** @id MochiKit.Signal.Event.prototype.preventDefault */
|
||||
preventDefault: function () {
|
||||
if (this._event.preventDefault) {
|
||||
this._event.preventDefault();
|
||||
} else if (this._confirmUnload === null) {
|
||||
this._event.returnValue = false;
|
||||
}
|
||||
},
|
||||
|
||||
_confirmUnload: null,
|
||||
|
||||
/** @id MochiKit.Signal.Event.prototype.confirmUnload */
|
||||
confirmUnload: function (msg) {
|
||||
if (this.type() == 'beforeunload') {
|
||||
this._confirmUnload = msg;
|
||||
this._event.returnValue = msg;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/* Safari sets keyCode to these special values onkeypress. */
|
||||
MochiKit.Signal._specialMacKeys = {
|
||||
3: 'KEY_ENTER',
|
||||
63289: 'KEY_NUM_PAD_CLEAR',
|
||||
63276: 'KEY_PAGE_UP',
|
||||
63277: 'KEY_PAGE_DOWN',
|
||||
63275: 'KEY_END',
|
||||
63273: 'KEY_HOME',
|
||||
63234: 'KEY_ARROW_LEFT',
|
||||
63232: 'KEY_ARROW_UP',
|
||||
63235: 'KEY_ARROW_RIGHT',
|
||||
63233: 'KEY_ARROW_DOWN',
|
||||
63302: 'KEY_INSERT',
|
||||
63272: 'KEY_DELETE'
|
||||
};
|
||||
|
||||
/* for KEY_F1 - KEY_F12 */
|
||||
(function () {
|
||||
var _specialMacKeys = MochiKit.Signal._specialMacKeys;
|
||||
for (var i = 63236; i <= 63242; i++) {
|
||||
// no F0
|
||||
_specialMacKeys[i] = 'KEY_F' + (i - 63236 + 1);
|
||||
}
|
||||
})();
|
||||
|
||||
/* Standard keyboard key codes. */
|
||||
MochiKit.Signal._specialKeys = {
|
||||
8: 'KEY_BACKSPACE',
|
||||
9: 'KEY_TAB',
|
||||
12: 'KEY_NUM_PAD_CLEAR', // weird, for Safari and Mac FF only
|
||||
13: 'KEY_ENTER',
|
||||
16: 'KEY_SHIFT',
|
||||
17: 'KEY_CTRL',
|
||||
18: 'KEY_ALT',
|
||||
19: 'KEY_PAUSE',
|
||||
20: 'KEY_CAPS_LOCK',
|
||||
27: 'KEY_ESCAPE',
|
||||
32: 'KEY_SPACEBAR',
|
||||
33: 'KEY_PAGE_UP',
|
||||
34: 'KEY_PAGE_DOWN',
|
||||
35: 'KEY_END',
|
||||
36: 'KEY_HOME',
|
||||
37: 'KEY_ARROW_LEFT',
|
||||
38: 'KEY_ARROW_UP',
|
||||
39: 'KEY_ARROW_RIGHT',
|
||||
40: 'KEY_ARROW_DOWN',
|
||||
44: 'KEY_PRINT_SCREEN',
|
||||
45: 'KEY_INSERT',
|
||||
46: 'KEY_DELETE',
|
||||
59: 'KEY_SEMICOLON', // weird, for Safari and IE only
|
||||
91: 'KEY_WINDOWS_LEFT',
|
||||
92: 'KEY_WINDOWS_RIGHT',
|
||||
93: 'KEY_SELECT',
|
||||
106: 'KEY_NUM_PAD_ASTERISK',
|
||||
107: 'KEY_NUM_PAD_PLUS_SIGN',
|
||||
109: 'KEY_NUM_PAD_HYPHEN-MINUS',
|
||||
110: 'KEY_NUM_PAD_FULL_STOP',
|
||||
111: 'KEY_NUM_PAD_SOLIDUS',
|
||||
144: 'KEY_NUM_LOCK',
|
||||
145: 'KEY_SCROLL_LOCK',
|
||||
186: 'KEY_SEMICOLON',
|
||||
187: 'KEY_EQUALS_SIGN',
|
||||
188: 'KEY_COMMA',
|
||||
189: 'KEY_HYPHEN-MINUS',
|
||||
190: 'KEY_FULL_STOP',
|
||||
191: 'KEY_SOLIDUS',
|
||||
192: 'KEY_GRAVE_ACCENT',
|
||||
219: 'KEY_LEFT_SQUARE_BRACKET',
|
||||
220: 'KEY_REVERSE_SOLIDUS',
|
||||
221: 'KEY_RIGHT_SQUARE_BRACKET',
|
||||
222: 'KEY_APOSTROPHE'
|
||||
// undefined: 'KEY_UNKNOWN'
|
||||
};
|
||||
|
||||
(function () {
|
||||
/* for KEY_0 - KEY_9 */
|
||||
var _specialKeys = MochiKit.Signal._specialKeys;
|
||||
for (var i = 48; i <= 57; i++) {
|
||||
_specialKeys[i] = 'KEY_' + (i - 48);
|
||||
}
|
||||
|
||||
/* for KEY_A - KEY_Z */
|
||||
for (i = 65; i <= 90; i++) {
|
||||
_specialKeys[i] = 'KEY_' + String.fromCharCode(i);
|
||||
}
|
||||
|
||||
/* for KEY_NUM_PAD_0 - KEY_NUM_PAD_9 */
|
||||
for (i = 96; i <= 105; i++) {
|
||||
_specialKeys[i] = 'KEY_NUM_PAD_' + (i - 96);
|
||||
}
|
||||
|
||||
/* for KEY_F1 - KEY_F12 */
|
||||
for (i = 112; i <= 123; i++) {
|
||||
// no F0
|
||||
_specialKeys[i] = 'KEY_F' + (i - 112 + 1);
|
||||
}
|
||||
})();
|
||||
|
||||
/* Internal object to keep track of created signals. */
|
||||
MochiKit.Signal.Ident = function (ident) {
|
||||
this.source = ident.source;
|
||||
this.signal = ident.signal;
|
||||
this.listener = ident.listener;
|
||||
this.isDOM = ident.isDOM;
|
||||
this.objOrFunc = ident.objOrFunc;
|
||||
this.funcOrStr = ident.funcOrStr;
|
||||
this.connected = ident.connected;
|
||||
};
|
||||
MochiKit.Signal.Ident.__export__ = false;
|
||||
MochiKit.Signal.Ident.prototype = {};
|
||||
|
||||
MochiKit.Base.update(MochiKit.Signal, {
|
||||
|
||||
_unloadCache: function () {
|
||||
var self = MochiKit.Signal;
|
||||
var observers = self._observers;
|
||||
|
||||
for (var i = 0; i < observers.length; i++) {
|
||||
if (observers[i].signal !== 'onload' && observers[i].signal !== 'onunload') {
|
||||
self._disconnect(observers[i]);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_listener: function (src, sig, func, obj, isDOM) {
|
||||
var self = MochiKit.Signal;
|
||||
var E = self.Event;
|
||||
if (!isDOM) {
|
||||
/* We don't want to re-bind already bound methods */
|
||||
if (typeof(func.im_self) == 'undefined') {
|
||||
return MochiKit.Base.bindLate(func, obj);
|
||||
} else {
|
||||
return func;
|
||||
}
|
||||
}
|
||||
obj = obj || src;
|
||||
if (typeof(func) == "string") {
|
||||
if (sig === 'onload' || sig === 'onunload') {
|
||||
return function (nativeEvent) {
|
||||
obj[func].apply(obj, [new E(src, nativeEvent)]);
|
||||
|
||||
var ident = new MochiKit.Signal.Ident({
|
||||
source: src, signal: sig, objOrFunc: obj, funcOrStr: func});
|
||||
|
||||
MochiKit.Signal._disconnect(ident);
|
||||
};
|
||||
} else {
|
||||
return function (nativeEvent) {
|
||||
obj[func].apply(obj, [new E(src, nativeEvent)]);
|
||||
};
|
||||
}
|
||||
} else {
|
||||
if (sig === 'onload' || sig === 'onunload') {
|
||||
return function (nativeEvent) {
|
||||
func.apply(obj, [new E(src, nativeEvent)]);
|
||||
|
||||
var ident = new MochiKit.Signal.Ident({
|
||||
source: src, signal: sig, objOrFunc: func});
|
||||
|
||||
MochiKit.Signal._disconnect(ident);
|
||||
};
|
||||
} else {
|
||||
return function (nativeEvent) {
|
||||
func.apply(obj, [new E(src, nativeEvent)]);
|
||||
};
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_browserAlreadyHasMouseEnterAndLeave: function () {
|
||||
return /MSIE/.test(navigator.userAgent);
|
||||
},
|
||||
|
||||
_browserLacksMouseWheelEvent: function () {
|
||||
return /Gecko\//.test(navigator.userAgent);
|
||||
},
|
||||
|
||||
_mouseEnterListener: function (src, sig, func, obj) {
|
||||
var E = MochiKit.Signal.Event;
|
||||
return function (nativeEvent) {
|
||||
var e = new E(src, nativeEvent);
|
||||
try {
|
||||
e.relatedTarget().nodeName;
|
||||
} catch (err) {
|
||||
/* probably hit a permission denied error; possibly one of
|
||||
* firefox's screwy anonymous DIVs inside an input element.
|
||||
* Allow this event to propogate up.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
e.stop();
|
||||
if (MochiKit.DOM.isChildNode(e.relatedTarget(), src)) {
|
||||
/* We've moved between our node and a child. Ignore. */
|
||||
return;
|
||||
}
|
||||
e.type = function () { return sig; };
|
||||
if (typeof(func) == "string") {
|
||||
return obj[func].apply(obj, [e]);
|
||||
} else {
|
||||
return func.apply(obj, [e]);
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
_getDestPair: function (objOrFunc, funcOrStr) {
|
||||
var obj = null;
|
||||
var func = null;
|
||||
if (typeof(funcOrStr) != 'undefined') {
|
||||
obj = objOrFunc;
|
||||
func = funcOrStr;
|
||||
if (typeof(funcOrStr) == 'string') {
|
||||
if (typeof(objOrFunc[funcOrStr]) != "function") {
|
||||
throw new Error("'funcOrStr' must be a function on 'objOrFunc'");
|
||||
}
|
||||
} else if (typeof(funcOrStr) != 'function') {
|
||||
throw new Error("'funcOrStr' must be a function or string");
|
||||
}
|
||||
} else if (typeof(objOrFunc) != "function") {
|
||||
throw new Error("'objOrFunc' must be a function if 'funcOrStr' is not given");
|
||||
} else {
|
||||
func = objOrFunc;
|
||||
}
|
||||
return [obj, func];
|
||||
},
|
||||
|
||||
/** @id MochiKit.Signal.connect */
|
||||
connect: function (src, sig, objOrFunc/* optional */, funcOrStr) {
|
||||
if (typeof(src) == "string") {
|
||||
src = MochiKit.DOM.getElement(src);
|
||||
}
|
||||
var self = MochiKit.Signal;
|
||||
|
||||
if (typeof(sig) != 'string') {
|
||||
throw new Error("'sig' must be a string");
|
||||
}
|
||||
|
||||
var destPair = self._getDestPair(objOrFunc, funcOrStr);
|
||||
var obj = destPair[0];
|
||||
var func = destPair[1];
|
||||
if (typeof(obj) == 'undefined' || obj === null) {
|
||||
obj = src;
|
||||
}
|
||||
|
||||
var isDOM = !!(src.addEventListener || src.attachEvent);
|
||||
if (isDOM && (sig === "onmouseenter" || sig === "onmouseleave")
|
||||
&& !self._browserAlreadyHasMouseEnterAndLeave()) {
|
||||
var listener = self._mouseEnterListener(src, sig.substr(2), func, obj);
|
||||
if (sig === "onmouseenter") {
|
||||
sig = "onmouseover";
|
||||
} else {
|
||||
sig = "onmouseout";
|
||||
}
|
||||
} else if (isDOM && sig == "onmousewheel" && self._browserLacksMouseWheelEvent()) {
|
||||
var listener = self._listener(src, sig, func, obj, isDOM);
|
||||
sig = "onDOMMouseScroll";
|
||||
} else {
|
||||
var listener = self._listener(src, sig, func, obj, isDOM);
|
||||
}
|
||||
|
||||
if (src.addEventListener) {
|
||||
src.addEventListener(sig.substr(2), listener, false);
|
||||
} else if (src.attachEvent) {
|
||||
src.attachEvent(sig, listener); // useCapture unsupported
|
||||
}
|
||||
|
||||
var ident = new MochiKit.Signal.Ident({
|
||||
source: src,
|
||||
signal: sig,
|
||||
listener: listener,
|
||||
isDOM: isDOM,
|
||||
objOrFunc: objOrFunc,
|
||||
funcOrStr: funcOrStr,
|
||||
connected: true
|
||||
});
|
||||
self._observers.push(ident);
|
||||
|
||||
if (!isDOM && typeof(src.__connect__) == 'function') {
|
||||
var args = MochiKit.Base.extend([ident], arguments, 1);
|
||||
src.__connect__.apply(src, args);
|
||||
}
|
||||
|
||||
return ident;
|
||||
},
|
||||
|
||||
/** @id MochiKit.Signal.connectOnce */
|
||||
connectOnce: function (src, sig, objOrFunc/* optional */, funcOrStr) {
|
||||
var self = MochiKit.Signal;
|
||||
var ident1 = self.connect(src, sig, objOrFunc, funcOrStr);
|
||||
var ident2;
|
||||
ident2 = self.connect(src, sig, function() {
|
||||
self.disconnect(ident1);
|
||||
self.disconnect(ident2);
|
||||
});
|
||||
return ident1;
|
||||
},
|
||||
|
||||
_disconnect: function (ident) {
|
||||
// already disconnected
|
||||
if (!ident.connected) {
|
||||
return;
|
||||
}
|
||||
ident.connected = false;
|
||||
var src = ident.source;
|
||||
var sig = ident.signal;
|
||||
var listener = ident.listener;
|
||||
// check isDOM
|
||||
if (!ident.isDOM) {
|
||||
if (typeof(src.__disconnect__) == 'function') {
|
||||
src.__disconnect__(ident, sig, ident.objOrFunc, ident.funcOrStr);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (src.removeEventListener) {
|
||||
src.removeEventListener(sig.substr(2), listener, false);
|
||||
} else if (src.detachEvent) {
|
||||
src.detachEvent(sig, listener); // useCapture unsupported
|
||||
} else {
|
||||
throw new Error("'src' must be a DOM element");
|
||||
}
|
||||
},
|
||||
|
||||
/** @id MochiKit.Signal.disconnect */
|
||||
disconnect: function (ident) {
|
||||
var self = MochiKit.Signal;
|
||||
var observers = self._observers;
|
||||
var m = MochiKit.Base;
|
||||
if (arguments.length > 1) {
|
||||
// compatibility API
|
||||
var src = arguments[0];
|
||||
if (typeof(src) == "string") {
|
||||
src = MochiKit.DOM.getElement(src);
|
||||
}
|
||||
var sig = arguments[1];
|
||||
var obj = arguments[2];
|
||||
var func = arguments[3];
|
||||
for (var i = observers.length - 1; i >= 0; i--) {
|
||||
var o = observers[i];
|
||||
if (o.source === src && o.signal === sig && o.objOrFunc === obj && o.funcOrStr === func) {
|
||||
self._disconnect(o);
|
||||
if (self._lock === 0) {
|
||||
observers.splice(i, 1);
|
||||
} else {
|
||||
self._dirty = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var idx = m.findIdentical(observers, ident);
|
||||
if (idx >= 0) {
|
||||
self._disconnect(ident);
|
||||
if (self._lock === 0) {
|
||||
observers.splice(idx, 1);
|
||||
} else {
|
||||
self._dirty = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
/** @id MochiKit.Signal.disconnectAllTo */
|
||||
disconnectAllTo: function (objOrFunc, /* optional */funcOrStr) {
|
||||
var self = MochiKit.Signal;
|
||||
var observers = self._observers;
|
||||
var disconnect = self._disconnect;
|
||||
var lock = self._lock;
|
||||
var dirty = self._dirty;
|
||||
if (typeof(funcOrStr) === 'undefined') {
|
||||
funcOrStr = null;
|
||||
}
|
||||
for (var i = observers.length - 1; i >= 0; i--) {
|
||||
var ident = observers[i];
|
||||
if (ident.objOrFunc === objOrFunc &&
|
||||
(funcOrStr === null || ident.funcOrStr === funcOrStr)) {
|
||||
disconnect(ident);
|
||||
if (lock === 0) {
|
||||
observers.splice(i, 1);
|
||||
} else {
|
||||
dirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
self._dirty = dirty;
|
||||
},
|
||||
|
||||
/** @id MochiKit.Signal.disconnectAll */
|
||||
disconnectAll: function (src/* optional */, sig) {
|
||||
if (typeof(src) == "string") {
|
||||
src = MochiKit.DOM.getElement(src);
|
||||
}
|
||||
var m = MochiKit.Base;
|
||||
var signals = m.flattenArguments(m.extend(null, arguments, 1));
|
||||
var self = MochiKit.Signal;
|
||||
var disconnect = self._disconnect;
|
||||
var observers = self._observers;
|
||||
var i, ident;
|
||||
var lock = self._lock;
|
||||
var dirty = self._dirty;
|
||||
if (signals.length === 0) {
|
||||
// disconnect all
|
||||
for (i = observers.length - 1; i >= 0; i--) {
|
||||
ident = observers[i];
|
||||
if (ident.source === src) {
|
||||
disconnect(ident);
|
||||
if (lock === 0) {
|
||||
observers.splice(i, 1);
|
||||
} else {
|
||||
dirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var sigs = {};
|
||||
for (i = 0; i < signals.length; i++) {
|
||||
sigs[signals[i]] = true;
|
||||
}
|
||||
for (i = observers.length - 1; i >= 0; i--) {
|
||||
ident = observers[i];
|
||||
if (ident.source === src && ident.signal in sigs) {
|
||||
disconnect(ident);
|
||||
if (lock === 0) {
|
||||
observers.splice(i, 1);
|
||||
} else {
|
||||
dirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
self._dirty = dirty;
|
||||
},
|
||||
|
||||
/** @id MochiKit.Signal.signal */
|
||||
signal: function (src, sig) {
|
||||
var self = MochiKit.Signal;
|
||||
var observers = self._observers;
|
||||
if (typeof(src) == "string") {
|
||||
src = MochiKit.DOM.getElement(src);
|
||||
}
|
||||
var args = MochiKit.Base.extend(null, arguments, 2);
|
||||
var errors = [];
|
||||
self._lock++;
|
||||
for (var i = 0; i < observers.length; i++) {
|
||||
var ident = observers[i];
|
||||
if (ident.source === src && ident.signal === sig &&
|
||||
ident.connected) {
|
||||
try {
|
||||
if (ident.isDOM && ident.funcOrStr != null) {
|
||||
var obj = ident.objOrFunc;
|
||||
obj[ident.funcOrStr].apply(obj, args);
|
||||
} else if (ident.isDOM) {
|
||||
ident.objOrFunc.apply(src, args);
|
||||
} else {
|
||||
ident.listener.apply(src, args);
|
||||
}
|
||||
} catch (e) {
|
||||
errors.push(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
self._lock--;
|
||||
if (self._lock === 0 && self._dirty) {
|
||||
self._dirty = false;
|
||||
for (var i = observers.length - 1; i >= 0; i--) {
|
||||
if (!observers[i].connected) {
|
||||
observers.splice(i, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (errors.length == 1) {
|
||||
throw errors[0];
|
||||
} else if (errors.length > 1) {
|
||||
var e = new Error("Multiple errors thrown in handling 'sig', see errors property");
|
||||
e.errors = errors;
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
MochiKit.Signal.__new__ = function (win) {
|
||||
var m = MochiKit.Base;
|
||||
this._document = document;
|
||||
this._window = win;
|
||||
this._lock = 0;
|
||||
this._dirty = false;
|
||||
|
||||
try {
|
||||
this.connect(window, 'onunload', this._unloadCache);
|
||||
} catch (e) {
|
||||
// pass: might not be a browser
|
||||
}
|
||||
|
||||
m.nameFunctions(this);
|
||||
};
|
||||
|
||||
MochiKit.Signal.__new__(this);
|
||||
|
||||
//
|
||||
// XXX: Internet Explorer blows
|
||||
//
|
||||
if (MochiKit.__export__) {
|
||||
connect = MochiKit.Signal.connect;
|
||||
disconnect = MochiKit.Signal.disconnect;
|
||||
disconnectAll = MochiKit.Signal.disconnectAll;
|
||||
signal = MochiKit.Signal.signal;
|
||||
}
|
||||
|
||||
MochiKit.Base._exportSymbols(this, MochiKit.Signal);
|
||||
592
frontend/delta/js/MochiKit/Sortable.js
Normal file
592
frontend/delta/js/MochiKit/Sortable.js
Normal file
@@ -0,0 +1,592 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
/***
|
||||
Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
|
||||
Mochi-ized By Thomas Herve (_firstname_@nimail.org)
|
||||
|
||||
See scriptaculous.js for full license.
|
||||
|
||||
***/
|
||||
|
||||
MochiKit.Base.module(MochiKit, 'Sortable', '1.5', ['Base', 'Iter', 'DOM', 'Position', 'DragAndDrop']);
|
||||
|
||||
MochiKit.Base.update(MochiKit.Sortable, {
|
||||
__export__: false,
|
||||
|
||||
/***
|
||||
|
||||
Manage sortables. Mainly use the create function to add a sortable.
|
||||
|
||||
***/
|
||||
sortables: {},
|
||||
|
||||
_findRootElement: function (element) {
|
||||
while (element.tagName.toUpperCase() != "BODY") {
|
||||
if (element.id && MochiKit.Sortable.sortables[element.id]) {
|
||||
return element;
|
||||
}
|
||||
element = element.parentNode;
|
||||
}
|
||||
},
|
||||
|
||||
_createElementId: function(element) {
|
||||
if (element.id == null || element.id == "") {
|
||||
var d = MochiKit.DOM;
|
||||
var id;
|
||||
var count = 1;
|
||||
while (d.getElement(id = "sortable" + count) != null) {
|
||||
count += 1;
|
||||
}
|
||||
d.setNodeAttribute(element, "id", id);
|
||||
}
|
||||
},
|
||||
|
||||
/** @id MochiKit.Sortable.options */
|
||||
options: function (element) {
|
||||
element = MochiKit.Sortable._findRootElement(MochiKit.DOM.getElement(element));
|
||||
if (!element) {
|
||||
return;
|
||||
}
|
||||
return MochiKit.Sortable.sortables[element.id];
|
||||
},
|
||||
|
||||
/** @id MochiKit.Sortable.destroy */
|
||||
destroy: function (element){
|
||||
var s = MochiKit.Sortable.options(element);
|
||||
var b = MochiKit.Base;
|
||||
var d = MochiKit.DragAndDrop;
|
||||
|
||||
if (s) {
|
||||
MochiKit.Signal.disconnect(s.startHandle);
|
||||
MochiKit.Signal.disconnect(s.endHandle);
|
||||
b.map(function (dr) {
|
||||
d.Droppables.remove(dr);
|
||||
}, s.droppables);
|
||||
b.map(function (dr) {
|
||||
dr.destroy();
|
||||
}, s.draggables);
|
||||
|
||||
delete MochiKit.Sortable.sortables[s.element.id];
|
||||
}
|
||||
},
|
||||
|
||||
/** @id MochiKit.Sortable.create */
|
||||
create: function (element, options) {
|
||||
element = MochiKit.DOM.getElement(element);
|
||||
var self = MochiKit.Sortable;
|
||||
self._createElementId(element);
|
||||
|
||||
/** @id MochiKit.Sortable.options */
|
||||
options = MochiKit.Base.update({
|
||||
|
||||
/** @id MochiKit.Sortable.element */
|
||||
element: element,
|
||||
|
||||
/** @id MochiKit.Sortable.tag */
|
||||
tag: 'li', // assumes li children, override with tag: 'tagname'
|
||||
|
||||
/** @id MochiKit.Sortable.dropOnEmpty */
|
||||
dropOnEmpty: false,
|
||||
|
||||
/** @id MochiKit.Sortable.tree */
|
||||
tree: false,
|
||||
|
||||
/** @id MochiKit.Sortable.treeTag */
|
||||
treeTag: 'ul',
|
||||
|
||||
/** @id MochiKit.Sortable.overlap */
|
||||
overlap: 'vertical', // one of 'vertical', 'horizontal'
|
||||
|
||||
/** @id MochiKit.Sortable.constraint */
|
||||
constraint: 'vertical', // one of 'vertical', 'horizontal', false
|
||||
// also takes array of elements (or ids); or false
|
||||
|
||||
/** @id MochiKit.Sortable.containment */
|
||||
containment: [element],
|
||||
|
||||
/** @id MochiKit.Sortable.handle */
|
||||
handle: false, // or a CSS class
|
||||
|
||||
/** @id MochiKit.Sortable.only */
|
||||
only: false,
|
||||
|
||||
/** @id MochiKit.Sortable.hoverclass */
|
||||
hoverclass: null,
|
||||
|
||||
/** @id MochiKit.Sortable.ghosting */
|
||||
ghosting: false,
|
||||
|
||||
/** @id MochiKit.Sortable.scroll */
|
||||
scroll: false,
|
||||
|
||||
/** @id MochiKit.Sortable.scrollSensitivity */
|
||||
scrollSensitivity: 20,
|
||||
|
||||
/** @id MochiKit.Sortable.scrollSpeed */
|
||||
scrollSpeed: 15,
|
||||
|
||||
/** @id MochiKit.Sortable.format */
|
||||
format: /^[^_]*_(.*)$/,
|
||||
|
||||
/** @id MochiKit.Sortable.onChange */
|
||||
onChange: MochiKit.Base.noop,
|
||||
|
||||
/** @id MochiKit.Sortable.onUpdate */
|
||||
onUpdate: MochiKit.Base.noop,
|
||||
|
||||
/** @id MochiKit.Sortable.accept */
|
||||
accept: null
|
||||
}, options);
|
||||
|
||||
// clear any old sortable with same element
|
||||
self.destroy(element);
|
||||
|
||||
// build options for the draggables
|
||||
var options_for_draggable = {
|
||||
revert: true,
|
||||
ghosting: options.ghosting,
|
||||
scroll: options.scroll,
|
||||
scrollSensitivity: options.scrollSensitivity,
|
||||
scrollSpeed: options.scrollSpeed,
|
||||
constraint: options.constraint,
|
||||
handle: options.handle
|
||||
};
|
||||
|
||||
if (options.starteffect) {
|
||||
options_for_draggable.starteffect = options.starteffect;
|
||||
}
|
||||
|
||||
if (options.reverteffect) {
|
||||
options_for_draggable.reverteffect = options.reverteffect;
|
||||
} else if (options.ghosting) {
|
||||
options_for_draggable.reverteffect = function (innerelement) {
|
||||
innerelement.style.top = 0;
|
||||
innerelement.style.left = 0;
|
||||
};
|
||||
}
|
||||
|
||||
if (options.endeffect) {
|
||||
options_for_draggable.endeffect = options.endeffect;
|
||||
}
|
||||
|
||||
if (options.zindex) {
|
||||
options_for_draggable.zindex = options.zindex;
|
||||
}
|
||||
|
||||
// build options for the droppables
|
||||
var options_for_droppable = {
|
||||
overlap: options.overlap,
|
||||
containment: options.containment,
|
||||
hoverclass: options.hoverclass,
|
||||
onhover: self.onHover,
|
||||
tree: options.tree,
|
||||
accept: options.accept
|
||||
};
|
||||
|
||||
var options_for_tree = {
|
||||
onhover: self.onEmptyHover,
|
||||
overlap: options.overlap,
|
||||
containment: options.containment,
|
||||
hoverclass: options.hoverclass,
|
||||
accept: options.accept
|
||||
};
|
||||
|
||||
// fix for gecko engine
|
||||
MochiKit.DOM.removeEmptyTextNodes(element);
|
||||
|
||||
options.draggables = [];
|
||||
options.droppables = [];
|
||||
|
||||
// drop on empty handling
|
||||
if (options.dropOnEmpty || options.tree) {
|
||||
new MochiKit.DragAndDrop.Droppable(element, options_for_tree);
|
||||
options.droppables.push(element);
|
||||
}
|
||||
MochiKit.Base.map(function (e) {
|
||||
// handles are per-draggable
|
||||
var handle = options.handle ?
|
||||
MochiKit.DOM.getFirstElementByTagAndClassName(null,
|
||||
options.handle, e) : e;
|
||||
options.draggables.push(
|
||||
new MochiKit.DragAndDrop.Draggable(e,
|
||||
MochiKit.Base.update(options_for_draggable,
|
||||
{handle: handle})));
|
||||
new MochiKit.DragAndDrop.Droppable(e, options_for_droppable);
|
||||
if (options.tree) {
|
||||
e.treeNode = element;
|
||||
}
|
||||
options.droppables.push(e);
|
||||
}, (self.findElements(element, options) || []));
|
||||
|
||||
if (options.tree) {
|
||||
MochiKit.Base.map(function (e) {
|
||||
new MochiKit.DragAndDrop.Droppable(e, options_for_tree);
|
||||
e.treeNode = element;
|
||||
options.droppables.push(e);
|
||||
}, (self.findTreeElements(element, options) || []));
|
||||
}
|
||||
|
||||
// keep reference
|
||||
self.sortables[element.id] = options;
|
||||
|
||||
options.lastValue = self.serialize(element);
|
||||
options.startHandle = MochiKit.Signal.connect(MochiKit.DragAndDrop.Draggables, 'start',
|
||||
MochiKit.Base.partial(self.onStart, element));
|
||||
options.endHandle = MochiKit.Signal.connect(MochiKit.DragAndDrop.Draggables, 'end',
|
||||
MochiKit.Base.partial(self.onEnd, element));
|
||||
},
|
||||
|
||||
/** @id MochiKit.Sortable.onStart */
|
||||
onStart: function (element, draggable) {
|
||||
var self = MochiKit.Sortable;
|
||||
var options = self.options(element);
|
||||
options.lastValue = self.serialize(options.element);
|
||||
},
|
||||
|
||||
/** @id MochiKit.Sortable.onEnd */
|
||||
onEnd: function (element, draggable) {
|
||||
var self = MochiKit.Sortable;
|
||||
self.unmark();
|
||||
var options = self.options(element);
|
||||
if (options.lastValue != self.serialize(options.element)) {
|
||||
options.onUpdate(options.element);
|
||||
}
|
||||
},
|
||||
|
||||
// return all suitable-for-sortable elements in a guaranteed order
|
||||
|
||||
/** @id MochiKit.Sortable.findElements */
|
||||
findElements: function (element, options) {
|
||||
return MochiKit.Sortable.findChildren(element, options.only, options.tree, options.tag);
|
||||
},
|
||||
|
||||
/** @id MochiKit.Sortable.findTreeElements */
|
||||
findTreeElements: function (element, options) {
|
||||
return MochiKit.Sortable.findChildren(
|
||||
element, options.only, options.tree ? true : false, options.treeTag);
|
||||
},
|
||||
|
||||
/** @id MochiKit.Sortable.findChildren */
|
||||
findChildren: function (element, only, recursive, tagName) {
|
||||
if (!element.hasChildNodes()) {
|
||||
return null;
|
||||
}
|
||||
tagName = tagName.toUpperCase();
|
||||
if (only) {
|
||||
only = MochiKit.Base.flattenArray([only]);
|
||||
}
|
||||
var elements = [];
|
||||
MochiKit.Base.map(function (e) {
|
||||
if (e.tagName &&
|
||||
e.tagName.toUpperCase() == tagName &&
|
||||
(!only ||
|
||||
MochiKit.Iter.some(only, function (c) {
|
||||
return MochiKit.DOM.hasElementClass(e, c);
|
||||
}))) {
|
||||
elements.push(e);
|
||||
}
|
||||
if (recursive) {
|
||||
var grandchildren = MochiKit.Sortable.findChildren(e, only, recursive, tagName);
|
||||
if (grandchildren && grandchildren.length > 0) {
|
||||
elements = elements.concat(grandchildren);
|
||||
}
|
||||
}
|
||||
}, element.childNodes);
|
||||
return elements;
|
||||
},
|
||||
|
||||
/** @id MochiKit.Sortable.onHover */
|
||||
onHover: function (element, dropon, overlap) {
|
||||
if (MochiKit.DOM.isChildNode(dropon, element)) {
|
||||
return;
|
||||
}
|
||||
var self = MochiKit.Sortable;
|
||||
|
||||
if (overlap > .33 && overlap < .66 && self.options(dropon).tree) {
|
||||
return;
|
||||
} else if (overlap > 0.5) {
|
||||
self.mark(dropon, 'before');
|
||||
if (dropon.previousSibling != element) {
|
||||
var oldParentNode = element.parentNode;
|
||||
element.style.visibility = 'hidden'; // fix gecko rendering
|
||||
dropon.parentNode.insertBefore(element, dropon);
|
||||
if (dropon.parentNode != oldParentNode) {
|
||||
self.options(oldParentNode).onChange(element);
|
||||
}
|
||||
self.options(dropon.parentNode).onChange(element);
|
||||
}
|
||||
} else {
|
||||
self.mark(dropon, 'after');
|
||||
var nextElement = dropon.nextSibling || null;
|
||||
if (nextElement != element) {
|
||||
var oldParentNode = element.parentNode;
|
||||
element.style.visibility = 'hidden'; // fix gecko rendering
|
||||
dropon.parentNode.insertBefore(element, nextElement);
|
||||
if (dropon.parentNode != oldParentNode) {
|
||||
self.options(oldParentNode).onChange(element);
|
||||
}
|
||||
self.options(dropon.parentNode).onChange(element);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_offsetSize: function (element, type) {
|
||||
if (type == 'vertical' || type == 'height') {
|
||||
return element.offsetHeight;
|
||||
} else {
|
||||
return element.offsetWidth;
|
||||
}
|
||||
},
|
||||
|
||||
/** @id MochiKit.Sortable.onEmptyHover */
|
||||
onEmptyHover: function (element, dropon, overlap) {
|
||||
var oldParentNode = element.parentNode;
|
||||
var self = MochiKit.Sortable;
|
||||
var droponOptions = self.options(dropon);
|
||||
|
||||
if (!MochiKit.DOM.isChildNode(dropon, element)) {
|
||||
var index;
|
||||
|
||||
var children = self.findElements(dropon, {tag: droponOptions.tag,
|
||||
only: droponOptions.only});
|
||||
var child = null;
|
||||
|
||||
if (children) {
|
||||
var offset = self._offsetSize(dropon, droponOptions.overlap) * (1.0 - overlap);
|
||||
|
||||
for (index = 0; index < children.length; index += 1) {
|
||||
if (offset - self._offsetSize(children[index], droponOptions.overlap) >= 0) {
|
||||
offset -= self._offsetSize(children[index], droponOptions.overlap);
|
||||
} else if (offset - (self._offsetSize (children[index], droponOptions.overlap) / 2) >= 0) {
|
||||
child = index + 1 < children.length ? children[index + 1] : null;
|
||||
break;
|
||||
} else {
|
||||
child = children[index];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dropon.insertBefore(element, child);
|
||||
|
||||
self.options(oldParentNode).onChange(element);
|
||||
droponOptions.onChange(element);
|
||||
}
|
||||
},
|
||||
|
||||
/** @id MochiKit.Sortable.unmark */
|
||||
unmark: function () {
|
||||
var m = MochiKit.Sortable._marker;
|
||||
if (m) {
|
||||
MochiKit.Style.hideElement(m);
|
||||
}
|
||||
},
|
||||
|
||||
/** @id MochiKit.Sortable.mark */
|
||||
mark: function (dropon, position) {
|
||||
// mark on ghosting only
|
||||
var d = MochiKit.DOM;
|
||||
var self = MochiKit.Sortable;
|
||||
var sortable = self.options(dropon.parentNode);
|
||||
if (sortable && !sortable.ghosting) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!self._marker) {
|
||||
self._marker = d.getElement('dropmarker') ||
|
||||
document.createElement('DIV');
|
||||
MochiKit.Style.hideElement(self._marker);
|
||||
d.addElementClass(self._marker, 'dropmarker');
|
||||
self._marker.style.position = 'absolute';
|
||||
document.getElementsByTagName('body').item(0).appendChild(self._marker);
|
||||
}
|
||||
var offsets = MochiKit.Position.cumulativeOffset(dropon);
|
||||
self._marker.style.left = offsets.x + 'px';
|
||||
self._marker.style.top = offsets.y + 'px';
|
||||
|
||||
if (position == 'after') {
|
||||
if (sortable.overlap == 'horizontal') {
|
||||
self._marker.style.left = (offsets.x + dropon.clientWidth) + 'px';
|
||||
} else {
|
||||
self._marker.style.top = (offsets.y + dropon.clientHeight) + 'px';
|
||||
}
|
||||
}
|
||||
MochiKit.Style.showElement(self._marker);
|
||||
},
|
||||
|
||||
_tree: function (element, options, parent) {
|
||||
var self = MochiKit.Sortable;
|
||||
var children = self.findElements(element, options) || [];
|
||||
|
||||
for (var i = 0; i < children.length; ++i) {
|
||||
var match = children[i].id.match(options.format);
|
||||
|
||||
if (!match) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var child = {
|
||||
id: encodeURIComponent(match ? match[1] : null),
|
||||
element: element,
|
||||
parent: parent,
|
||||
children: [],
|
||||
position: parent.children.length,
|
||||
container: self._findChildrenElement(children[i], options.treeTag.toUpperCase())
|
||||
};
|
||||
|
||||
/* Get the element containing the children and recurse over it */
|
||||
if (child.container) {
|
||||
self._tree(child.container, options, child);
|
||||
}
|
||||
|
||||
parent.children.push (child);
|
||||
}
|
||||
|
||||
return parent;
|
||||
},
|
||||
|
||||
/* Finds the first element of the given tag type within a parent element.
|
||||
Used for finding the first LI[ST] within a L[IST]I[TEM].*/
|
||||
_findChildrenElement: function (element, containerTag) {
|
||||
if (element && element.hasChildNodes) {
|
||||
containerTag = containerTag.toUpperCase();
|
||||
for (var i = 0; i < element.childNodes.length; ++i) {
|
||||
if (element.childNodes[i].tagName.toUpperCase() == containerTag) {
|
||||
return element.childNodes[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
/** @id MochiKit.Sortable.tree */
|
||||
tree: function (element, options) {
|
||||
element = MochiKit.DOM.getElement(element);
|
||||
var sortableOptions = MochiKit.Sortable.options(element);
|
||||
options = MochiKit.Base.update({
|
||||
tag: sortableOptions.tag,
|
||||
treeTag: sortableOptions.treeTag,
|
||||
only: sortableOptions.only,
|
||||
name: element.id,
|
||||
format: sortableOptions.format
|
||||
}, options || {});
|
||||
|
||||
var root = {
|
||||
id: null,
|
||||
parent: null,
|
||||
children: new Array,
|
||||
container: element,
|
||||
position: 0
|
||||
};
|
||||
|
||||
return MochiKit.Sortable._tree(element, options, root);
|
||||
},
|
||||
|
||||
/**
|
||||
* Specifies the sequence for the Sortable.
|
||||
* @param {Node} element Element to use as the Sortable.
|
||||
* @param {Object} newSequence New sequence to use.
|
||||
* @param {Object} options Options to use fro the Sortable.
|
||||
*/
|
||||
setSequence: function (element, newSequence, options) {
|
||||
var self = MochiKit.Sortable;
|
||||
var b = MochiKit.Base;
|
||||
element = MochiKit.DOM.getElement(element);
|
||||
options = b.update(self.options(element), options || {});
|
||||
|
||||
var nodeMap = {};
|
||||
b.map(function (n) {
|
||||
var m = n.id.match(options.format);
|
||||
if (m) {
|
||||
nodeMap[m[1]] = [n, n.parentNode];
|
||||
}
|
||||
n.parentNode.removeChild(n);
|
||||
}, self.findElements(element, options));
|
||||
|
||||
b.map(function (ident) {
|
||||
var n = nodeMap[ident];
|
||||
if (n) {
|
||||
n[1].appendChild(n[0]);
|
||||
delete nodeMap[ident];
|
||||
}
|
||||
}, newSequence);
|
||||
},
|
||||
|
||||
/* Construct a [i] index for a particular node */
|
||||
_constructIndex: function (node) {
|
||||
var index = '';
|
||||
do {
|
||||
if (node.id) {
|
||||
index = '[' + node.position + ']' + index;
|
||||
}
|
||||
} while ((node = node.parent) != null);
|
||||
return index;
|
||||
},
|
||||
|
||||
/** @id MochiKit.Sortable.sequence */
|
||||
sequence: function (element, options) {
|
||||
element = MochiKit.DOM.getElement(element);
|
||||
var self = MochiKit.Sortable;
|
||||
var options = MochiKit.Base.update(self.options(element), options || {});
|
||||
|
||||
return MochiKit.Base.map(function (item) {
|
||||
return item.id.match(options.format) ? item.id.match(options.format)[1] : '';
|
||||
}, MochiKit.DOM.getElement(self.findElements(element, options) || []));
|
||||
},
|
||||
|
||||
/**
|
||||
* Serializes the content of a Sortable. Useful to send this content through a XMLHTTPRequest.
|
||||
* These options override the Sortable options for the serialization only.
|
||||
* @param {Node} element Element to serialize.
|
||||
* @param {Object} options Serialization options.
|
||||
*/
|
||||
serialize: function (element, options) {
|
||||
element = MochiKit.DOM.getElement(element);
|
||||
var self = MochiKit.Sortable;
|
||||
options = MochiKit.Base.update(self.options(element), options || {});
|
||||
var name = encodeURIComponent(options.name || element.id);
|
||||
|
||||
if (options.tree) {
|
||||
return MochiKit.Base.flattenArray(MochiKit.Base.map(function (item) {
|
||||
return [name + self._constructIndex(item) + "[id]=" +
|
||||
encodeURIComponent(item.id)].concat(item.children.map(arguments.callee));
|
||||
}, self.tree(element, options).children)).join('&');
|
||||
} else {
|
||||
return MochiKit.Base.map(function (item) {
|
||||
return name + "[]=" + encodeURIComponent(item);
|
||||
}, self.sequence(element, options)).join('&');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// trunk compatibility
|
||||
MochiKit.Sortable.Sortable = MochiKit.Sortable;
|
||||
|
||||
MochiKit.Sortable.__new__ = function () {
|
||||
MochiKit.Base.nameFunctions(this);
|
||||
};
|
||||
|
||||
MochiKit.Sortable.__new__();
|
||||
|
||||
MochiKit.Base._exportSymbols(this, MochiKit.Sortable);
|
||||
584
frontend/delta/js/MochiKit/Style.js
Normal file
584
frontend/delta/js/MochiKit/Style.js
Normal file
@@ -0,0 +1,584 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
/***
|
||||
|
||||
MochiKit.Style 1.5
|
||||
|
||||
See <http://mochikit.com/> for documentation, downloads, license, etc.
|
||||
|
||||
(c) 2005-2006 Bob Ippolito, Beau Hartshorne. All rights Reserved.
|
||||
|
||||
The MochiKit.Style.getElementPosition function is adapted from
|
||||
YAHOO.util.Dom.getXY v0.9.0. which is copyrighted by Yahoo! Inc.
|
||||
|
||||
***/
|
||||
|
||||
MochiKit.Base.module(MochiKit, 'Style', '1.5', ['Base', 'DOM']);
|
||||
|
||||
|
||||
/** @id MochiKit.Style.Dimensions */
|
||||
MochiKit.Style.Dimensions = function (w, h) {
|
||||
if (!(this instanceof MochiKit.Style.Dimensions)) {
|
||||
return new MochiKit.Style.Dimensions(w, h);
|
||||
}
|
||||
this.w = w;
|
||||
this.h = h;
|
||||
};
|
||||
|
||||
MochiKit.Style.Dimensions.prototype.__repr__ = function () {
|
||||
var repr = MochiKit.Base.repr;
|
||||
return '{w: ' + repr(this.w) + ', h: ' + repr(this.h) + '}';
|
||||
};
|
||||
|
||||
MochiKit.Style.Dimensions.prototype.toString = function () {
|
||||
return this.__repr__();
|
||||
};
|
||||
|
||||
|
||||
/** @id MochiKit.Style.Coordinates */
|
||||
MochiKit.Style.Coordinates = function (x, y) {
|
||||
if (!(this instanceof MochiKit.Style.Coordinates)) {
|
||||
return new MochiKit.Style.Coordinates(x, y);
|
||||
}
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
};
|
||||
|
||||
MochiKit.Style.Coordinates.prototype.__repr__ = function () {
|
||||
var repr = MochiKit.Base.repr;
|
||||
return '{x: ' + repr(this.x) + ', y: ' + repr(this.y) + '}';
|
||||
};
|
||||
|
||||
MochiKit.Style.Coordinates.prototype.toString = function () {
|
||||
return this.__repr__();
|
||||
};
|
||||
|
||||
|
||||
MochiKit.Base.update(MochiKit.Style, {
|
||||
|
||||
/** @id MochiKit.Style.getStyle */
|
||||
getStyle: function (elem, cssProperty) {
|
||||
var dom = MochiKit.DOM;
|
||||
var d = dom._document;
|
||||
|
||||
elem = dom.getElement(elem);
|
||||
cssProperty = MochiKit.Base.camelize(cssProperty);
|
||||
|
||||
if (!elem || elem == d) {
|
||||
return undefined;
|
||||
}
|
||||
if (cssProperty == 'opacity' && typeof(elem.filters) != 'undefined') {
|
||||
var opacity = (MochiKit.Style.getStyle(elem, 'filter') || '').match(/alpha\(opacity=(.*)\)/);
|
||||
if (opacity && opacity[1]) {
|
||||
return parseFloat(opacity[1]) / 100;
|
||||
}
|
||||
return 1.0;
|
||||
}
|
||||
if (cssProperty == 'float' || cssProperty == 'cssFloat' || cssProperty == 'styleFloat') {
|
||||
if (elem.style["float"]) {
|
||||
return elem.style["float"];
|
||||
} else if (elem.style.cssFloat) {
|
||||
return elem.style.cssFloat;
|
||||
} else if (elem.style.styleFloat) {
|
||||
return elem.style.styleFloat;
|
||||
} else {
|
||||
return "none";
|
||||
}
|
||||
}
|
||||
var value = elem.style ? elem.style[cssProperty] : null;
|
||||
if (!value) {
|
||||
if (d.defaultView && d.defaultView.getComputedStyle) {
|
||||
var css = d.defaultView.getComputedStyle(elem, null);
|
||||
cssProperty = cssProperty.replace(/([A-Z])/g, '-$1'
|
||||
).toLowerCase(); // from dojo.style.toSelectorCase
|
||||
value = css ? css.getPropertyValue(cssProperty) : null;
|
||||
} else if (elem.currentStyle) {
|
||||
value = elem.currentStyle[cssProperty];
|
||||
if (/^\d/.test(value) && !/px$/.test(value) && cssProperty != 'fontWeight') {
|
||||
/* Convert to px using an hack from Dean Edwards */
|
||||
var left = elem.style.left;
|
||||
var rsLeft = elem.runtimeStyle.left;
|
||||
elem.runtimeStyle.left = elem.currentStyle.left;
|
||||
elem.style.left = value || 0;
|
||||
value = elem.style.pixelLeft + "px";
|
||||
elem.style.left = left;
|
||||
elem.runtimeStyle.left = rsLeft;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cssProperty == 'opacity') {
|
||||
value = parseFloat(value);
|
||||
}
|
||||
|
||||
if (/Opera/.test(navigator.userAgent) && (MochiKit.Base.findValue(['left', 'top', 'right', 'bottom'], cssProperty) != -1)) {
|
||||
if (MochiKit.Style.getStyle(elem, 'position') == 'static') {
|
||||
value = 'auto';
|
||||
}
|
||||
}
|
||||
|
||||
return value == 'auto' ? null : value;
|
||||
},
|
||||
|
||||
/** @id MochiKit.Style.setStyle */
|
||||
setStyle: function (elem, style) {
|
||||
elem = MochiKit.DOM.getElement(elem);
|
||||
for (var name in style) {
|
||||
switch (name) {
|
||||
case 'opacity':
|
||||
MochiKit.Style.setOpacity(elem, style[name]);
|
||||
break;
|
||||
case 'float':
|
||||
case 'cssFloat':
|
||||
case 'styleFloat':
|
||||
if (typeof(elem.style["float"]) != "undefined") {
|
||||
elem.style["float"] = style[name];
|
||||
} else if (typeof(elem.style.cssFloat) != "undefined") {
|
||||
elem.style.cssFloat = style[name];
|
||||
} else {
|
||||
elem.style.styleFloat = style[name];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
elem.style[MochiKit.Base.camelize(name)] = style[name];
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/** @id MochiKit.Style.setOpacity */
|
||||
setOpacity: function (elem, o) {
|
||||
elem = MochiKit.DOM.getElement(elem);
|
||||
var self = MochiKit.Style;
|
||||
if (o == 1) {
|
||||
var toSet = /Gecko/.test(navigator.userAgent) && !(/Konqueror|AppleWebKit|KHTML/.test(navigator.userAgent));
|
||||
elem.style["opacity"] = toSet ? 0.999999 : 1.0;
|
||||
if (/MSIE/.test(navigator.userAgent)) {
|
||||
elem.style['filter'] =
|
||||
self.getStyle(elem, 'filter').replace(/alpha\([^\)]*\)/gi, '');
|
||||
}
|
||||
} else {
|
||||
if (o < 0.00001) {
|
||||
o = 0;
|
||||
}
|
||||
elem.style["opacity"] = o;
|
||||
if (/MSIE/.test(navigator.userAgent)) {
|
||||
elem.style['filter'] =
|
||||
self.getStyle(elem, 'filter').replace(/alpha\([^\)]*\)/gi, '') + 'alpha(opacity=' + o * 100 + ')';
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/*
|
||||
|
||||
getElementPosition is adapted from YAHOO.util.Dom.getXY v0.9.0.
|
||||
Copyright: Copyright (c) 2006, Yahoo! Inc. All rights reserved.
|
||||
License: BSD, http://developer.yahoo.net/yui/license.txt
|
||||
|
||||
*/
|
||||
|
||||
/** @id MochiKit.Style.getElementPosition */
|
||||
getElementPosition: function (elem, /* optional */relativeTo) {
|
||||
var self = MochiKit.Style;
|
||||
var dom = MochiKit.DOM;
|
||||
var isCoordinates = function (o) {
|
||||
return o != null &&
|
||||
o.nodeType == null &&
|
||||
typeof(o.x) == "number" &&
|
||||
typeof(o.y) == "number";
|
||||
};
|
||||
|
||||
if (typeof(elem) == "string") {
|
||||
elem = dom.getElement(elem);
|
||||
}
|
||||
if (elem == null ||
|
||||
(!isCoordinates(elem) && self.getStyle(elem, 'display') == 'none')) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
var c = new self.Coordinates(0, 0);
|
||||
var box = null;
|
||||
var parent = null;
|
||||
|
||||
var d = MochiKit.DOM._document;
|
||||
var de = d.documentElement;
|
||||
var b = d.body;
|
||||
|
||||
if (isCoordinates(elem)) {
|
||||
/* it's just a MochiKit.Style.Coordinates object */
|
||||
c.x += elem.x || 0;
|
||||
c.y += elem.y || 0;
|
||||
} else if (elem.getBoundingClientRect) { // IE shortcut
|
||||
/*
|
||||
|
||||
The IE shortcut can be off by two. We fix it. See:
|
||||
http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/getboundingclientrect.asp
|
||||
|
||||
This is similar to the method used in
|
||||
MochiKit.Signal.Event.mouse().
|
||||
|
||||
*/
|
||||
box = elem.getBoundingClientRect();
|
||||
|
||||
c.x += box.left +
|
||||
(de.scrollLeft || b.scrollLeft) -
|
||||
(de.clientLeft || 0);
|
||||
|
||||
c.y += box.top +
|
||||
(de.scrollTop || b.scrollTop) -
|
||||
(de.clientTop || 0);
|
||||
|
||||
} else if (elem.offsetParent) {
|
||||
c.x += elem.offsetLeft;
|
||||
c.y += elem.offsetTop;
|
||||
parent = elem.offsetParent;
|
||||
|
||||
if (parent != elem) {
|
||||
while (parent) {
|
||||
c.x += parseInt(parent.style.borderLeftWidth, 10) || 0;
|
||||
c.y += parseInt(parent.style.borderTopWidth, 10) || 0;
|
||||
c.x += parent.offsetLeft;
|
||||
c.y += parent.offsetTop;
|
||||
parent = parent.offsetParent;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Opera < 9 and old Safari (absolute) incorrectly account for
|
||||
body offsetTop and offsetLeft.
|
||||
|
||||
*/
|
||||
var ua = navigator.userAgent.toLowerCase();
|
||||
if ((typeof(opera) != 'undefined' &&
|
||||
parseFloat(opera.version()) < 9) ||
|
||||
(ua.indexOf('AppleWebKit') != -1 &&
|
||||
self.getStyle(elem, 'position') == 'absolute')) {
|
||||
|
||||
c.x -= b.offsetLeft;
|
||||
c.y -= b.offsetTop;
|
||||
|
||||
}
|
||||
|
||||
// Adjust position for strange Opera scroll bug
|
||||
if (elem.parentNode) {
|
||||
parent = elem.parentNode;
|
||||
} else {
|
||||
parent = null;
|
||||
}
|
||||
while (parent) {
|
||||
var tagName = parent.tagName.toUpperCase();
|
||||
if (tagName === 'BODY' || tagName === 'HTML') {
|
||||
break;
|
||||
}
|
||||
var disp = self.getStyle(parent, 'display');
|
||||
// Handle strange Opera bug for some display
|
||||
if (disp.search(/^inline|table-row.*$/i)) {
|
||||
c.x -= parent.scrollLeft;
|
||||
c.y -= parent.scrollTop;
|
||||
}
|
||||
if (parent.parentNode) {
|
||||
parent = parent.parentNode;
|
||||
} else {
|
||||
parent = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (relativeTo) {
|
||||
relativeTo = arguments.callee(relativeTo);
|
||||
if (relativeTo) {
|
||||
c.x -= (relativeTo.x || 0);
|
||||
c.y -= (relativeTo.y || 0);
|
||||
}
|
||||
}
|
||||
|
||||
return c;
|
||||
},
|
||||
|
||||
/** @id MochiKit.Style.setElementPosition */
|
||||
setElementPosition: function (elem, newPos/* optional */, units) {
|
||||
elem = MochiKit.DOM.getElement(elem);
|
||||
if (typeof(units) == 'undefined') {
|
||||
units = 'px';
|
||||
}
|
||||
var newStyle = {};
|
||||
var isUndefNull = MochiKit.Base.isUndefinedOrNull;
|
||||
if (!isUndefNull(newPos.x)) {
|
||||
newStyle['left'] = newPos.x + units;
|
||||
}
|
||||
if (!isUndefNull(newPos.y)) {
|
||||
newStyle['top'] = newPos.y + units;
|
||||
}
|
||||
MochiKit.DOM.updateNodeAttributes(elem, {'style': newStyle});
|
||||
},
|
||||
|
||||
/** @id MochiKit.Style.makePositioned */
|
||||
makePositioned: function (element) {
|
||||
element = MochiKit.DOM.getElement(element);
|
||||
var pos = MochiKit.Style.getStyle(element, 'position');
|
||||
if (pos == 'static' || !pos) {
|
||||
element.style.position = 'relative';
|
||||
// Opera returns the offset relative to the positioning context,
|
||||
// when an element is position relative but top and left have
|
||||
// not been defined
|
||||
if (/Opera/.test(navigator.userAgent)) {
|
||||
element.style.top = 0;
|
||||
element.style.left = 0;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/** @id MochiKit.Style.undoPositioned */
|
||||
undoPositioned: function (element) {
|
||||
element = MochiKit.DOM.getElement(element);
|
||||
if (element.style.position == 'relative') {
|
||||
element.style.position = element.style.top = element.style.left = element.style.bottom = element.style.right = '';
|
||||
}
|
||||
},
|
||||
|
||||
/** @id MochiKit.Style.makeClipping */
|
||||
makeClipping: function (element) {
|
||||
element = MochiKit.DOM.getElement(element);
|
||||
var s = element.style;
|
||||
var oldOverflow = { 'overflow': s.overflow,
|
||||
'overflow-x': s.overflowX,
|
||||
'overflow-y': s.overflowY };
|
||||
if ((MochiKit.Style.getStyle(element, 'overflow') || 'visible') != 'hidden') {
|
||||
element.style.overflow = 'hidden';
|
||||
element.style.overflowX = 'hidden';
|
||||
element.style.overflowY = 'hidden';
|
||||
}
|
||||
return oldOverflow;
|
||||
},
|
||||
|
||||
/** @id MochiKit.Style.undoClipping */
|
||||
undoClipping: function (element, overflow) {
|
||||
element = MochiKit.DOM.getElement(element);
|
||||
if (typeof(overflow) == 'string') {
|
||||
element.style.overflow = overflow;
|
||||
} else if (overflow != null) {
|
||||
element.style.overflow = overflow['overflow'];
|
||||
element.style.overflowX = overflow['overflow-x'];
|
||||
element.style.overflowY = overflow['overflow-y'];
|
||||
}
|
||||
},
|
||||
|
||||
/** @id MochiKit.Style.getElementDimensions */
|
||||
getElementDimensions: function (elem, contentSize/*optional*/) {
|
||||
var self = MochiKit.Style;
|
||||
var dom = MochiKit.DOM;
|
||||
if (typeof(elem.w) == 'number' || typeof(elem.h) == 'number') {
|
||||
return new self.Dimensions(elem.w || 0, elem.h || 0);
|
||||
}
|
||||
elem = dom.getElement(elem);
|
||||
if (!elem) {
|
||||
return undefined;
|
||||
}
|
||||
var disp = self.getStyle(elem, 'display');
|
||||
// display can be empty/undefined on WebKit/KHTML
|
||||
if (disp == 'none' || disp == '' || typeof(disp) == 'undefined') {
|
||||
var s = elem.style;
|
||||
var originalVisibility = s.visibility;
|
||||
var originalPosition = s.position;
|
||||
var originalDisplay = s.display;
|
||||
s.visibility = 'hidden';
|
||||
s.position = 'absolute';
|
||||
s.display = self._getDefaultDisplay(elem);
|
||||
var originalWidth = elem.offsetWidth;
|
||||
var originalHeight = elem.offsetHeight;
|
||||
s.display = originalDisplay;
|
||||
s.position = originalPosition;
|
||||
s.visibility = originalVisibility;
|
||||
} else {
|
||||
originalWidth = elem.offsetWidth || 0;
|
||||
originalHeight = elem.offsetHeight || 0;
|
||||
}
|
||||
if (contentSize) {
|
||||
var tableCell = 'colSpan' in elem && 'rowSpan' in elem;
|
||||
var collapse = (tableCell && elem.parentNode && self.getStyle(
|
||||
elem.parentNode, 'borderCollapse') == 'collapse');
|
||||
if (collapse) {
|
||||
if (/MSIE/.test(navigator.userAgent)) {
|
||||
var borderLeftQuota = elem.previousSibling? 0.5 : 1;
|
||||
var borderRightQuota = elem.nextSibling? 0.5 : 1;
|
||||
}
|
||||
else {
|
||||
var borderLeftQuota = 0.5;
|
||||
var borderRightQuota = 0.5;
|
||||
}
|
||||
} else {
|
||||
var borderLeftQuota = 1;
|
||||
var borderRightQuota = 1;
|
||||
}
|
||||
originalWidth -= Math.round(
|
||||
(parseFloat(self.getStyle(elem, 'paddingLeft')) || 0)
|
||||
+ (parseFloat(self.getStyle(elem, 'paddingRight')) || 0)
|
||||
+ borderLeftQuota *
|
||||
(parseFloat(self.getStyle(elem, 'borderLeftWidth')) || 0)
|
||||
+ borderRightQuota *
|
||||
(parseFloat(self.getStyle(elem, 'borderRightWidth')) || 0)
|
||||
);
|
||||
if (tableCell) {
|
||||
if (/Gecko|Opera/.test(navigator.userAgent)
|
||||
&& !/Konqueror|AppleWebKit|KHTML/.test(navigator.userAgent)) {
|
||||
var borderHeightQuota = 0;
|
||||
} else if (/MSIE/.test(navigator.userAgent)) {
|
||||
var borderHeightQuota = 1;
|
||||
} else {
|
||||
var borderHeightQuota = collapse? 0.5 : 1;
|
||||
}
|
||||
} else {
|
||||
var borderHeightQuota = 1;
|
||||
}
|
||||
originalHeight -= Math.round(
|
||||
(parseFloat(self.getStyle(elem, 'paddingTop')) || 0)
|
||||
+ (parseFloat(self.getStyle(elem, 'paddingBottom')) || 0)
|
||||
+ borderHeightQuota * (
|
||||
(parseFloat(self.getStyle(elem, 'borderTopWidth')) || 0)
|
||||
+ (parseFloat(self.getStyle(elem, 'borderBottomWidth')) || 0))
|
||||
);
|
||||
}
|
||||
return new self.Dimensions(originalWidth, originalHeight);
|
||||
},
|
||||
|
||||
/** @id MochiKit.Style.setElementDimensions */
|
||||
setElementDimensions: function (elem, newSize/* optional */, units) {
|
||||
elem = MochiKit.DOM.getElement(elem);
|
||||
if (typeof(units) == 'undefined') {
|
||||
units = 'px';
|
||||
}
|
||||
var newStyle = {};
|
||||
var isUndefNull = MochiKit.Base.isUndefinedOrNull;
|
||||
if (!isUndefNull(newSize.w)) {
|
||||
newStyle['width'] = newSize.w + units;
|
||||
}
|
||||
if (!isUndefNull(newSize.h)) {
|
||||
newStyle['height'] = newSize.h + units;
|
||||
}
|
||||
MochiKit.DOM.updateNodeAttributes(elem, {'style': newStyle});
|
||||
},
|
||||
|
||||
_getDefaultDisplay: function (elem) {
|
||||
var self = MochiKit.Style;
|
||||
var dom = MochiKit.DOM;
|
||||
elem = dom.getElement(elem);
|
||||
if (!elem) {
|
||||
return undefined;
|
||||
}
|
||||
var tagName = elem.tagName.toUpperCase();
|
||||
return self._defaultDisplay[tagName] || 'block';
|
||||
},
|
||||
|
||||
/** @id MochiKit.Style.setDisplayForElement */
|
||||
setDisplayForElement: function (display, element/*, ...*/) {
|
||||
var elements = MochiKit.Base.extend(null, arguments, 1);
|
||||
var getElement = MochiKit.DOM.getElement;
|
||||
for (var i = 0; i < elements.length; i++) {
|
||||
element = getElement(elements[i]);
|
||||
if (element) {
|
||||
element.style.display = display;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/** @id MochiKit.Style.getViewportDimensions */
|
||||
getViewportDimensions: function () {
|
||||
var d = new MochiKit.Style.Dimensions();
|
||||
var w = MochiKit.DOM._window;
|
||||
var b = MochiKit.DOM._document.body;
|
||||
if (w.innerWidth) {
|
||||
d.w = w.innerWidth;
|
||||
d.h = w.innerHeight;
|
||||
} else if (b && b.parentElement && b.parentElement.clientWidth) {
|
||||
d.w = b.parentElement.clientWidth;
|
||||
d.h = b.parentElement.clientHeight;
|
||||
} else if (b && b.clientWidth) {
|
||||
d.w = b.clientWidth;
|
||||
d.h = b.clientHeight;
|
||||
}
|
||||
return d;
|
||||
},
|
||||
|
||||
/** @id MochiKit.Style.getViewportPosition */
|
||||
getViewportPosition: function () {
|
||||
var c = new MochiKit.Style.Coordinates(0, 0);
|
||||
var d = MochiKit.DOM._document;
|
||||
var de = d.documentElement;
|
||||
var db = d.body;
|
||||
if (de && (de.scrollTop || de.scrollLeft)) {
|
||||
c.x = de.scrollLeft;
|
||||
c.y = de.scrollTop;
|
||||
} else if (db) {
|
||||
c.x = db.scrollLeft;
|
||||
c.y = db.scrollTop;
|
||||
}
|
||||
return c;
|
||||
},
|
||||
|
||||
__new__: function () {
|
||||
var m = MochiKit.Base;
|
||||
|
||||
var inlines = ['A','ABBR','ACRONYM','B','BASEFONT','BDO','BIG','BR',
|
||||
'CITE','CODE','DFN','EM','FONT','I','IMG','KBD','LABEL',
|
||||
'Q','S','SAMP','SMALL','SPAN','STRIKE','STRONG','SUB',
|
||||
'SUP','TEXTAREA','TT','U','VAR'];
|
||||
this._defaultDisplay = { 'TABLE': 'table',
|
||||
'THEAD': 'table-header-group',
|
||||
'TBODY': 'table-row-group',
|
||||
'TFOOT': 'table-footer-group',
|
||||
'COLGROUP': 'table-column-group',
|
||||
'COL': 'table-column',
|
||||
'TR': 'table-row',
|
||||
'TD': 'table-cell',
|
||||
'TH': 'table-cell',
|
||||
'CAPTION': 'table-caption',
|
||||
'LI': 'list-item',
|
||||
'INPUT': 'inline-block',
|
||||
'SELECT': 'inline-block' };
|
||||
// CSS 'display' support in IE6/7 is just broken...
|
||||
if (/MSIE/.test(navigator.userAgent)) {
|
||||
for (var k in this._defaultDisplay) {
|
||||
var v = this._defaultDisplay[k];
|
||||
if (v.indexOf('table') == 0) {
|
||||
this._defaultDisplay[k] = 'block';
|
||||
}
|
||||
}
|
||||
}
|
||||
for (var i = 0; i < inlines.length; i++) {
|
||||
this._defaultDisplay[inlines[i]] = 'inline';
|
||||
}
|
||||
|
||||
// Backwards compatibility aliases
|
||||
m._deprecated(this, 'elementPosition', 'MochiKit.Style.getElementPosition', '1.3', true);
|
||||
m._deprecated(this, 'elementDimensions', 'MochiKit.Style.getElementDimensions', '1.3', true);
|
||||
|
||||
this.hideElement = m.partial(this.setDisplayForElement, 'none');
|
||||
// TODO: showElement could be improved by using getDefaultDisplay.
|
||||
this.showElement = m.partial(this.setDisplayForElement, 'block');
|
||||
|
||||
m.nameFunctions(this);
|
||||
}
|
||||
});
|
||||
|
||||
MochiKit.Style.__new__();
|
||||
MochiKit.Base._exportSymbols(this, MochiKit.Style);
|
||||
167
frontend/delta/js/MochiKit/Test.js
Normal file
167
frontend/delta/js/MochiKit/Test.js
Normal file
@@ -0,0 +1,167 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
/***
|
||||
|
||||
MochiKit.Test 1.5
|
||||
|
||||
See <http://mochikit.com/> for documentation, downloads, license, etc.
|
||||
|
||||
(c) 2005 Bob Ippolito. All rights Reserved.
|
||||
|
||||
***/
|
||||
|
||||
MochiKit.Base.module(MochiKit, 'Test', '1.5', ['Base']);
|
||||
|
||||
MochiKit.Test.runTests = function (obj) {
|
||||
if (typeof(obj) == "string") {
|
||||
// TODO: Remove this temporary API change advertisement
|
||||
throw new TypeError("Automatic module import not supported, call runTests() with proper object: " + obj);
|
||||
}
|
||||
var suite = new MochiKit.Test.Suite();
|
||||
suite.run(obj);
|
||||
};
|
||||
|
||||
MochiKit.Test.Suite = function () {
|
||||
this.testIndex = 0;
|
||||
MochiKit.Base.bindMethods(this);
|
||||
};
|
||||
|
||||
MochiKit.Test.Suite.prototype = {
|
||||
run: function (obj) {
|
||||
try {
|
||||
obj(this);
|
||||
} catch (e) {
|
||||
this.traceback(e);
|
||||
}
|
||||
},
|
||||
traceback: function (e) {
|
||||
var items = MochiKit.Iter.sorted(MochiKit.Base.items(e));
|
||||
print("not ok " + this.testIndex + " - Error thrown");
|
||||
for (var i = 0; i < items.length; i++) {
|
||||
var kv = items[i];
|
||||
if (kv[0] == "stack") {
|
||||
kv[1] = kv[1].split(/\n/)[0];
|
||||
}
|
||||
this.print("# " + kv.join(": "));
|
||||
}
|
||||
},
|
||||
print: function (s) {
|
||||
print(s);
|
||||
},
|
||||
is: function (got, expected, /* optional */message) {
|
||||
var res = 1;
|
||||
var msg = null;
|
||||
try {
|
||||
res = MochiKit.Base.compare(got, expected);
|
||||
} catch (e) {
|
||||
msg = "Can not compare " + typeof(got) + ":" + typeof(expected);
|
||||
}
|
||||
if (res) {
|
||||
msg = "Expected value did not compare equal";
|
||||
}
|
||||
if (!res) {
|
||||
return this.testResult(true, message);
|
||||
}
|
||||
return this.testResult(false, message,
|
||||
[[msg], ["got:", got], ["expected:", expected]]);
|
||||
},
|
||||
|
||||
testResult: function (pass, msg, failures) {
|
||||
this.testIndex += 1;
|
||||
if (pass) {
|
||||
this.print("ok " + this.testIndex + " - " + msg);
|
||||
return;
|
||||
}
|
||||
this.print("not ok " + this.testIndex + " - " + msg);
|
||||
if (failures) {
|
||||
for (var i = 0; i < failures.length; i++) {
|
||||
this.print("# " + failures[i].join(" "));
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
isDeeply: function (got, expected, /* optional */message) {
|
||||
var m = MochiKit.Base;
|
||||
var res = 1;
|
||||
try {
|
||||
res = m.compare(got, expected);
|
||||
} catch (e) {
|
||||
// pass
|
||||
}
|
||||
if (res === 0) {
|
||||
return this.ok(true, message);
|
||||
}
|
||||
var gk = m.keys(got);
|
||||
var ek = m.keys(expected);
|
||||
gk.sort();
|
||||
ek.sort();
|
||||
if (m.compare(gk, ek)) {
|
||||
// differing keys
|
||||
var cmp = {};
|
||||
var i;
|
||||
for (i = 0; i < gk.length; i++) {
|
||||
cmp[gk[i]] = "got";
|
||||
}
|
||||
for (i = 0; i < ek.length; i++) {
|
||||
if (ek[i] in cmp) {
|
||||
delete cmp[ek[i]];
|
||||
} else {
|
||||
cmp[ek[i]] = "expected";
|
||||
}
|
||||
}
|
||||
var diffkeys = m.keys(cmp);
|
||||
diffkeys.sort();
|
||||
var gotkeys = [];
|
||||
var expkeys = [];
|
||||
while (diffkeys.length) {
|
||||
var k = diffkeys.shift();
|
||||
if (k in Object.prototype) {
|
||||
continue;
|
||||
}
|
||||
(cmp[k] == "got" ? gotkeys : expkeys).push(k);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
return this.testResult((!res), msg,
|
||||
(msg ? [["got:", got], ["expected:", expected]] : undefined)
|
||||
);
|
||||
},
|
||||
|
||||
ok: function (res, message) {
|
||||
return this.testResult(res, message);
|
||||
}
|
||||
};
|
||||
|
||||
MochiKit.Test.__new__ = function () {
|
||||
var m = MochiKit.Base;
|
||||
this.Suite.__export__ = false;
|
||||
m.nameFunctions(this);
|
||||
|
||||
};
|
||||
|
||||
MochiKit.Test.__new__();
|
||||
|
||||
MochiKit.Base._exportSymbols(this, MochiKit.Test);
|
||||
569
frontend/delta/js/MochiKit/Text.js
Normal file
569
frontend/delta/js/MochiKit/Text.js
Normal file
@@ -0,0 +1,569 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
/***
|
||||
|
||||
MochiKit.Text 1.5
|
||||
|
||||
See <http://mochikit.com/> for documentation, downloads, license, etc.
|
||||
|
||||
(c) 2008 Per Cederberg. All rights Reserved.
|
||||
|
||||
***/
|
||||
|
||||
MochiKit.Base.module(MochiKit, 'Text', '1.5', ['Base', 'Format']);
|
||||
|
||||
/**
|
||||
* Checks if a text string starts with the specified substring. If
|
||||
* either of the two strings is null, false will be returned.
|
||||
*
|
||||
* @param {String} substr the substring to search for
|
||||
* @param {String} str the string to search in
|
||||
*
|
||||
* @return {Boolean} true if the string starts with the substring, or
|
||||
* false otherwise
|
||||
*/
|
||||
MochiKit.Text.startsWith = function (substr, str) {
|
||||
return str != null && substr != null && str.indexOf(substr) == 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks if a text string ends with the specified substring. If
|
||||
* either of the two strings is null, false will be returned.
|
||||
*
|
||||
* @param {String} substr the substring to search for
|
||||
* @param {String} str the string to search in
|
||||
*
|
||||
* @return {Boolean} true if the string ends with the substring, or
|
||||
* false otherwise
|
||||
*/
|
||||
MochiKit.Text.endsWith = function (substr, str) {
|
||||
return str != null && substr != null &&
|
||||
str.lastIndexOf(substr) == Math.max(str.length - substr.length, 0);
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks if a text string contains the specified substring. If
|
||||
* either of the two strings is null, false will be returned.
|
||||
*
|
||||
* @param {String} substr the substring to search for
|
||||
* @param {String} str the string to search in
|
||||
*
|
||||
* @return {Boolean} true if the string contains the substring, or
|
||||
* false otherwise
|
||||
*/
|
||||
MochiKit.Text.contains = function (substr, str) {
|
||||
return str != null && substr != null && str.indexOf(substr) >= 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds a character to the left-hand side of a string until it
|
||||
* reaches the specified minimum length.
|
||||
*
|
||||
* @param {String} str the string to process
|
||||
* @param {Number} minLength the requested minimum length
|
||||
* @param {String} fillChar the padding character to add, defaults
|
||||
* to a space
|
||||
*
|
||||
* @return {String} the padded string
|
||||
*/
|
||||
MochiKit.Text.padLeft = function (str, minLength, fillChar) {
|
||||
str = str || "";
|
||||
fillChar = fillChar || " ";
|
||||
while (str.length < minLength) {
|
||||
str = fillChar + str;
|
||||
}
|
||||
return str;
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds a character to the right-hand side of a string until it
|
||||
* reaches the specified minimum length.
|
||||
*
|
||||
* @param {String} str the string to process
|
||||
* @param {Number} minLength the requested minimum length
|
||||
* @param {String} fillChar the padding character to add, defaults
|
||||
* to a space
|
||||
*
|
||||
* @return {String} the padded string
|
||||
*/
|
||||
MochiKit.Text.padRight = function (str, minLength, fillChar) {
|
||||
str = str || "";
|
||||
fillChar = fillChar || " ";
|
||||
while (str.length < minLength) {
|
||||
str += fillChar;
|
||||
}
|
||||
return str;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a truncated copy of a string. If the string is shorter
|
||||
* than the specified maximum length, the object will be returned
|
||||
* unmodified. If an optional tail string is specified, additional
|
||||
* elements will be removed in order to accomodate the tail (that
|
||||
* will be appended). This function also works on arrays.
|
||||
*
|
||||
* @param {String} str the string to truncate
|
||||
* @param {Number} maxLength the maximum length
|
||||
* @param {String} [tail] the tail to append on truncation
|
||||
*
|
||||
* @return {String} the truncated string
|
||||
*/
|
||||
MochiKit.Text.truncate = function (str, maxLength, tail) {
|
||||
if (str == null || str.length <= maxLength || maxLength < 0) {
|
||||
return str;
|
||||
} else if (tail != null) {
|
||||
str = str.slice(0, Math.max(0, maxLength - tail.length));
|
||||
if (typeof(str) == "string") {
|
||||
return str + tail;
|
||||
} else {
|
||||
return MochiKit.Base.extend(str, tail);
|
||||
}
|
||||
} else {
|
||||
return str.slice(0, maxLength);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Splits a text string using separator as the split point
|
||||
* If max is given, at most max splits are done, giving at most
|
||||
* max + 1 elements in the returned list.
|
||||
*
|
||||
* @param {String} str the string to split
|
||||
* @param {String/RegExp} [separator] the separator char or regexp to use,
|
||||
* defaults to newline
|
||||
* @param {Number} [max] the maximum number of parts to return
|
||||
* @return {Array} an array of parts of the string
|
||||
*/
|
||||
MochiKit.Text.split = function (str, separator, max) {
|
||||
if (str == null) {
|
||||
return str;
|
||||
}
|
||||
separator = separator || '\n';
|
||||
var bits = str.split(separator);
|
||||
if ((typeof(max) == "undefined") || max >= bits.length - 1) {
|
||||
return bits;
|
||||
}
|
||||
bits.splice(max, bits.length, bits.slice(max, bits.length).join(separator));
|
||||
return bits;
|
||||
};
|
||||
|
||||
/**
|
||||
* Splits a text string using separator as the split point
|
||||
* If max is given, at most max splits are done,
|
||||
* using splits from the right
|
||||
*
|
||||
* @param {String} str the string to split
|
||||
* @param {String/RegExp} [separator] the separator char or regexp to use,
|
||||
* defaults to newline
|
||||
* @param {Number} [max] the maximum number of parts to return
|
||||
* @return {Array} an array of parts of the string
|
||||
*/
|
||||
MochiKit.Text.rsplit = function (str, separator, max) {
|
||||
if (str == null) {
|
||||
return str;
|
||||
}
|
||||
separator = separator || '\n';
|
||||
var bits = str.split(separator);
|
||||
if ((typeof(max) == "undefined") || max >= bits.length - 1){
|
||||
return bits;
|
||||
}
|
||||
bits.splice(0, bits.length-max, bits.slice(0, bits.length-max).join(separator));
|
||||
return bits;
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a formatter function for the specified formatter pattern
|
||||
* and locale. The returned function takes as many arguments as the
|
||||
* formatter pattern requires. See separate documentation for
|
||||
* information about the formatter pattern syntax.
|
||||
*
|
||||
* @param {String} pattern the formatter pattern string
|
||||
* @param {Object} [locale] the locale to use, defaults to
|
||||
* LOCALE.en_US
|
||||
*
|
||||
* @return {Function} the formatter function created
|
||||
*
|
||||
* @throws FormatPatternError if the format pattern was invalid
|
||||
*/
|
||||
MochiKit.Text.formatter = function (pattern, locale) {
|
||||
if (locale == null) {
|
||||
locale = MochiKit.Format.formatLocale();
|
||||
} else if (typeof(locale) == "string") {
|
||||
locale = MochiKit.Format.formatLocale(locale);
|
||||
}
|
||||
var parts = MochiKit.Text._parsePattern(pattern);
|
||||
return function() {
|
||||
var values = MochiKit.Base.extend([], arguments);
|
||||
var res = [];
|
||||
for (var i = 0; i < parts.length; i++) {
|
||||
if (typeof(parts[i]) == "string") {
|
||||
res.push(parts[i]);
|
||||
} else {
|
||||
res.push(MochiKit.Text.formatValue(parts[i], values, locale));
|
||||
}
|
||||
}
|
||||
return res.join("");
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Formats the specified arguments according to a formatter pattern.
|
||||
* See separate documentation for information about the formatter
|
||||
* pattern syntax.
|
||||
*
|
||||
* @param {String} pattern the formatter pattern string
|
||||
* @param {Object} [...] the optional values to format
|
||||
*
|
||||
* @return {String} the formatted output string
|
||||
*
|
||||
* @throws FormatPatternError if the format pattern was invalid
|
||||
*/
|
||||
MochiKit.Text.format = function (pattern/*, ...*/) {
|
||||
var func = MochiKit.Text.formatter(pattern);
|
||||
return func.apply(this, MochiKit.Base.extend([], arguments, 1));
|
||||
};
|
||||
|
||||
/**
|
||||
* Format a value with the specified format specifier.
|
||||
*
|
||||
* @param {String/Object} spec the format specifier string or parsed
|
||||
* format specifier object
|
||||
* @param {Object} value the value to format
|
||||
* @param {Object} [locale] the locale to use, defaults to
|
||||
* LOCALE.en_US
|
||||
*
|
||||
* @return {String} the formatted output string
|
||||
*
|
||||
* @throws FormatPatternError if the format specifier was invalid
|
||||
*/
|
||||
MochiKit.Text.formatValue = function (spec, value, locale) {
|
||||
var self = MochiKit.Text;
|
||||
if (typeof(spec) === "string") {
|
||||
spec = self._parseFormatFlags(spec, 0, spec.length);
|
||||
}
|
||||
for (var i = 0; spec.path != null && i < spec.path.length; i++) {
|
||||
if (value != null) {
|
||||
value = value[spec.path[i]];
|
||||
}
|
||||
}
|
||||
if (locale == null) {
|
||||
locale = MochiKit.Format.formatLocale();
|
||||
} else if (typeof(locale) == "string") {
|
||||
locale = MochiKit.Format.formatLocale(locale);
|
||||
}
|
||||
var str = "";
|
||||
if (spec.type == "number") {
|
||||
if (value instanceof Number) {
|
||||
value = value.valueOf();
|
||||
}
|
||||
if (typeof(value) != "number" || isNaN(value)) {
|
||||
str = "";
|
||||
} else if (value === Number.POSITIVE_INFINITY) {
|
||||
str = "\u221e";
|
||||
} else if (value === Number.NEGATIVE_INFINITY) {
|
||||
str = "-\u221e";
|
||||
} else {
|
||||
var sign = (value < 0) ? "-" : spec.sign;
|
||||
value = Math.abs(value);
|
||||
if (spec.format === "%") {
|
||||
str = self._truncToPercent(value, spec.precision);
|
||||
} else if (spec.format === "d") {
|
||||
str = MochiKit.Format.roundToFixed(value, 0);
|
||||
} else if (spec.radix != 10) {
|
||||
str = Math.floor(value).toString(spec.radix);
|
||||
if (spec.format === "x") {
|
||||
str = str.toLowerCase();
|
||||
} else if (spec.format === "X") {
|
||||
str = str.toUpperCase();
|
||||
}
|
||||
} else if (spec.precision >= 0) {
|
||||
str = MochiKit.Format.roundToFixed(value, spec.precision);
|
||||
} else {
|
||||
str = value.toString();
|
||||
}
|
||||
if (spec.padding === "0" && spec.format === "%") {
|
||||
str = self.padLeft(str, spec.width - sign.length - 1, "0");
|
||||
} else if (spec.padding == "0") {
|
||||
str = self.padLeft(str, spec.width - sign.length, "0");
|
||||
}
|
||||
str = self._localizeNumber(str, locale, spec.group);
|
||||
str = sign + str;
|
||||
}
|
||||
if (str !== "" && spec.format === "%") {
|
||||
str = str + locale.percent;
|
||||
}
|
||||
} else {
|
||||
if (spec.format == "r") {
|
||||
str = MochiKit.Base.repr(value);
|
||||
} else {
|
||||
str = (value == null) ? "" : value.toString();
|
||||
}
|
||||
str = self.truncate(str, spec.precision);
|
||||
}
|
||||
if (spec.align == "<") {
|
||||
str = self.padRight(str, spec.width);
|
||||
} else {
|
||||
str = self.padLeft(str, spec.width);
|
||||
}
|
||||
return str;
|
||||
};
|
||||
|
||||
/**
|
||||
* Adjust an already formatted numeric string for locale-specific
|
||||
* grouping and decimal separators. The grouping is optional and
|
||||
* will attempt to keep the number string length intact by removing
|
||||
* padded zeros (if possible).
|
||||
*
|
||||
* @param {String} num the formatted number string
|
||||
* @param {Object} locale the formatting locale to use
|
||||
* @param {Boolean} group the grouping flag
|
||||
*
|
||||
* @return {String} the localized number string
|
||||
*/
|
||||
MochiKit.Text._localizeNumber = function (num, locale, group) {
|
||||
var parts = num.split(/\./);
|
||||
var whole = parts[0];
|
||||
var frac = (parts.length == 1) ? "" : parts[1];
|
||||
var res = (frac.length > 0) ? locale.decimal : "";
|
||||
while (group && frac.length > 3) {
|
||||
res = res + frac.substring(0, 3) + locale.separator;
|
||||
frac = frac.substring(3);
|
||||
if (whole.charAt(0) == "0") {
|
||||
whole = whole.substring(1);
|
||||
}
|
||||
}
|
||||
if (frac.length > 0) {
|
||||
res = res + frac;
|
||||
}
|
||||
while (group && whole.length > 3) {
|
||||
var pos = whole.length - 3;
|
||||
res = locale.separator + whole.substring(pos) + res;
|
||||
whole = whole.substring((whole.charAt(0) == "0") ? 1 : 0, pos);
|
||||
}
|
||||
return whole + res;
|
||||
};
|
||||
|
||||
/**
|
||||
* Parses a format pattern and returns an array of constant strings
|
||||
* and format info objects.
|
||||
*
|
||||
* @param {String} pattern the format pattern to analyze
|
||||
*
|
||||
* @return {Array} an array of strings and format info objects
|
||||
*
|
||||
* @throws FormatPatternError if the format pattern was invalid
|
||||
*/
|
||||
MochiKit.Text._parsePattern = function (pattern) {
|
||||
var self = MochiKit.Text;
|
||||
var parts = [];
|
||||
var re = /{[^{}]*}|{{?|}}?/g;
|
||||
var lastPos = re.lastIndex = 0;
|
||||
var m;
|
||||
while ((m = re.exec(pattern)) != null) {
|
||||
if (lastPos < m.index) {
|
||||
parts.push(pattern.substring(lastPos, m.index))
|
||||
}
|
||||
var str = m[0];
|
||||
lastPos = m.index + str.length;
|
||||
if (self.startsWith("{", str) && self.endsWith("}", str)) {
|
||||
parts.push(self._parseFormat(pattern, m.index + 1, lastPos - 1));
|
||||
} else if (self.startsWith("{{", str) || self.startsWith("}}", str)) {
|
||||
parts.push(str.substring(1));
|
||||
} else if (self.startsWith("{", str)) {
|
||||
var msg = "unescaped { char, should be escaped as {{";
|
||||
throw new self.FormatPatternError(pattern, m.index, msg);
|
||||
} else if (self.startsWith("}", str)) {
|
||||
var msg = "unescaped } char, should be escaped as }}";
|
||||
throw new self.FormatPatternError(pattern, m.index, msg);
|
||||
}
|
||||
}
|
||||
if (lastPos < pattern.length) {
|
||||
parts.push(pattern.substring(lastPos));
|
||||
}
|
||||
return parts;
|
||||
};
|
||||
|
||||
/**
|
||||
* Parses a format instruction and returns a format info object.
|
||||
*
|
||||
* @param {String} pattern the format pattern string
|
||||
* @param {Number} startPos the first index of the format instruction
|
||||
* @param {Number} endPos the last index of the format instruction
|
||||
*
|
||||
* @return {Object} the format info object
|
||||
*
|
||||
* @throws FormatPatternError if the format pattern was invalid
|
||||
*/
|
||||
MochiKit.Text._parseFormat = function (pattern, startPos, endPos) {
|
||||
var self = MochiKit.Text;
|
||||
var text = pattern.substring(startPos, endPos);
|
||||
var parts = self.split(text, ":", 1);
|
||||
var path = parts[0];
|
||||
var flagsPos = startPos + path.length + ((parts.length == 1) ? 0 : 1);
|
||||
var info = self._parseFormatFlags(pattern, flagsPos, endPos);
|
||||
info.path = (path == "") ? [] : path.split(".");
|
||||
for (var i = 0; i < info.path.length; i++) {
|
||||
var v = info.path[i];
|
||||
// TODO: replace with MochiKit.Format.strip?
|
||||
v = v.replace(/^\s+/, "").replace(/\s+$/, "");
|
||||
if (v == "" && info.path.length == 1) {
|
||||
v = 0;
|
||||
} else if (v == "") {
|
||||
var msg = "format value path contains blanks";
|
||||
throw new self.FormatPatternError(pattern, startPos, msg);
|
||||
} else if (/^\d+$/.test(v)) {
|
||||
v = parseInt(v, 10);
|
||||
}
|
||||
info.path[i] = v;
|
||||
}
|
||||
if (info.path.length <= 0 || typeof(info.path[0]) != "number") {
|
||||
info.path.unshift(0);
|
||||
}
|
||||
return info;
|
||||
};
|
||||
|
||||
/**
|
||||
* Parses a string with format flags and returns a format info object.
|
||||
*
|
||||
* @param {String} pattern the format pattern string
|
||||
* @param {Number} startPos the first index of the format instruction
|
||||
* @param {Number} endPos the last index of the format instruction
|
||||
*
|
||||
* @return {Object} the format info object
|
||||
*
|
||||
* @throws FormatPatternError if the format pattern was invalid
|
||||
*/
|
||||
MochiKit.Text._parseFormatFlags = function (pattern, startPos, endPos) {
|
||||
var update = MochiKit.Base.update;
|
||||
var info = { type: "string", format: "s", width: 0, precision: -1,
|
||||
align: ">", sign: "", padding: " ", group: false };
|
||||
// TODO: replace with MochiKit.Format.rstrip?
|
||||
var text = pattern.substring(startPos, endPos).replace(/\s+$/, "");
|
||||
var m = /^([<>+ 0,-]+)?(\d+)?(\.\d*)?([srbdoxXf%])?(.*)$/.exec(text);
|
||||
var flags = m[1];
|
||||
var width = m[2];
|
||||
var precision = m[3];
|
||||
var type = m[4];
|
||||
var unmatched = m[5];
|
||||
for (var i = 0; flags && i < flags.length; i++) {
|
||||
var chr = flags.charAt(i);
|
||||
if (chr == "<" || chr == ">") {
|
||||
info.align = chr;
|
||||
} else if (chr == "+" || chr == "-" || chr == " ") {
|
||||
info.sign = (chr == "-") ? "" : chr;
|
||||
} else if (chr == "0") {
|
||||
info.padding = chr;
|
||||
} else if (chr == ",") {
|
||||
info.group = true;
|
||||
}
|
||||
}
|
||||
if (width) {
|
||||
info.width = parseInt(width, 10);
|
||||
}
|
||||
if (precision && precision.length > 1) {
|
||||
info.precision = parseInt(precision.substring(1), 10);
|
||||
}
|
||||
if (type == "s" || type == "r") {
|
||||
info.format = type;
|
||||
} else if (type == "b") {
|
||||
update(info, { type: "number", format: type, radix: 2 });
|
||||
} else if (type == "o") {
|
||||
update(info, { type: "number", format: type, radix: 8 });
|
||||
} else if (type == "x" || type == "X") {
|
||||
update(info, { type: "number", format: type, radix: 16 });
|
||||
} else if (type == "d" || type == "f" || type == "%") {
|
||||
update(info, { type: "number", format: type, radix: 10 });
|
||||
}
|
||||
if (unmatched) {
|
||||
var msg = "unsupported format flag: " + unmatched.charAt(0);
|
||||
throw new MochiKit.Text.FormatPatternError(pattern, startPos, msg);
|
||||
}
|
||||
return info;
|
||||
};
|
||||
|
||||
/**
|
||||
* Formats a value as a percentage. This method avoids multiplication
|
||||
* by 100 since it leads to weird numeric rounding errors. Instead it
|
||||
* just move the decimal separator in the text string. It is ugly,
|
||||
* but works...
|
||||
*
|
||||
* @param {Number} value the value to format
|
||||
* @param {Number} precision the number of precision digits
|
||||
*/
|
||||
MochiKit.Text._truncToPercent = function (value, precision) {
|
||||
// TODO: This can be simplified by using MochiKit.Format._shiftNumber
|
||||
// as roundToFixed does.
|
||||
var str;
|
||||
if (precision >= 0) {
|
||||
str = MochiKit.Format.roundToFixed(value, precision + 2);
|
||||
} else {
|
||||
str = (value == null) ? "0" : value.toString();
|
||||
}
|
||||
var arr = MochiKit.Text.split(str, ".", 2);
|
||||
var frac = MochiKit.Text.padRight(arr[1], 2, "0");
|
||||
var whole = arr[0] + frac.substring(0, 2);
|
||||
frac = frac.substring(2);
|
||||
while (/^0[0-9]/.test(whole)) {
|
||||
whole = whole.substring(1);
|
||||
}
|
||||
return (frac.length <= 0) ? whole : whole + "." + frac;
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new format pattern error.
|
||||
*
|
||||
* @param {String} pattern the format pattern string
|
||||
* @param {Number} pos the position of the error
|
||||
* @param {String} message the error message text
|
||||
*
|
||||
* @return {Error} the format pattern error
|
||||
*
|
||||
* @class The format pattern error class. This error is thrown when
|
||||
* a syntax error is encountered inside a format string.
|
||||
* @property {String} pattern The format pattern string.
|
||||
* @property {Number} pos The position of the error.
|
||||
* @property {String} message The error message text.
|
||||
* @extends MochiKit.Base.NamedError
|
||||
*/
|
||||
MochiKit.Text.FormatPatternError = function (pattern, pos, message) {
|
||||
this.pattern = pattern;
|
||||
this.pos = pos;
|
||||
this.message = message;
|
||||
};
|
||||
|
||||
MochiKit.Text.FormatPatternError.prototype = new MochiKit.Base.NamedError("MochiKit.Text.FormatPatternError");
|
||||
MochiKit.Text.FormatPatternError.constructor = MochiKit.Text.FormatPatternError;
|
||||
|
||||
//
|
||||
//XXX: Internet Explorer export fix
|
||||
//
|
||||
if (MochiKit.__export__) {
|
||||
formatter = MochiKit.Text.formatter;
|
||||
format = MochiKit.Text.format;
|
||||
formatValue = MochiKit.Text.formatValue;
|
||||
}
|
||||
|
||||
|
||||
MochiKit.Base.nameFunctions(MochiKit.Text);
|
||||
MochiKit.Base._exportSymbols(this, MochiKit.Text);
|
||||
1999
frontend/delta/js/MochiKit/Visual.js
Normal file
1999
frontend/delta/js/MochiKit/Visual.js
Normal file
File diff suppressed because it is too large
Load Diff
11491
frontend/delta/js/React/react-0.4.1.js
Normal file
11491
frontend/delta/js/React/react-0.4.1.js
Normal file
File diff suppressed because it is too large
Load Diff
62
frontend/delta/js/main.js
Normal file
62
frontend/delta/js/main.js
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
function _pm_logEvent(anEvent) {
|
||||
// console.log("####", anEvent);
|
||||
|
||||
anEvent.preventDefault();
|
||||
}
|
||||
|
||||
function handleGenericDeferredError(anError) {
|
||||
var result;
|
||||
|
||||
if (anError instanceof MochiKit.Async.CancelledError) {
|
||||
result = anError;
|
||||
} else {
|
||||
MochiKit.Logging.logError("## MainController - GENERIC ERROR" + "\n" + "==>> " + anError + " <<==\n" + anError.stack);
|
||||
//console.log(anError);
|
||||
result = new MochiKit.Async.CancelledError(anError);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
Clipperz.PM.RunTime = {};
|
||||
function run() {
|
||||
var parameters = {};
|
||||
|
||||
Clipperz.PM.Strings.Languages.initSetup();
|
||||
|
||||
|
||||
if ((window.location.search.indexOf('registration') != -1) || (window.location.hash.indexOf('registration') != -1)) {
|
||||
parameters['shouldShowRegistrationForm'] = true;
|
||||
} else {
|
||||
parameters['shouldShowRegistrationForm'] = false;
|
||||
}
|
||||
|
||||
Clipperz.PM.RunTime.mainController = new Clipperz.PM.UI.MainController();
|
||||
Clipperz.PM.RunTime.mainController.run(parameters);
|
||||
}
|
||||
|
||||
MochiKit.DOM.addLoadEvent(run);
|
||||
9
frontend/delta/less/web.less
Normal file
9
frontend/delta/less/web.less
Normal file
@@ -0,0 +1,9 @@
|
||||
@import "web/fonts";
|
||||
@import "web/overlay";
|
||||
@import "web/behavior";
|
||||
@import "web/style";
|
||||
@import "web/480";
|
||||
@import "web/768";
|
||||
@import "web/992";
|
||||
|
||||
@import "web/add2home";
|
||||
11
frontend/delta/less/web/480.less
Normal file
11
frontend/delta/less/web/480.less
Normal file
@@ -0,0 +1,11 @@
|
||||
@media only screen and (min-width: 480px) {
|
||||
.loginForm {
|
||||
font-size: 1.2em;
|
||||
|
||||
input {
|
||||
}
|
||||
button {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user