First release of /delta version

This commit is contained in:
Giulio Cesare Solaroli
2013-08-30 23:23:42 +02:00
parent bde3c7b985
commit 20bea94ab6
131 changed files with 59632 additions and 79 deletions
+707
View 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
View 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, "&lt;");
result = result.replace(/>/g, "&gt;");
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,"&lt;");
result = result.replace(/>/img,"&gt;");
} 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
);
File diff suppressed because it is too large Load Diff
+344
View 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
View 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
View 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")
};
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -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"
});
//#############################################################################
@@ -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
]
@@ -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"
});
@@ -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")
};
@@ -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
View 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
View 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
View 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
View 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
View 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
View 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"
});
@@ -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"
});
@@ -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
View 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;
@@ -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
View 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
View 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]
});
//*****************************************************************************
File diff suppressed because it is too large Load Diff
@@ -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"
});
@@ -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"
});
@@ -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"
});
@@ -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"
});
@@ -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;
}
//#############################################################################
@@ -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"
});
@@ -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"
});
@@ -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"
});
@@ -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;
};
@@ -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"
});
@@ -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
View 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
View 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
View 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
View 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"
});
@@ -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"
});
@@ -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"
});
@@ -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
View 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"
}
@@ -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"
}
File diff suppressed because it is too large Load Diff
+189
View 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;
@@ -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")
*/
])
]);
}
//=========================================================================
});
@@ -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()),
]);
}
//=========================================================================
});
@@ -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()});
}
});
@@ -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()});
}
});
@@ -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"
});
@@ -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();
}
}
}
//=========================================================================
});
@@ -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();
};
//-----------------------------------------------------------------------------
@@ -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
View 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
View 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
View 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
View 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
View 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
View 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, &gt; &lt;.
*/
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
View 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
};