summaryrefslogtreecommitdiff
path: root/frontend/beta/js/Clipperz
authorGiulio Cesare Solaroli <giulio.cesare@clipperz.com>2011-10-02 23:56:18 (UTC)
committer Giulio Cesare Solaroli <giulio.cesare@clipperz.com>2011-10-02 23:56:18 (UTC)
commitef68436ac04da078ffdcacd7e1f785473a303d45 (patch) (side-by-side diff)
treec403752d66a2c4775f00affd4fa8431b29c5b68c /frontend/beta/js/Clipperz
parent597ecfbc0249d83e1b856cbd558340c01237a360 (diff)
downloadclipperz-ef68436ac04da078ffdcacd7e1f785473a303d45.zip
clipperz-ef68436ac04da078ffdcacd7e1f785473a303d45.tar.gz
clipperz-ef68436ac04da078ffdcacd7e1f785473a303d45.tar.bz2
First version of the newly restructured repository
Diffstat (limited to 'frontend/beta/js/Clipperz') (more/less context) (ignore whitespace changes)
-rw-r--r--frontend/beta/js/Clipperz/Base.js308
-rw-r--r--frontend/beta/js/Clipperz/ByteArray.js1426
-rw-r--r--frontend/beta/js/Clipperz/CSVProcessor.js348
-rw-r--r--frontend/beta/js/Clipperz/Crypto/AES.js836
-rw-r--r--frontend/beta/js/Clipperz/Crypto/Base.js1852
-rw-r--r--frontend/beta/js/Clipperz/Crypto/BigInt.js1760
-rw-r--r--frontend/beta/js/Clipperz/Crypto/BigInt_scoped.js1649
-rw-r--r--frontend/beta/js/Clipperz/Crypto/ECC.js960
-rw-r--r--frontend/beta/js/Clipperz/Crypto/ECC/BinaryField/Curve.js461
-rw-r--r--frontend/beta/js/Clipperz/Crypto/ECC/BinaryField/FiniteField.js526
-rw-r--r--frontend/beta/js/Clipperz/Crypto/ECC/BinaryField/Point.js67
-rw-r--r--frontend/beta/js/Clipperz/Crypto/ECC/BinaryField/Value.js377
-rw-r--r--frontend/beta/js/Clipperz/Crypto/PRNG.js854
-rw-r--r--frontend/beta/js/Clipperz/Crypto/RSA.js151
-rw-r--r--frontend/beta/js/Clipperz/Crypto/SHA.js296
-rw-r--r--frontend/beta/js/Clipperz/Crypto/SRP.js331
-rw-r--r--frontend/beta/js/Clipperz/DOM.js131
-rw-r--r--frontend/beta/js/Clipperz/Date.js305
-rw-r--r--frontend/beta/js/Clipperz/KeePassExportProcessor.js251
-rw-r--r--frontend/beta/js/Clipperz/NotificationCenter.js325
-rw-r--r--frontend/beta/js/Clipperz/PM/BookmarkletProcessor.js288
-rw-r--r--frontend/beta/js/Clipperz/PM/Components/BaseComponent.js124
-rw-r--r--frontend/beta/js/Clipperz/PM/Components/Compact/CompactHeader.js86
-rw-r--r--frontend/beta/js/Clipperz/PM/Components/Compact/CompactInterface.js312
-rw-r--r--frontend/beta/js/Clipperz/PM/Components/Compact/LoginForm.js189
-rw-r--r--frontend/beta/js/Clipperz/PM/Components/Import/CSVImport/CSVImportColumns.js174
-rw-r--r--frontend/beta/js/Clipperz/PM/Components/Import/CSVImport/CSVImportFields.js247
-rw-r--r--frontend/beta/js/Clipperz/PM/Components/Import/CSVImport/CSVImportHeader.js240
-rw-r--r--frontend/beta/js/Clipperz/PM/Components/Import/CSVImport/CSVImportNotes.js212
-rw-r--r--frontend/beta/js/Clipperz/PM/Components/Import/CSVImport/CSVImportTitle.js189
-rw-r--r--frontend/beta/js/Clipperz/PM/Components/Import/CSVImportComponent.js548
-rw-r--r--frontend/beta/js/Clipperz/PM/Components/Import/ClipperzImportComponent.js212
-rw-r--r--frontend/beta/js/Clipperz/PM/Components/Import/ExcelImportComponent.js134
-rw-r--r--frontend/beta/js/Clipperz/PM/Components/Import/GenericImportComponent.js523
-rw-r--r--frontend/beta/js/Clipperz/PM/Components/Import/KeePassImportComponent.js450
-rw-r--r--frontend/beta/js/Clipperz/PM/Components/Import/MainComponent.js332
-rw-r--r--frontend/beta/js/Clipperz/PM/Components/Import/PasswordPlusImportComponent.js315
-rw-r--r--frontend/beta/js/Clipperz/PM/Components/Import/RoboFormImportComponent.js392
-rw-r--r--frontend/beta/js/Clipperz/PM/Components/MessageBox.js224
-rw-r--r--frontend/beta/js/Clipperz/PM/Components/OTP/MainComponent.js490
-rw-r--r--frontend/beta/js/Clipperz/PM/Components/Panels/AccountPanel.js784
-rw-r--r--frontend/beta/js/Clipperz/PM/Components/Panels/BasePanel.js96
-rw-r--r--frontend/beta/js/Clipperz/PM/Components/Panels/ContactsPanel.js105
-rw-r--r--frontend/beta/js/Clipperz/PM/Components/Panels/DataPanel.js486
-rw-r--r--frontend/beta/js/Clipperz/PM/Components/Panels/LoginPanel.js1114
-rw-r--r--frontend/beta/js/Clipperz/PM/Components/Panels/LogoutPanel.js73
-rw-r--r--frontend/beta/js/Clipperz/PM/Components/Panels/MainPanel.js906
-rw-r--r--frontend/beta/js/Clipperz/PM/Components/Panels/ToolsPanel.js305
-rw-r--r--frontend/beta/js/Clipperz/PM/Components/PasswordEntropyDisplay.js118
-rw-r--r--frontend/beta/js/Clipperz/PM/Components/PasswordGenerator.js285
-rw-r--r--frontend/beta/js/Clipperz/PM/Components/Printing/Footer.js28
-rw-r--r--frontend/beta/js/Clipperz/PM/Components/Printing/Header.js28
-rw-r--r--frontend/beta/js/Clipperz/PM/Components/Printing/Record.js95
-rw-r--r--frontend/beta/js/Clipperz/PM/Components/RecordDetail/AbstractComponent.js105
-rw-r--r--frontend/beta/js/Clipperz/PM/Components/RecordDetail/AbstractFieldSubComponent.js77
-rw-r--r--frontend/beta/js/Clipperz/PM/Components/RecordDetail/CreationWizard.js317
-rw-r--r--frontend/beta/js/Clipperz/PM/Components/RecordDetail/DirectLoginBindingComponent.js174
-rw-r--r--frontend/beta/js/Clipperz/PM/Components/RecordDetail/DirectLoginComponent.js362
-rw-r--r--frontend/beta/js/Clipperz/PM/Components/RecordDetail/DirectLoginValueComponent.js257
-rw-r--r--frontend/beta/js/Clipperz/PM/Components/RecordDetail/DirectLoginsComponent.js199
-rw-r--r--frontend/beta/js/Clipperz/PM/Components/RecordDetail/FieldButtonComponent.js117
-rw-r--r--frontend/beta/js/Clipperz/PM/Components/RecordDetail/FieldComponent.js189
-rw-r--r--frontend/beta/js/Clipperz/PM/Components/RecordDetail/FieldDragHandler.js59
-rw-r--r--frontend/beta/js/Clipperz/PM/Components/RecordDetail/FieldLabelComponent.js141
-rw-r--r--frontend/beta/js/Clipperz/PM/Components/RecordDetail/FieldTypeComponent.js157
-rw-r--r--frontend/beta/js/Clipperz/PM/Components/RecordDetail/FieldValueComponent.js275
-rw-r--r--frontend/beta/js/Clipperz/PM/Components/RecordDetail/HeaderComponent.js165
-rw-r--r--frontend/beta/js/Clipperz/PM/Components/RecordDetail/MainComponent.js758
-rw-r--r--frontend/beta/js/Clipperz/PM/Components/RecordDetail/NotesComponent.js240
-rw-r--r--frontend/beta/js/Clipperz/PM/Components/RecordDetail/TitleComponent.js137
-rw-r--r--frontend/beta/js/Clipperz/PM/Components/TabPanel/TabPanelController.js158
-rw-r--r--frontend/beta/js/Clipperz/PM/Components/TextFormField.js310
-rw-r--r--frontend/beta/js/Clipperz/PM/Connection.js584
-rw-r--r--frontend/beta/js/Clipperz/PM/Crypto.js503
-rw-r--r--frontend/beta/js/Clipperz/PM/DataModel/DirectLogin.js536
-rw-r--r--frontend/beta/js/Clipperz/PM/DataModel/DirectLoginBinding.js113
-rw-r--r--frontend/beta/js/Clipperz/PM/DataModel/DirectLoginInput.js229
-rw-r--r--frontend/beta/js/Clipperz/PM/DataModel/DirectLoginReference.js192
-rw-r--r--frontend/beta/js/Clipperz/PM/DataModel/Header.js751
-rw-r--r--frontend/beta/js/Clipperz/PM/DataModel/OneTimePassword.js333
-rw-r--r--frontend/beta/js/Clipperz/PM/DataModel/OneTimePasswordManager.js280
-rw-r--r--frontend/beta/js/Clipperz/PM/DataModel/Record.js759
-rw-r--r--frontend/beta/js/Clipperz/PM/DataModel/RecordField.js220
-rw-r--r--frontend/beta/js/Clipperz/PM/DataModel/RecordVersion.js535
-rw-r--r--frontend/beta/js/Clipperz/PM/DataModel/Statistics.js133
-rw-r--r--frontend/beta/js/Clipperz/PM/DataModel/User.js904
-rw-r--r--frontend/beta/js/Clipperz/PM/DataModel/UserPreferences.js197
-rw-r--r--frontend/beta/js/Clipperz/PM/Date.js193
-rw-r--r--frontend/beta/js/Clipperz/PM/Main.js588
-rw-r--r--frontend/beta/js/Clipperz/PM/Proxy.js173
-rwxr-xr-xfrontend/beta/js/Clipperz/PM/Proxy/Proxy.JSON.js100
-rw-r--r--frontend/beta/js/Clipperz/PM/Proxy/Proxy.Offline.DataStore.js804
-rw-r--r--frontend/beta/js/Clipperz/PM/Proxy/Proxy.Offline.js73
-rwxr-xr-xfrontend/beta/js/Clipperz/PM/Proxy/Proxy.PHP.js259
-rw-r--r--frontend/beta/js/Clipperz/PM/Proxy/Proxy.Test.js94
-rw-r--r--frontend/beta/js/Clipperz/PM/Strings.js231
-rw-r--r--frontend/beta/js/Clipperz/PM/Strings/MessagePanelConfigurations.js389
-rw-r--r--frontend/beta/js/Clipperz/PM/Strings/Strings_de-DE.js352
-rw-r--r--frontend/beta/js/Clipperz/PM/Strings/Strings_el-GR.js701
-rw-r--r--frontend/beta/js/Clipperz/PM/Strings/Strings_en-CA.js43
-rw-r--r--frontend/beta/js/Clipperz/PM/Strings/Strings_en-GB.js43
-rw-r--r--frontend/beta/js/Clipperz/PM/Strings/Strings_en-US.js1259
-rw-r--r--frontend/beta/js/Clipperz/PM/Strings/Strings_es-ES.js480
-rw-r--r--frontend/beta/js/Clipperz/PM/Strings/Strings_fr-FR.js362
-rw-r--r--frontend/beta/js/Clipperz/PM/Strings/Strings_he-IL.js40
-rw-r--r--frontend/beta/js/Clipperz/PM/Strings/Strings_it-IT.js694
-rw-r--r--frontend/beta/js/Clipperz/PM/Strings/Strings_ja-JP.js808
-rw-r--r--frontend/beta/js/Clipperz/PM/Strings/Strings_pt-BR.js478
-rw-r--r--frontend/beta/js/Clipperz/PM/Strings/Strings_pt-PT.js42
-rw-r--r--frontend/beta/js/Clipperz/PM/Strings/Strings_ru-RU.js440
-rw-r--r--frontend/beta/js/Clipperz/PM/Strings/Strings_zh-CN.js477
-rw-r--r--frontend/beta/js/Clipperz/PM/Toll.js193
-rw-r--r--frontend/beta/js/Clipperz/Profile.js485
-rw-r--r--frontend/beta/js/Clipperz/Set.js167
-rw-r--r--frontend/beta/js/Clipperz/Signal.js71
-rw-r--r--frontend/beta/js/Clipperz/Style.js73
-rw-r--r--frontend/beta/js/Clipperz/YUI/Collapser.js73
-rw-r--r--frontend/beta/js/Clipperz/YUI/DomHelper.js465
-rw-r--r--frontend/beta/js/Clipperz/YUI/DomQuery.js710
-rw-r--r--frontend/beta/js/Clipperz/YUI/Drawer.js238
-rw-r--r--frontend/beta/js/Clipperz/YUI/IBLayoutManager.js114
-rw-r--r--frontend/beta/js/Clipperz/YUI/IBLayoutRegion.js249
-rw-r--r--frontend/beta/js/Clipperz/YUI/MessageBox.js265
123 files changed, 46010 insertions, 0 deletions
diff --git a/frontend/beta/js/Clipperz/Base.js b/frontend/beta/js/Clipperz/Base.js
new file mode 100644
index 0000000..5bd972b
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/Base.js
@@ -0,0 +1,308 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
+if (typeof(Clipperz.Base) == 'undefined') { Clipperz.Base = {}; }
+
+Clipperz.Base.VERSION = "0.1";
+Clipperz.Base.NAME = "Clipperz.Base";
+
+MochiKit.Base.update(Clipperz.Base, {
+
+ //-------------------------------------------------------------------------
+
+ '__repr__': function () {
+ return "[" + this.NAME + " " + this.VERSION + "]";
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'toString': function () {
+ return this.__repr__();
+ },
+
+ //-------------------------------------------------------------------------
+
+ '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 {
+// jslog.error("Trying to remove an object not present in the array");
+ // TODO: raise an exception
+ }
+ },
+
+ '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;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'evalJSON': function(aString) {
+/*
+ var result;
+
+ // check for XSS injection
+ if (/<script>/.test(aString)) {
+ throw "error";
+ }
+
+ if (/<iframe>/.test(aString)) {
+ throw "error";
+ }
+
+ result = MochiKit.Base.evalJSON(aString);
+
+ return result;
+*/
+
+// return MochiKit.Base.evalJSON(aString);
+ return JSON2.parse(aString);
+ },
+
+ 'serializeJSON': function(anObject) {
+// return MochiKit.Base.serializeJSON(anObject);
+ return JSON2.stringify(anObject);
+ },
+
+ //-------------------------------------------------------------------------
+
+ '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;
+ },
+
+ //-------------------------------------------------------------------------
+
+ '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")
+ },
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+
+});
+
+
+
+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;
+
+//MochiKit.Logging.logDebug(">>> comparator");
+//MochiKit.Logging.logDebug("- a: " + Clipperz.Base.serializeJSON(a));
+//MochiKit.Logging.logDebug("- b: " + Clipperz.Base.serializeJSON(a));
+ aKeys = MochiKit.Base.keys(a).sort();
+ bKeys = MochiKit.Base.keys(b).sort();
+
+ result = MochiKit.Base.compare(aKeys, bKeys);
+//if (result != 0) {
+// MochiKit.Logging.logDebug("- comparator 'keys':");
+// MochiKit.Logging.logDebug("- comparator aKeys: " + Clipperz.Base.serializeJSON(aKeys));
+// MochiKit.Logging.logDebug("- comparator bKeys: " + Clipperz.Base.serializeJSON(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]]);
+//if (result != 0) {
+// MochiKit.Logging.logDebug("- comparator 'values':");
+// MochiKit.Logging.logDebug("- comparator a[aKeys[i]]: " + Clipperz.Base.serializeJSON(a[aKeys[i]]));
+// MochiKit.Logging.logDebug("- comparator b[bKeys[i]]: " + Clipperz.Base.serializeJSON(b[bKeys[i]]));
+//}
+ }
+ }
+
+//MochiKit.Logging.logDebug("<<< comparator - result: " + result);
+ return result;
+ },
+ true
+);
diff --git a/frontend/beta/js/Clipperz/ByteArray.js b/frontend/beta/js/Clipperz/ByteArray.js
new file mode 100644
index 0000000..2275087
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/ByteArray.js
@@ -0,0 +1,1426 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
+
+//=============================================================================
+
+Clipperz.ByteArray_abstract = function(args) {
+ return this;
+}
+
+Clipperz.ByteArray_abstract.prototype = MochiKit.Base.update(null, {
+
+ //-------------------------------------------------------------------------
+
+ 'toString': function() {
+ return "Clipperz.ByteArray_abstract";
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'equals': function(aValue) {
+ return (this.compare(aValue) == 0);
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'compare': function(aValue) {
+ var result;
+ var i;
+
+ result = MochiKit.Base.compare(this.length(), aValue.length());
+ i = this.length();
+
+ while ((result == 0) && (i>0)) {
+ i--;
+ result = MochiKit.Base.compare(this.byteAtIndex(i), aValue.byteAtIndex(i));
+ }
+
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'clone': function() {
+ throw Clipperz.Base.exception.AbstractMethod;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'newInstance': function() {
+ throw Clipperz.Base.exception.AbstractMethod;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'reset': function() {
+ throw Clipperz.Base.exception.AbstractMethod;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'length': function() {
+ throw Clipperz.Base.exception.AbstractMethod;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'checkValue': function(aValue) {
+ if ((aValue & 0xff) != aValue) {
+ MochiKit.Logging.logError("Clipperz.ByteArray.appendByte: the provided value (0x" + aValue.toString(16) + ") is not a byte value.");
+ throw Clipperz.ByteArray.exception.InvalidValue;
+ }
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'xorMergeWithBlock': function(aBlock, anAllignment, paddingMode) {
+ var result;
+ var a, b;
+ var aLength;
+ var bLength;
+ var i, c;
+
+ if (this.length() > aBlock.length()) {
+ a = this;
+ b = aBlock;
+ } else {
+ a = aBlock;
+ b = this;
+ }
+
+ aLength = a.length();
+ bLength = b.length();
+
+ if (aLength != bLength) {
+ if (paddingMode == 'truncate') {
+ if (anAllignment == 'left') {
+ a = a.split(0, bLength);
+ } else {
+ a = a.split(aLength - bLength);
+ }
+ } else {
+ var ii, cc;
+ var padding;
+
+// padding = new Clipperz.ByteArray();
+ padding = this.newInstance();
+ cc = aLength - bLength;
+ for (ii=0; ii<cc; ii++) {
+ padding.appendByte(0);
+ }
+
+ if (anAllignment == 'left') {
+ b = b.appendBlock(padding);
+ } else {
+ b = padding.appendBlock(b);
+ }
+ }
+ }
+
+
+// result = new Clipperz.ByteArray();
+ result = this.newInstance();
+ c = a.length();
+ for (i=0; i<c; i++) {
+ result.appendByte(a.byteAtIndex(i) ^ b.byteAtIndex(i));
+ }
+
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+/*
+ 'shiftLeft': function(aNumberOfBitsToShift) {
+ var result;
+
+ result = this.clone(); // ???????????
+
+ return result;
+ },
+*/
+ //-------------------------------------------------------------------------
+
+ 'appendBlock': function(aBlock) {
+ throw Clipperz.Base.exception.AbstractMethod;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'appendByte': function(aValue) {
+ throw Clipperz.Base.exception.AbstractMethod;
+ },
+
+ 'appendBytes': function(args) {
+ var values;
+ var i,c;
+
+ if (args.constructor == Array) {
+ values = args;
+ } else {
+ values = arguments;
+ }
+
+ c = values.length;
+ for (i=0; i<c; i++) {
+ this.appendByte(values[i]);
+ }
+
+ return this;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'appendWord': function(aValue, isLittleEndian) {
+ var result;
+ var processAsLittleEndian;
+
+ processAsLittleEndian = isLittleEndian === true ? true : false;
+
+ if (processAsLittleEndian) {
+ result = this.appendBytes( (aValue) & 0xff, (aValue >> 8) & 0xff, (aValue >> 16) & 0xff, (aValue >> 24) & 0xff ); // little endian
+ } else {
+ result = this.appendBytes( (aValue >> 24) & 0xff, (aValue >> 16) & 0xff, (aValue >> 8) & 0xff, (aValue) & 0xff ); // big endian - DEFAULT
+ }
+
+ return result;
+ },
+
+ 'appendWords': function(args) {
+ var values;
+ var i,c;
+
+ if (args.constructor == Array) {
+ values = args;
+ } else {
+ values = arguments;
+ }
+
+ c = values.length;
+ for (i=0; i<c; i++) {
+ this.appendWord(values[i], false);
+ }
+
+ return this;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'appendBigEndianWords': function(args) {
+ var values;
+ var i,c;
+
+ if (args.constructor == Array) {
+ values = args;
+ } else {
+ values = arguments;
+ }
+
+ c = values.length;
+ for (i=0; i<c; i++) {
+ this.appendWord(values[i], true);
+ }
+
+ return this;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'byteAtIndex': function(anIndex) {
+ throw Clipperz.Base.exception.AbstractMethod;
+ },
+
+ 'setByteAtIndex': function(aValue, anIndex) {
+ throw Clipperz.Base.exception.AbstractMethod;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'bitAtIndex': function(aBitPosition) {
+ var result;
+ var bytePosition;
+ var bitPositionInSelectedByte;
+ var selectedByte;
+ var selectedByteMask;
+
+ bytePosition = this.length() - Math.ceil((aBitPosition + 1)/ 8);
+ bitPositionInSelectedByte = aBitPosition % 8;
+ selectedByte = this.byteAtIndex(bytePosition);
+
+ if (bitPositionInSelectedByte > 0) {
+ selectedByteMask = (1 << bitPositionInSelectedByte);
+ } else {
+ selectedByteMask = 1;
+ }
+ result = selectedByte & selectedByteMask ? 1 : 0;
+//console.log("aBitPosition: " + aBitPosition + ", length: " + this.length() + ", bytePosition: " + bytePosition + ", bitPositionInSelectedByte: " + bitPositionInSelectedByte + ", selectedByteMask: " + selectedByteMask);
+
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'bitBlockAtIndexWithSize': function(aBitPosition, aSize) {
+ var result;
+ var bitValue;
+ var i,c;
+
+ result = 0;
+ c = aSize;
+ for (i=0; i<c; i++) {
+ bitValue = this.bitAtIndex(aBitPosition + i);
+ result = result | bitValue << i;
+ }
+
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'asString': function() {
+ var result;
+ var length;
+ var i;
+
+//var startTime = new Date();
+
+//# result = "";
+ result = [];
+
+ i = 0;
+ length = this.length();
+
+ while (i < length) {
+ var currentCharacter;
+ var currentByte;
+ var unicode;
+
+ currentByte = this.byteAtIndex(i);
+
+ if ((currentByte & 0x80) == 0x00 ) { // 0xxxxxxx
+ unicode = currentByte;
+ currentCharacter = String.fromCharCode(unicode);
+ } else if ((currentByte & 0xe0) == 0xc0 ) { // 110xxxxx 10xxxxxx
+ unicode = (currentByte & 0x1f) << 6;
+ i++; currentByte = this.byteAtIndex(i);
+ unicode = unicode | (currentByte & 0x3f);
+
+ currentCharacter = String.fromCharCode(unicode);
+ } else if ((currentByte & 0xf0) == 0xe0 ) { // 1110xxxx 10xxxxxx 10xxxxxx
+ unicode = (currentByte & 0x0f) << (6+6);
+ i++; currentByte = this.byteAtIndex(i);
+ unicode = unicode | ((currentByte & 0x3f) << 6);
+ i++; currentByte = this.byteAtIndex(i);
+ unicode = unicode | (currentByte & 0x3f);
+
+ currentCharacter = String.fromCharCode(unicode);
+ } else { // 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+ unicode = (currentByte & 0x07) << (6+6+6);
+ i++; currentByte = this.byteAtIndex(i);
+ unicode = unicode | ((currentByte & 0x3f) << (6+6));
+ i++; currentByte = this.byteAtIndex(i);
+ unicode = unicode | ((currentByte & 0x3f) << 6);
+ i++; currentByte = this.byteAtIndex(i);
+ unicode = unicode | (currentByte & 0x3f);
+
+ currentCharacter = String.fromCharCode(unicode);
+ }
+
+// result += currentCharacter;
+ result.push(currentCharacter);
+ i++;
+ }
+
+//MochiKit.Logging.logDebug("[" + (new Date() - startTime) + "] ByteArray.asString");
+
+// return result;
+ return result.join("");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'toHexString': function() {
+ throw Clipperz.Base.exception.AbstractMethod;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'base64map': "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
+ 'base64mapIndex': "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".split(''),
+// 'base64mapInvertedIndex': {
+// 'A': 0, 'B': 1, 'C': 2, 'D': 3, 'E': 4, 'F': 5, 'G': 6, 'H': 7, 'I': 8, 'J': 9,
+// 'K': 10, 'L': 11, 'M': 12, 'N': 13, 'O': 14, 'P': 15, 'Q': 16, 'R': 17, 'S': 18, 'T': 19,
+// 'U': 20, 'V': 21, 'W': 22, 'X': 23, 'Y': 24, 'Z': 25, 'a': 26, 'b': 27, 'c': 28, 'd': 29,
+// 'e': 30, 'f': 31, 'g': 32, 'h': 33, 'i': 34, 'j': 35, 'k': 36, 'l': 37, 'm': 38, 'n': 39,
+// 'o': 40, 'p': 41, 'q': 42, 'r': 43, 's': 44, 't': 45, 'u': 46, 'v': 47, 'w': 48, 'x': 49,
+// 'y': 50, 'z': 51, '0': 52, '1': 53, '2': 54, '3': 55, '4': 56, '5': 57, '6': 58, '7': 59,
+// '8': 60, '9': 61, '+': 62, '/': 63,
+// "=": -1},
+
+ //-------------------------------------------------------------------------
+
+ 'appendBase64String': function(aValue) {
+ var i;
+ var length;
+
+ length = aValue.length;
+
+ if ((length % 4) != 0) {
+ MochiKit.Logging.logError("the value passed to the 'ByteArray.setBase64Value' is not correct");
+ throw Clipperz.ByteArray.exception.InvalidValue;
+ }
+
+ i = 0;
+ while (i<length) {
+ var value1, value2, value3, value4;
+ var byte1, byte2, byte3;
+
+ value1 = this.base64map.indexOf(aValue.charAt(i));
+ value2 = this.base64map.indexOf(aValue.charAt(i+1));
+ value3 = this.base64map.indexOf(aValue.charAt(i+2));
+ value4 = this.base64map.indexOf(aValue.charAt(i+3));
+
+// value1 = this.base64mapInvertedIndex[aValue.charAt(i)];
+// value2 = this.base64mapInvertedIndex[aValue.charAt(i+1)];
+// value3 = this.base64mapInvertedIndex[aValue.charAt(i+2)];
+// value4 = this.base64mapInvertedIndex[aValue.charAt(i+3)];
+
+ byte1 = (value1 << 2) | ((value2 & 0x30) >> 4);
+ if (value3 != -1) {
+ byte2 = ((value2 & 0x0f) << 4) | ((value3 & 0x3c) >> 2);
+
+ if (value4 != -1) {
+ byte3 = ((value3 & 0x03) << 6) | (value4);
+ } else {
+ byte3 = null;
+ }
+ } else {
+ byte2 = null;
+ byte3 = null;
+ }
+
+ this.appendByte(byte1);
+ this.appendByte(byte2);
+ this.appendByte(byte3);
+
+ i += 4;
+ }
+
+ return this;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'toBase64String': function() {
+ var result;
+ var length;
+ var i;
+ var byte1, byte2, byte3;
+ var char1, char2, char3, char4;
+
+ i = 0;
+ length = this.length();
+ result = new Array(Math.ceil(length/3));
+
+ while (i < length) {
+ byte1 = this.byteAtIndex(i);
+ if ((i+2) < length) {
+ byte2 = this.byteAtIndex(i+1);
+ byte3 = this.byteAtIndex(i+2);
+ } else if ((i+2) == length) {
+ byte2 = this.byteAtIndex(i+1);
+ byte3 = null;
+ } else {
+ byte2 = null;
+ byte3 = null;
+ }
+
+ char1 = this.base64mapIndex[byte1 >> 2];
+ if (byte2 != null) {
+ char2 = this.base64mapIndex[((byte1 & 0x03) << 4) | ((byte2 & 0xf0) >> 4)];
+ if (byte3 != null) {
+ char3 = this.base64mapIndex[((byte2 & 0x0f) << 2) | ((byte3 & 0xc0) >> 6)];
+ char4 = this.base64mapIndex[(byte3 & 0x3f)];
+ } else {
+ char3 = this.base64mapIndex[(byte2 & 0x0f) << 2];
+ char4 = "=";
+ }
+ } else {
+ char2 = this.base64mapIndex[(byte1 & 0x03) << 4];
+ char3 = "=";
+ char4 = "=";
+ }
+
+ result.push(char1 + char2 + char3 + char4);
+
+ i += 3;
+ }
+
+ return result.join("");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'base32map': "0123456789abcdefghjkmnpqrstvwxyz",
+ 'base32mapIndex': "0123456789abcdefghjkmnpqrstvwxyz".split(''),
+
+ //-------------------------------------------------------------------------
+
+ 'appendBase32String': function(aValue) {
+ var value;
+ var i;
+ var length;
+ var value1, value2, value3, value4, value5, value6, value7, value8;
+ var byte1, byte2, byte3, byte4, byte5;
+
+ value = aValue.toLowerCase();
+ value = value.replace(/[\s\-]/g, '');
+ value = value.replace(/[0o]/g, '0');
+ value = value.replace(/[1il]/g, '1');
+
+ length = value.length;
+
+ if ((length % 8) != 0) {
+ MochiKit.Logging.logError("the value passed to the 'ByteArray.setBase32Value' is not correct");
+ throw Clipperz.ByteArray.exception.InvalidValue;
+ }
+
+ i = 0;
+ while (i<length) {
+ value1 = this.base32map.indexOf(value.charAt(i));
+ value2 = this.base32map.indexOf(value.charAt(i+1));
+ value3 = this.base32map.indexOf(value.charAt(i+2));
+ value4 = this.base32map.indexOf(value.charAt(i+3));
+ value5 = this.base32map.indexOf(value.charAt(i+4));
+ value6 = this.base32map.indexOf(value.charAt(i+5));
+ value7 = this.base32map.indexOf(value.charAt(i+6));
+ value8 = this.base32map.indexOf(value.charAt(i+7));
+
+ byte1 = byte2 = byte3 = byte4 = byte5 = null;
+
+ byte1 = (value1 << 3) | ((value2 & 0x1c) >> 2);
+ if (value3 != -1) {
+ byte2 = ((value2 & 0x03) << 6) | (value3 << 1) | ((value4 & 0x10) >> 4);
+ if (value5 != -1) {
+ byte3 = ((value4 & 0x0f) << 4) | ((value5 & 0x1e) >> 1);
+ if (value6 != -1) {
+ byte4 = ((value5 & 0x01) << 7) | (value6 << 2) | ((value7 & 0x18) >> 3);
+ if (value8 != -1) {
+ byte5 = ((value7 & 0x07) << 5) | (value8);
+ }
+ }
+ }
+ }
+
+ this.appendByte(byte1);
+ this.appendByte(byte2);
+ this.appendByte(byte3);
+ this.appendByte(byte4);
+ this.appendByte(byte5);
+
+ i += 8;
+ }
+
+ return this;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'toBase32String': function() {
+ var result;
+ var length;
+ var i;
+ var byte1, byte2, byte3, byte4, byte5;
+ var char1, char2, char3, char4, char5, char6, char7, char8;
+
+ i = 0;
+ length = this.length();
+ result = new Array(Math.ceil(length/5));
+
+ while (i < length) {
+ byte1 = this.byteAtIndex(i);
+
+ if ((i+4) < length) {
+ byte2 = this.byteAtIndex(i+1);
+ byte3 = this.byteAtIndex(i+2);
+ byte4 = this.byteAtIndex(i+3);
+ byte5 = this.byteAtIndex(i+4);
+ } else if ((i+4) == length) {
+ byte2 = this.byteAtIndex(i+1);
+ byte3 = this.byteAtIndex(i+2);
+ byte4 = this.byteAtIndex(i+3);
+ byte5 = null;
+ } else if ((i+3) == length) {
+ byte2 = this.byteAtIndex(i+1);
+ byte3 = this.byteAtIndex(i+2);
+ byte4 = null;
+ byte5 = null;
+ } else if ((i+2) == length) {
+ byte2 = this.byteAtIndex(i+1);
+ byte3 = null;
+ byte4 = null;
+ byte5 = null;
+ } else {
+ byte2 = null;
+ byte3 = null;
+ byte4 = null;
+ byte5 = null;
+ }
+
+
+ char1 = this.base32mapIndex[byte1 >> 3];
+ char2 = char3 = char4 = char5 = char6 = char7 = char8 = "=";
+
+ if (byte2 != null) {
+ char2 = this.base32mapIndex[((byte1 & 0x07) << 2) | ((byte2 & 0xc0) >> 6)];
+ char3 = this.base32mapIndex[((byte2 & 0x3e) >> 1)];
+ if (byte3 != null) {
+ char4 = this.base32mapIndex[((byte2 & 0x01) << 4) | ((byte3 & 0xf0) >> 4)];
+ if (byte4 != null) {
+ char5 = this.base32mapIndex[((byte3 & 0x0f) << 1) | ((byte4 & 0x80) >> 7)];
+ char6 = this.base32mapIndex[(byte4 & 0x7c) >> 2];
+ if (byte5 != null) {
+ char7 = this.base32mapIndex[((byte4 & 0x03) << 3) | ((byte5 & 0xe0) >> 5)];
+ char8 = this.base32mapIndex[(byte5 & 0x1f)];
+ } else {
+ char7 = this.base32mapIndex[(byte4 & 0x03) << 3];
+ }
+ } else {
+ char5 = this.base32mapIndex[(byte3 & 0x0f) << 1];
+ }
+
+ } else {
+ char4 = this.base32mapIndex[(byte2 & 0x01) << 4];
+ }
+ } else {
+ char2 = this.base32mapIndex[(byte1 & 0x07) << 2];
+ }
+
+ result.push(char1 + char2 + char3 + char4 + char5 + char6 + char7 + char8);
+ i += 5;
+ }
+
+ return result.join("");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'split': function(aStartingIndex, anEndingIndex) {
+ throw Clipperz.Base.exception.AbstractMethod;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'increment': function() {
+ var i;
+ var done;
+
+ done = false;
+ i = this.length() - 1;
+
+ while ((i>=0) && (done == false)) {
+ var currentByteValue;
+
+ currentByteValue = this.byteAtIndex(i);
+
+ if (currentByteValue == 0xff) {
+ this.setByteAtIndex(0, i);
+ if (i>= 0) {
+ i --;
+ } else {
+ done = true;
+ }
+ } else {
+ this.setByteAtIndex(currentByteValue + 1, i);
+ done = true;
+ }
+ }
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'arrayValues': function() {
+ throw Clipperz.Base.exception.AbstractMethod;
+ },
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+
+});
+
+//=============================================================================
+//
+// Clipperz.ByteArray_hex
+//
+//=============================================================================
+Clipperz.ByteArray_hex = function (args) {
+ this._value = "";
+
+ if (typeof(args) != 'undefined') {
+ if (args.constructor == Array) {
+ this.appendBytes(args);
+ } else if (args.constructor == String) {
+ if (args.indexOf("0x") == 0) {
+ var value;
+
+ value = args.substring(2).toLowerCase();
+ if (/[0123456789abcdef]*/.test(value)) {
+ if ((value.length % 2) == 0) {
+ this._value = value;
+ } else {
+ this._value = "0" + value;
+ }
+ } else {
+MochiKit.Logging.logError("Clipperz.ByteArray should be inizialized with an hex string.");
+ throw Clipperz.ByteArray.exception.InvalidValue;
+ }
+ } else {
+ var value;
+ var i,c;
+
+ c = args.length;
+ value = new Array(c);
+ for (i=0; i<c; i++) {
+ value.push(Clipperz.ByteArray.unicodeToUtf8HexString(args.charCodeAt(i)));
+ }
+
+ this._value = value.join("");
+ }
+ } else {
+ this.appendBytes(MochiKit.Base.extend(null, arguments));
+ }
+ }
+ return this;
+}
+
+Clipperz.ByteArray_hex.prototype = MochiKit.Base.update(new Clipperz.ByteArray_abstract(), {
+
+ //-------------------------------------------------------------------------
+
+ 'toString': function() {
+ return "Clipperz.ByteArray_hex";
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'clone': function() {
+ var result;
+
+ result = this.newInstance();
+ result._value = this._value;
+
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'newInstance': function() {
+ return new Clipperz.ByteArray_hex();
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'reset': function() {
+ this._value = "";
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'length': function() {
+ return (this._value.length / 2);
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'appendBlock': function(aBlock) {
+ this._value = this._value += aBlock.toHexString().substring(2);
+
+ return this;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'appendByte': function(aValue) {
+ if (aValue != null) {
+ this.checkValue(aValue);
+ this._value += Clipperz.ByteArray.byteToHex(aValue);
+ }
+
+ return this;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'byteAtIndex': function(anIndex) {
+ return parseInt(this._value.substr(anIndex*2, 2), 16);
+ },
+
+ 'setByteAtIndex': function(aValue, anIndex) {
+ var missingBytes;
+
+ this.checkValue(aValue);
+
+ missingBytes = anIndex - this.length();
+
+ if (missingBytes < 0) {
+ var currentValue;
+ var firstCutIndex;
+ var secondCutIndex;
+
+ firstCutIndex = anIndex * 2;
+ secondCutIndex = firstCutIndex + 2;
+ currentValue = this._value;
+ this._value = currentValue.substring(0, firstCutIndex) +
+ Clipperz.ByteArray.byteToHex(aValue) +
+ currentValue.substring(secondCutIndex);
+ } else if (missingBytes == 0) {
+ this.appendByte(aValue);
+ } else {
+ var i,c;
+
+ c = missingBytes;
+ for (i=0; i<c; i++) {
+ this.appendByte(0);
+ }
+
+ this.appendByte(aValue);
+ }
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'toHexString': function() {
+ return "0x" + this._value;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'split': function(aStartingIndex, anEndingIndex) {
+ var result;
+ var startingIndex;
+ var endingIndex;
+
+ result = this.newInstance();
+
+ startingIndex = aStartingIndex * 2;
+ if (typeof(anEndingIndex) != 'undefined') {
+ endingIndex = anEndingIndex * 2;
+ result._value = this._value.substring(startingIndex, endingIndex);
+ } else {
+ result._value = this._value.substring(startingIndex);
+ }
+
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'arrayValues': function() {
+ var result;
+ var i,c;
+
+ c = this.length();
+
+ result = new Array(c);
+ for (i=0; i<c; i++) {
+ result[i] = this.byteAtIndex(i);
+ }
+
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+});
+
+//=============================================================================
+//
+// Clipperz.ByteArray_array
+//
+//=============================================================================
+
+Clipperz.ByteArray_array = function (args) {
+ if (typeof(args) != 'undefined') {
+ if (args.constructor == Array) {
+ this._value = args.slice(0);
+ } else if (args.constructor == String) {
+ var result;
+ var value;
+ var i, c;
+
+ if (args.indexOf("0x") == 0) {
+
+ value = args.substring(2).toLowerCase();
+ if (/[0123456789abcdef]*/.test(value)) {
+ if ((value.length % 2) != 0) {
+ value = "0" + value;
+ }
+ } else {
+MochiKit.Logging.logError("Clipperz.ByteArray should be inizialized with an hex string.");
+ throw Clipperz.ByteArray.exception.InvalidValue;
+ }
+
+ c = value.length / 2
+ result = new Array(c);
+ for (i=0; i<c; i++) {
+ result[i] = parseInt(value.substr(i*2, 2), 16);
+ }
+
+ } else {
+ var unicode;
+ result = [];
+ c = args.length;
+ for (i=0; i<c; i++) {
+// Clipperz.ByteArray.pushUtf8BytesOfUnicodeChar(result, args.charCodeAt(i));
+
+ unicode = args.charCodeAt(i);
+ if (unicode <= 0x7f) { // 0x00000000 - 0x0000007f -> 0xxxxxxx
+ result.push(unicode);
+ // } else if ((unicode >= 0x80) && (unicode <= 0x7ff)) { // 0x00000080 - 0x000007ff -> 110xxxxx 10xxxxxx
+ } else if (unicode <= 0x7ff) { // 0x00000080 - 0x000007ff -> 110xxxxx 10xxxxxx
+ result.push((unicode >> 6) | 0xc0);
+ result.push((unicode & 0x3F) | 0x80);
+ // } else if ((unicode >= 0x0800) && (unicode <= 0xffff)) { // 0x00000800 - 0x0000ffff -> 1110xxxx 10xxxxxx 10xxxxxx
+ } else if (unicode <= 0xffff) { // 0x00000800 - 0x0000ffff -> 1110xxxx 10xxxxxx 10xxxxxx
+ result.push((unicode >> 12) | 0xe0);
+ result.push(((unicode >> 6) & 0x3f) | 0x80);
+ result.push((unicode & 0x3f) | 0x80);
+ } else { // 0x00010000 - 0x001fffff -> 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+ result.push((unicode >> 18) | 0xf0);
+ result.push(((unicode >> 12) & 0x3f) | 0x80);
+ result.push(((unicode >> 6) & 0x3f) | 0x80);
+ result.push((unicode & 0x3f) | 0x80);
+ }
+ }
+ }
+
+
+ this._value = result;
+ } else {
+ this._value = [];
+ this.appendBytes(MochiKit.Base.extend(null, arguments));
+ }
+ } else {
+ this._value = [];
+ }
+
+ return this;
+}
+
+Clipperz.ByteArray_array.prototype = MochiKit.Base.update(new Clipperz.ByteArray_abstract(), {
+
+ //-------------------------------------------------------------------------
+
+ 'toString': function() {
+ return "Clipperz.ByteArray_array";
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'clone': function() {
+ var result;
+
+ result = this.newInstance();
+ result.appendBytes(this._value);
+
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'newInstance': function() {
+ return new Clipperz.ByteArray_array();
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'reset': function() {
+ this._value = [];
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'length': function() {
+ return (this._value.length);
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'appendBlock': function(aBlock) {
+ MochiKit.Base.extend(this._value, aBlock._value);
+
+ return this;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'appendByte': function(aValue) {
+ if (aValue != null) {
+ this.checkValue(aValue);
+ this._value.push(aValue);
+ }
+
+ return this;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'byteAtIndex': function(anIndex) {
+ return this._value[anIndex];
+ },
+
+ 'setByteAtIndex': function(aValue, anIndex) {
+ var missingBytes;
+
+ this.checkValue(aValue);
+
+ missingBytes = anIndex - this.length();
+
+ if (missingBytes < 0) {
+ this._value[anIndex] = aValue;
+ } else if (missingBytes == 0) {
+ this._value.push(aValue);
+ } else {
+ var i,c;
+
+ c = missingBytes;
+ for (i=0; i<c; i++) {
+ this._value.push(0);
+ }
+
+ this._value.push(aValue);
+ }
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'toHexString': function() {
+ var result;
+ var i, c;
+
+ result = "0x";
+ c = this.length();
+ for (i=0; i<c; i++) {
+ result += Clipperz.ByteArray.byteToHex(this._value[i]);
+ }
+
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'split': function(aStartingIndex, anEndingIndex) {
+ var result;
+
+ result = this.newInstance();
+ result._value = this._value.slice(aStartingIndex, anEndingIndex ? anEndingIndex : this.length());
+
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'arrayValues': function() {
+ return this._value.slice(0);
+ },
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+});
+
+
+
+
+
+//=============================================================================
+//
+// Clipperz.ByteArray_string
+//
+//=============================================================================
+
+Clipperz.ByteArray_string = function (args) {
+ this._value = "";
+
+ if (typeof(args) != 'undefined') {
+ if (args.constructor == Array) {
+ this.appendBytes(args);
+ } else if (args.constructor == String) {
+ var result;
+ var value;
+ var i, c;
+
+ if (args.indexOf("0x") == 0) {
+
+ value = args.substring(2).toLowerCase();
+ if (/[0123456789abcdef]*/.test(value)) {
+ if ((value.length % 2) != 0) {
+ value = "0" + value;
+ }
+ } else {
+MochiKit.Logging.logError("Clipperz.ByteArray should be inizialized with an hex string.");
+ throw Clipperz.ByteArray.exception.InvalidValue;
+ }
+ } else {
+ value = "";
+ c = args.length;
+ for (i=0; i<c; i++) {
+ value += Clipperz.ByteArray.unicodeToUtf8HexString(args.charCodeAt(i));
+ }
+ }
+
+ c = value.length / 2
+ for (i=0; i<c; i++) {
+ this.appendByte(parseInt(value.substr(i*2, 2), 16));
+ }
+ } else {
+ this.appendBytes(MochiKit.Base.extend(null, arguments));
+ }
+ }
+
+ return this;
+}
+
+Clipperz.ByteArray_string.prototype = MochiKit.Base.update(new Clipperz.ByteArray_abstract(), {
+
+ //-------------------------------------------------------------------------
+
+ 'toString': function() {
+ return "Clipperz.ByteArray_string";
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'clone': function() {
+ var result;
+
+ result = this.newInstance();
+ result._value = this._value;
+
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'newInstance': function() {
+ return new Clipperz.ByteArray_string();
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'reset': function() {
+ this._value = "";
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'length': function() {
+ return (this._value.length);
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'appendBlock': function(aBlock) {
+ this._value += aBlock._value;
+
+ return this;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'appendByte': function(aValue) {
+ if (aValue != null) {
+ this.checkValue(aValue);
+ this._value += String.fromCharCode(aValue);
+ }
+
+ return this;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'byteAtIndex': function(anIndex) {
+ return this._value.charCodeAt(anIndex);
+ },
+
+ 'setByteAtIndex': function(aValue, anIndex) {
+ var missingBytes;
+
+ this.checkValue(aValue);
+
+ missingBytes = anIndex - this.length();
+
+ if (missingBytes < 0) {
+ this._value = this._value.substring(0, anIndex) + String.fromCharCode(aValue) + this._value.substring(anIndex + 1);
+ } else if (missingBytes == 0) {
+ this.appendByte(aValue);
+ } else {
+ var i,c;
+
+ c = missingBytes;
+ for (i=0; i<c; i++) {
+ this.appendByte(0);
+ }
+
+ this.appendByte(aValue);
+ }
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'toHexString': function() {
+ var result;
+ var i, c;
+
+ result = "0x";
+ c = this.length();
+ for (i=0; i<c; i++) {
+ result += Clipperz.ByteArray.byteToHex(this.byteAtIndex(i));
+ }
+
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'split': function(aStartingIndex, anEndingIndex) {
+ var result;
+ result = this.newInstance();
+ result._value = this._value.substring(aStartingIndex, anEndingIndex ? anEndingIndex : this.length());
+
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'arrayValues': function() {
+ var result;
+ var i,c;
+
+ c = this.length();
+
+ result = new Array(c);
+ for (i=0; i<c; i++) {
+ result[i] = this.byteAtIndex(i);
+ }
+
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+});
+
+
+//=============================================================================
+//
+// Clipperz.ByteArray
+//
+//=============================================================================
+
+Clipperz.ByteArray = Clipperz.ByteArray_array;
+//Clipperz.ByteArray = Clipperz.ByteArray_string;
+//Clipperz.ByteArray = Clipperz.ByteArray_hex;
+
+//#############################################################################
+
+Clipperz.ByteArray.byteToHex = function(aByte) {
+ return ((aByte < 16) ? "0" : "") + aByte.toString(16);
+}
+
+
+Clipperz.ByteArray.unicodeToUtf8HexString = function(aUnicode) {
+ var result;
+ var self;
+
+ self = Clipperz.ByteArray;
+
+ if (aUnicode <= 0x7f) { // 0x00000000 - 0x0000007f -> 0xxxxxxx
+ result = self.byteToHex(aUnicode);
+// } else if ((aUnicode >= 0x80) && (aUnicode <= 0x7ff)) { // 0x00000080 - 0x000007ff -> 110xxxxx 10xxxxxx
+ } else if (aUnicode <= 0x7ff) { // 0x00000080 - 0x000007ff -> 110xxxxx 10xxxxxx
+ result = self.byteToHex((aUnicode >> 6) | 0xc0);
+ result += self.byteToHex((aUnicode & 0x3F) | 0x80);
+// } else if ((aUnicode >= 0x0800) && (aUnicode <= 0xffff)) { // 0x00000800 - 0x0000ffff -> 1110xxxx 10xxxxxx 10xxxxxx
+ } else if (aUnicode <= 0xffff) { // 0x00000800 - 0x0000ffff -> 1110xxxx 10xxxxxx 10xxxxxx
+ result = self.byteToHex((aUnicode >> 12) | 0xe0);
+ result += self.byteToHex(((aUnicode >> 6) & 0x3f) | 0x80);
+ result += self.byteToHex((aUnicode & 0x3f) | 0x80);
+ } else { // 0x00010000 - 0x001fffff -> 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+ result = self.byteToHex((aUnicode >> 18) | 0xf0);
+ result += self.byteToHex(((aUnicode >> 12) & 0x3f) | 0x80);
+ result += self.byteToHex(((aUnicode >> 6) & 0x3f) | 0x80);
+ result += self.byteToHex((aUnicode & 0x3f) | 0x80);
+ }
+
+ return result;
+}
+
+Clipperz.ByteArray.pushUtf8BytesOfUnicodeChar = function(anArray, aUnicode) {
+ var self;
+
+ self = Clipperz.ByteArray;
+
+ if (aUnicode <= 0x7f) { // 0x00000000 - 0x0000007f -> 0xxxxxxx
+ anArray.push(aUnicode);
+// } else if ((aUnicode >= 0x80) && (aUnicode <= 0x7ff)) { // 0x00000080 - 0x000007ff -> 110xxxxx 10xxxxxx
+ } else if (aUnicode <= 0x7ff) { // 0x00000080 - 0x000007ff -> 110xxxxx 10xxxxxx
+ anArray.push((aUnicode >> 6) | 0xc0);
+ anArray.push((aUnicode & 0x3F) | 0x80);
+// } else if ((aUnicode >= 0x0800) && (aUnicode <= 0xffff)) { // 0x00000800 - 0x0000ffff -> 1110xxxx 10xxxxxx 10xxxxxx
+ } else if (aUnicode <= 0xffff) { // 0x00000800 - 0x0000ffff -> 1110xxxx 10xxxxxx 10xxxxxx
+ anArray.push((aUnicode >> 12) | 0xe0);
+ anArray.push(((aUnicode >> 6) & 0x3f) | 0x80);
+ anArray.push((aUnicode & 0x3f) | 0x80);
+ } else { // 0x00010000 - 0x001fffff -> 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+ anArray.push((aUnicode >> 18) | 0xf0);
+ anArray.push(((aUnicode >> 12) & 0x3f) | 0x80);
+ anArray.push(((aUnicode >> 6) & 0x3f) | 0x80);
+ anArray.push((aUnicode & 0x3f) | 0x80);
+ }
+}
+
+Clipperz.ByteArray.exception = {
+ InvalidValue: new MochiKit.Base.NamedError("Clipperz.ByteArray.exception.InvalidValue")
+};
+
+//#############################################################################
+
+Clipperz.ByteArrayIterator = function(args) {
+ args = args || {};
+
+ this._byteArray = args.byteArray;
+ this._blockSize = args.blockSize;
+ this._finalPadding = args.finalPadding || false;
+
+ this._currentPosition = 0;
+
+ return this;
+}
+
+Clipperz.ByteArrayIterator.prototype = MochiKit.Base.update(null, {
+
+ //-------------------------------------------------------------------------
+
+ 'toString': function() {
+ return "Clipperz.ByteArrayIterator";
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'blockSize': function() {
+ var result;
+
+ result = this._blockSize;
+
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'currentPosition': function() {
+ var result;
+
+ result = this._currentPosition;
+
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'byteArray': function() {
+ var result;
+
+ result = this._byteArray;
+
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'finalPadding': function() {
+ var result;
+
+ result = this._finalPadding;
+
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'nextBlock': function() {
+ var result;
+ var currentPosition;
+ var byteArrayLength;
+
+ currentPosition = this._currentPosition;
+ byteArrayLength = this.byteArray().length();
+
+ if (currentPosition < byteArrayLength) {
+ var i,c;
+
+ c = this.blockSize();
+ result = new Array(c);
+ for (i=0; i<c; i++) {
+ if (currentPosition < byteArrayLength) {
+ result[i] = this.byteArray().byteAtIndex(currentPosition);
+ currentPosition++;
+ } else if (this.finalPadding() == true) {
+ result[i] = 0;
+ }
+ }
+
+ this._currentPosition = currentPosition;
+ } else {
+ result = null;
+ }
+
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'nextBlockArray': function() {
+ var result;
+ var nextBlock;
+
+ nextBlock = this.nextBlock();
+
+ if (nextBlock != null) {
+ result = new Clipperz.ByteArray(nextBlock);
+ } else {
+ result = null;
+ }
+
+ return result;
+ },
+
+ //-----------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+
+});
diff --git a/frontend/beta/js/Clipperz/CSVProcessor.js b/frontend/beta/js/Clipperz/CSVProcessor.js
new file mode 100644
index 0000000..164b02e
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/CSVProcessor.js
@@ -0,0 +1,348 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. 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;
+
+//MochiKit.Logging.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, "");
+
+//MochiKit.Logging.logDebug("line: '" + parameter.line + "'");
+ } while (parameter.line != "");
+//MochiKit.Logging.logDebug("--- CSVProcessor.parse - result: " + Clipperz.Base.serializeJSON(result));
+//MochiKit.Logging.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 MochiKit.Async.Deferred();
+ deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'importProcessorProgressUpdate', {status:'processing', size:aContext.size, progress:(aContext.size - aContext.line.length)});
+ deferredResult.addCallback(MochiKit.Async.wait, 0.2);
+ deferredResult.addCallback(MochiKit.Base.method(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 MochiKit.Async.Deferred();
+ deferredResult.addCallback(MochiKit.Base.method(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;
+
+//MochiKit.Logging.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) {
+//MochiKit.Logging.logDebug("---> 1: '" + aParameter.line.replace(/\n/g, "\\n") + "'");
+ if (inQuotes == true) {
+//MochiKit.Logging.logDebug("---> 1.1: '" + aParameter.line.replace(/\n/g, "\\n") + "'");
+ throw new Error("CSV Parsing error; end of string, missing closing double-quote...");
+ } else {
+//MochiKit.Logging.logDebug("---> 1.2: '" + aParameter.line.replace(/\n/g, "\\n") + "'");
+ done = true;
+ }
+ } else if (escapedQuoteBeginRegexp.test(aParameter.line)) {
+//MochiKit.Logging.logDebug("---> 2.1: '" + aParameter.line.replace(/\n/g, "\\n") + "'");
+ result += this.quoteChar();
+ aParameter.line = aParameter.line.substr(2, aParameter.line.length - 1);
+//MochiKit.Logging.logDebug("<--- 2.2: '" + aParameter.line.replace(/\n/g, "\\n") + "'");
+ } else if (singleQuoteBeginRegexp.test(aParameter.line)) {
+//MochiKit.Logging.logDebug("---> 3: '" + aParameter.line.replace(/\n/g, "\\n") + "'");
+ if (inQuotes == true) {
+ if (aParameter.line.length == 1) {
+//MochiKit.Logging.logDebug("---> 3.1: '" + aParameter.line.replace(/\n/g, "\\n") + "'");
+ aParameter.line = '';
+ done = true;
+ } else if (singleQuoteCommaEndRegexp.test(aParameter.line)) {
+//MochiKit.Logging.logDebug("---> 3.3: '" + aParameter.line.replace(/\n/g, "\\n") + "'");
+ aParameter.line = aParameter.line.substr(2, aParameter.line.length - 1);
+ done = true;
+//MochiKit.Logging.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 {
+//MochiKit.Logging.logDebug("---> 4: '" + aParameter.line.replace(/\n/g, "\\n") + "'");
+ if (result == "") {
+//MochiKit.Logging.logDebug("---> 4.1: '" + aParameter.line.replace(/\n/g, "\\n") + "'");
+ inQuotes = true;
+ aParameter.line = aParameter.line.substr(1, aParameter.line.length - 1);
+//MochiKit.Logging.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)) {
+//MochiKit.Logging.logDebug("---> 5: '" + aParameter.line.replace(/\n/g, "\\n") + "'");
+ if (inQuotes) {
+//MochiKit.Logging.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);
+//MochiKit.Logging.logDebug("<--- 5.1: '" + aParameter.line.replace(/\n/g, "\\n") + "'");
+ } else {
+//MochiKit.Logging.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 == "") {
+//MochiKit.Logging.logDebug("######");
+ aParameter.isThereAnEmptyFinalField = true;
+ };
+ done = true;
+//MochiKit.Logging.logDebug("<--- 5.2: '" + aParameter.line.replace(/\n/g, "\\n") + "'");
+ }
+ } else if (validRegexp.test(aParameter.line)) {
+//MochiKit.Logging.logDebug("---> 6: '" + aParameter.line.replace(/\n/g, "\\n") + "'");
+ result += aParameter.line.substr(0, 1);
+ aParameter.line = aParameter.line.substr(1, aParameter.line.length - 1);
+//MochiKit.Logging.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) {
+ MochiKit.Logging.logError(exception.message);
+// result = null;
+ throw exception;
+ }
+ }
+
+//if (result != null) {
+// MochiKit.Logging.logDebug("<=== result: '" + result.replace(/\n/g, "\\n") + "'");
+//} else {
+// MochiKit.Logging.logDebug("<=== result: NULL");
+//}
+
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+});
+
+
diff --git a/frontend/beta/js/Clipperz/Crypto/AES.js b/frontend/beta/js/Clipperz/Crypto/AES.js
new file mode 100644
index 0000000..a60df5c
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/Crypto/AES.js
@@ -0,0 +1,836 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. 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;
+
+ 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;
+ },
+
+ 'executionStep': function() {
+ return this._executionStep;
+ },
+
+ 'setExecutionStep': function(aValue) {
+ this._executionStep = aValue;
+ },
+
+ 'pause': function(aValue) {
+ return MochiKit.Async.wait(Clipperz.Crypto.AES.DeferredExecution.pauseTime, aValue);
+ },
+
+ //-----------------------------------------------------------------------------
+ __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 {
+ MochiKit.Logging.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;
+
+ self = Clipperz.Crypto.AES;
+ 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);
+
+ return anExecutionContext;
+ },
+
+ //-----------------------------------------------------------------------------
+
+ 'deferredEncryptBlocks': function(anExecutionContext) {
+ var deferredResult;
+ var messageSize;
+ var i,c;
+ var now;
+
+ messageSize = anExecutionContext.messageLength();
+
+ deferredResult = new MochiKit.Async.Deferred();
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Clipperz.Crypto.AES.deferredEncryptBlocks - START: " + res); return res;});
+// deferredResult.addCallback(MochiKit.Base.method(anExecutionContext, 'pause'));
+
+ c = Math.ceil(messageSize / anExecutionContext.elaborationChunkSize());
+ for (i=0; i<c; i++) {
+//deferredResult.addBoth(function(res) {now = new Date(); return res;});
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Clipperz.Crypto.AES.deferredEncryptBlocks - : (" + i + ") - " + res); return res;});
+ deferredResult.addCallback(Clipperz.Crypto.AES.deferredEncryptExecutionChunk);
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("[" + (new Date() - now) + "]Clipperz.Crypto.AES.deferredEncryptBlocks"); return res;});
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Clipperz.Crypto.AES.deferredEncryptBlocks - : (" + i + ") -- " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(anExecutionContext, 'pause'));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Clipperz.Crypto.AES.deferredEncryptBlocks - : (" + i + ") --- " + res); return res;});
+ }
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Clipperz.Crypto.AES.deferredEncryptBlocks - END: " + res); return res;});
+
+ deferredResult.callback(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 MochiKit.Async.Deferred();
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Clipperz.Crypto.AES.deferredEncrypt - 1: " + res); return res;});
+ deferredResult.addCallback(Clipperz.Crypto.AES.deferredEncryptBlocks);
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Clipperz.Crypto.AES.deferredEncrypt - 2: " + res); return res;});
+ deferredResult.addCallback(function(anExecutionContext) {
+ var result;
+
+ result = anExecutionContext.nonce().clone();
+ result.appendBytes(anExecutionContext.resultArray());
+
+ return result;
+ });
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Clipperz.Crypto.AES.deferredEncrypt - 3: " + res); return res;});
+ 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 MochiKit.Async.Deferred();
+ 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': 4096, // 1024 4096 8192 16384 32768;
+ 'pauseTime': 0.2
+}
+
+Clipperz.Crypto.AES.exception = {
+ 'UnsupportedKeySize': new MochiKit.Base.NamedError("Clipperz.Crypto.AES.exception.UnsupportedKeySize")
+};
diff --git a/frontend/beta/js/Clipperz/Crypto/Base.js b/frontend/beta/js/Clipperz/Crypto/Base.js
new file mode 100644
index 0000000..b69dcc8
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/Crypto/Base.js
@@ -0,0 +1,1852 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+try { if (typeof(Clipperz.Base) == 'undefined') { throw ""; }} catch (e) {
+ throw "Clipperz.Crypto.Base depends on Clipperz.Base!";
+}
+
+if (typeof(Clipperz.Crypto) == 'undefined') { Clipperz.Crypto = {}; }
+if (typeof(Clipperz.Crypto.Base) == 'undefined') { Clipperz.Crypto.Base = {}; }
+
+Clipperz.Crypto.Base.VERSION = "0.1";
+Clipperz.Crypto.Base.NAME = "Clipperz.Crypto.Base";
+
+//#############################################################################
+// Downloaded on March 30, 2006 from http://anmar.eu.org/projects/jssha2/files/jssha2-0.3.zip (jsSha2/sha256.js)
+//#############################################################################
+
+/* A JavaScript implementation of the Secure Hash Algorithm, SHA-256
+ * Version 0.3 Copyright Angel Marin 2003-2004 - http://anmar.eu.org/
+ * Distributed under the BSD License
+ * Some bits taken from Paul Johnston's SHA-1 implementation
+ */
+var chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode */
+function safe_add (x, y) {
+ var lsw = (x & 0xFFFF) + (y & 0xFFFF);
+ var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
+ return (msw << 16) | (lsw & 0xFFFF);
+}
+function S (X, n) {return ( X >>> n ) | (X << (32 - n));}
+function R (X, n) {return ( X >>> n );}
+function Ch(x, y, z) {return ((x & y) ^ ((~x) & z));}
+function Maj(x, y, z) {return ((x & y) ^ (x & z) ^ (y & z));}
+function Sigma0256(x) {return (S(x, 2) ^ S(x, 13) ^ S(x, 22));}
+function Sigma1256(x) {return (S(x, 6) ^ S(x, 11) ^ S(x, 25));}
+function Gamma0256(x) {return (S(x, 7) ^ S(x, 18) ^ R(x, 3));}
+function Gamma1256(x) {return (S(x, 17) ^ S(x, 19) ^ R(x, 10));}
+function core_sha256 (m, l) {
+ var K = new Array(0x428A2F98,0x71374491,0xB5C0FBCF,0xE9B5DBA5,0x3956C25B,0x59F111F1,0x923F82A4,0xAB1C5ED5,0xD807AA98,0x12835B01,0x243185BE,0x550C7DC3,0x72BE5D74,0x80DEB1FE,0x9BDC06A7,0xC19BF174,0xE49B69C1,0xEFBE4786,0xFC19DC6,0x240CA1CC,0x2DE92C6F,0x4A7484AA,0x5CB0A9DC,0x76F988DA,0x983E5152,0xA831C66D,0xB00327C8,0xBF597FC7,0xC6E00BF3,0xD5A79147,0x6CA6351,0x14292967,0x27B70A85,0x2E1B2138,0x4D2C6DFC,0x53380D13,0x650A7354,0x766A0ABB,0x81C2C92E,0x92722C85,0xA2BFE8A1,0xA81A664B,0xC24B8B70,0xC76C51A3,0xD192E819,0xD6990624,0xF40E3585,0x106AA070,0x19A4C116,0x1E376C08,0x2748774C,0x34B0BCB5,0x391C0CB3,0x4ED8AA4A,0x5B9CCA4F,0x682E6FF3,0x748F82EE,0x78A5636F,0x84C87814,0x8CC70208,0x90BEFFFA,0xA4506CEB,0xBEF9A3F7,0xC67178F2);
+ var HASH = new Array(0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19);
+ var W = new Array(64);
+ var a, b, c, d, e, f, g, h, i, j;
+ var T1, T2;
+ /* append padding */
+ m[l >> 5] |= 0x80 << (24 - l % 32);
+ m[((l + 64 >> 9) << 4) + 15] = l;
+ for ( var i = 0; i<m.length; i+=16 ) {
+ a = HASH[0]; b = HASH[1]; c = HASH[2]; d = HASH[3]; e = HASH[4]; f = HASH[5]; g = HASH[6]; h = HASH[7];
+ for ( var j = 0; j<64; j++) {
+ if (j < 16) W[j] = m[j + i];
+ else W[j] = safe_add(safe_add(safe_add(Gamma1256(W[j - 2]), W[j - 7]), Gamma0256(W[j - 15])), W[j - 16]);
+ T1 = safe_add(safe_add(safe_add(safe_add(h, Sigma1256(e)), Ch(e, f, g)), K[j]), W[j]);
+ T2 = safe_add(Sigma0256(a), Maj(a, b, c));
+ h = g; g = f; f = e; e = safe_add(d, T1); d = c; c = b; b = a; a = safe_add(T1, T2);
+ }
+ HASH[0] = safe_add(a, HASH[0]); HASH[1] = safe_add(b, HASH[1]); HASH[2] = safe_add(c, HASH[2]); HASH[3] = safe_add(d, HASH[3]); HASH[4] = safe_add(e, HASH[4]); HASH[5] = safe_add(f, HASH[5]); HASH[6] = safe_add(g, HASH[6]); HASH[7] = safe_add(h, HASH[7]);
+ }
+ return HASH;
+}
+function str2binb (str) {
+ var bin = Array();
+ var mask = (1 << chrsz) - 1;
+ for(var i = 0; i < str.length * chrsz; i += chrsz)
+ bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (24 - i%32);
+ return bin;
+}
+function binb2hex (binarray) {
+ var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */
+ var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
+ var str = "";
+ for (var i = 0; i < binarray.length * 4; i++) {
+ str += hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF) + hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8 )) & 0xF);
+ }
+ return str;
+}
+function hex_sha256(s){return binb2hex(core_sha256(str2binb(s),s.length * chrsz));}
+
+
+
+//#############################################################################
+// Downloaded on March 30, 2006 from http://www.fourmilab.ch/javascrypt/javascrypt.zip (entropy.js)
+//#############################################################################
+
+ // Entropy collection utilities
+
+ /* Start by declaring static storage and initialise
+ the entropy vector from the time we come through
+ here. */
+
+ var entropyData = new Array(); // Collected entropy data
+ var edlen = 0; // Keyboard array data length
+
+ addEntropyTime(); // Start entropy collection with page load time
+ ce(); // Roll milliseconds into initial entropy
+
+ // Add a byte to the entropy vector
+
+ function addEntropyByte(b) {
+ entropyData[edlen++] = b;
+ }
+
+ /* Capture entropy. When the user presses a key or performs
+ various other events for which we can request
+ notification, add the time in 255ths of a second to the
+ entropyData array. The name of the function is short
+ so it doesn't bloat the form object declarations in
+ which it appears in various "onXXX" events. */
+
+ function ce() {
+ addEntropyByte(Math.floor((((new Date).getMilliseconds()) * 255) / 999));
+ }
+
+ // Add a 32 bit quantity to the entropy vector
+
+ function addEntropy32(w) {
+ var i;
+
+ for (i = 0; i < 4; i++) {
+ addEntropyByte(w & 0xFF);
+ w >>= 8;
+ }
+ }
+
+ /* Add the current time and date (milliseconds since the epoch,
+ truncated to 32 bits) to the entropy vector. */
+
+ function addEntropyTime() {
+ addEntropy32((new Date()).getTime());
+ }
+
+ /* Start collection of entropy from mouse movements. The
+ argument specifies the number of entropy items to be
+ obtained from mouse motion, after which mouse motion
+ will be ignored. Note that you can re-enable mouse
+ motion collection at any time if not already underway. */
+
+ var mouseMotionCollect = 0;
+ var oldMoveHandler; // For saving and restoring mouse move handler in IE4
+
+ function mouseMotionEntropy(maxsamp) {
+ if (mouseMotionCollect <= 0) {
+ mouseMotionCollect = maxsamp;
+ if ((document.implementation.hasFeature("Events", "2.0")) &&
+ document.addEventListener) {
+ // Browser supports Document Object Model (DOM) 2 events
+ document.addEventListener("mousemove", mouseMoveEntropy, false);
+ } else {
+ if (document.attachEvent) {
+ // Internet Explorer 5 and above event model
+ document.attachEvent("onmousemove", mouseMoveEntropy);
+ } else {
+ // Internet Explorer 4 event model
+ oldMoveHandler = document.onmousemove;
+ document.onmousemove = mouseMoveEntropy;
+ }
+ }
+//dump("Mouse enable", mouseMotionCollect);
+ }
+ }
+
+ /* Collect entropy from mouse motion events. Note that
+ this is craftily coded to work with either DOM2 or Internet
+ Explorer style events. Note that we don't use every successive
+ mouse movement event. Instead, we XOR the three bytes collected
+ from the mouse and use that to determine how many subsequent
+ mouse movements we ignore before capturing the next one. */
+
+ var mouseEntropyTime = 0; // Delay counter for mouse entropy collection
+
+ function mouseMoveEntropy(e) {
+ if (!e) {
+ e = window.event; // Internet Explorer event model
+ }
+ if (mouseMotionCollect > 0) {
+ if (mouseEntropyTime-- <= 0) {
+ addEntropyByte(e.screenX & 0xFF);
+ addEntropyByte(e.screenY & 0xFF);
+ ce();
+ mouseMotionCollect--;
+ mouseEntropyTime = (entropyData[edlen - 3] ^ entropyData[edlen - 2] ^
+ entropyData[edlen - 1]) % 19;
+//dump("Mouse Move", byteArrayToHex(entropyData.slice(-3)));
+ }
+ if (mouseMotionCollect <= 0) {
+ if (document.removeEventListener) {
+ document.removeEventListener("mousemove", mouseMoveEntropy, false);
+ } else if (document.detachEvent) {
+ document.detachEvent("onmousemove", mouseMoveEntropy);
+ } else {
+ document.onmousemove = oldMoveHandler;
+ }
+//dump("Spung!", 0);
+ }
+ }
+ }
+
+ /* Compute a 32 byte key value from the entropy vector.
+ We compute the value by taking the MD5 sum of the even
+ and odd bytes respectively of the entropy vector, then
+ concatenating the two MD5 sums. */
+
+ function keyFromEntropy() {
+ var i, k = new Array(32);
+
+ if (edlen == 0) {
+ alert("Blooie! Entropy vector void at call to keyFromEntropy.");
+ }
+//dump("Entropy bytes", edlen);
+
+ md5_init();
+ for (i = 0; i < edlen; i += 2) {
+ md5_update(entropyData[i]);
+ }
+ md5_finish();
+ for (i = 0; i < 16; i++) {
+ k[i] = digestBits[i];
+ }
+
+ md5_init();
+ for (i = 1; i < edlen; i += 2) {
+ md5_update(entropyData[i]);
+ }
+ md5_finish();
+ for (i = 0; i < 16; i++) {
+ k[i + 16] = digestBits[i];
+ }
+
+//dump("keyFromEntropy", byteArrayToHex(k));
+ return k;
+ }
+
+//#############################################################################
+// Downloaded on March 30, 2006 from http://www.fourmilab.ch/javascrypt/javascrypt.zip (aesprng.js)
+//#############################################################################
+
+
+ // AES based pseudorandom number generator
+
+ /* Constructor. Called with an array of 32 byte (0-255) values
+ containing the initial seed. */
+
+ function AESprng(seed) {
+ this.key = new Array();
+ this.key = seed;
+ this.itext = hexToByteArray("9F489613248148F9C27945C6AE62EECA3E3367BB14064E4E6DC67A9F28AB3BD1");
+ this.nbytes = 0; // Bytes left in buffer
+
+ this.next = AESprng_next;
+ this.nextbits = AESprng_nextbits;
+ this.nextInt = AESprng_nextInt;
+ this.round = AESprng_round;
+
+ /* Encrypt the initial text with the seed key
+ three times, feeding the output of the encryption
+ back into the key for the next round. */
+
+ bsb = blockSizeInBits;
+ blockSizeInBits = 256;
+ var i, ct;
+ for (i = 0; i < 3; i++) {
+ this.key = rijndaelEncrypt(this.itext, this.key, "ECB");
+ }
+
+ /* Now make between one and four additional
+ key-feedback rounds, with the number determined
+ by bits from the result of the first three
+ rounds. */
+
+ var n = 1 + (this.key[3] & 2) + (this.key[9] & 1);
+ for (i = 0; i < n; i++) {
+ this.key = rijndaelEncrypt(this.itext, this.key, "ECB");
+ }
+ blockSizeInBits = bsb;
+ }
+
+ function AESprng_round() {
+ bsb = blockSizeInBits;
+ blockSizeInBits = 256;
+ this.key = rijndaelEncrypt(this.itext, this.key, "ECB");
+ this.nbytes = 32;
+ blockSizeInBits = bsb;
+ }
+
+ // Return next byte from the generator
+
+ function AESprng_next() {
+ if (this.nbytes <= 0) {
+ this.round();
+ }
+ return(this.key[--this.nbytes]);
+ }
+
+ // Return n bit integer value (up to maximum integer size)
+
+ function AESprng_nextbits(n) {
+ var i, w = 0, nbytes = Math.floor((n + 7) / 8);
+
+ for (i = 0; i < nbytes; i++) {
+ w = (w << 8) | this.next();
+ }
+ return w & ((1 << n) - 1);
+ }
+
+ // Return integer between 0 and n inclusive
+
+ function AESprng_nextInt(n) {
+ var p = 1, nb = 0;
+
+ // Determine smallest p, 2^p > n
+ // nb = log_2 p
+
+ while (n >= p) {
+ p <<= 1;
+ nb++;
+ }
+ p--;
+
+ /* Generate values from 0 through n by first generating
+ values v from 0 to (2^p)-1, then discarding any results v > n.
+ For the rationale behind this (and why taking
+ values mod (n + 1) is biased toward smaller values, see
+ Ferguson and Schneier, "Practical Cryptography",
+ ISBN 0-471-22357-3, section 10.8). */
+
+ while (true) {
+ var v = this.nextbits(nb) & p;
+
+ if (v <= n) {
+ return v;
+ }
+ }
+ }
+
+//#############################################################################
+// Downloaded on March 30, 2006 from http://www.fourmilab.ch/javascrypt/javascrypt.zip (md5.js)
+//#############################################################################
+
+/*
+ * md5.jvs 1.0b 27/06/96
+ *
+ * Javascript implementation of the RSA Data Security, Inc. MD5
+ * Message-Digest Algorithm.
+ *
+ * Copyright (c) 1996 Henri Torgemane. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * and its documentation for any purposes and without
+ * fee is hereby granted provided that this copyright notice
+ * appears in all copies.
+ *
+ * Of course, this soft is provided "as is" without express or implied
+ * warranty of any kind.
+
+ This version contains some trivial reformatting modifications
+ by John Walker.
+
+ */
+
+function array(n) {
+ for (i = 0; i < n; i++) {
+ this[i] = 0;
+ }
+ this.length = n;
+}
+
+/* Some basic logical functions had to be rewritten because of a bug in
+ * Javascript.. Just try to compute 0xffffffff >> 4 with it..
+ * Of course, these functions are slower than the original would be, but
+ * at least, they work!
+ */
+
+function integer(n) {
+ return n % (0xffffffff + 1);
+}
+
+function shr(a, b) {
+ a = integer(a);
+ b = integer(b);
+ if (a - 0x80000000 >= 0) {
+ a = a % 0x80000000;
+ a >>= b;
+ a += 0x40000000 >> (b - 1);
+ } else {
+ a >>= b;
+ }
+ return a;
+}
+
+function shl1(a) {
+ a = a % 0x80000000;
+ if (a & 0x40000000 == 0x40000000) {
+ a -= 0x40000000;
+ a *= 2;
+ a += 0x80000000;
+ } else {
+ a *= 2;
+ }
+ return a;
+}
+
+function shl(a, b) {
+ a = integer(a);
+ b = integer(b);
+ for (var i = 0; i < b; i++) {
+ a = shl1(a);
+ }
+ return a;
+}
+
+function and(a, b) {
+ a = integer(a);
+ b = integer(b);
+ var t1 = a - 0x80000000;
+ var t2 = b - 0x80000000;
+ if (t1 >= 0) {
+ if (t2 >= 0) {
+ return ((t1 & t2) + 0x80000000);
+ } else {
+ return (t1 & b);
+ }
+ } else {
+ if (t2 >= 0) {
+ return (a & t2);
+ } else {
+ return (a & b);
+ }
+ }
+}
+
+function or(a, b) {
+ a = integer(a);
+ b = integer(b);
+ var t1 = a - 0x80000000;
+ var t2 = b - 0x80000000;
+ if (t1 >= 0) {
+ if (t2 >= 0) {
+ return ((t1 | t2) + 0x80000000);
+ } else {
+ return ((t1 | b) + 0x80000000);
+ }
+ } else {
+ if (t2 >= 0) {
+ return ((a | t2) + 0x80000000);
+ } else {
+ return (a | b);
+ }
+ }
+}
+
+function xor(a, b) {
+ a = integer(a);
+ b = integer(b);
+ var t1 = a - 0x80000000;
+ var t2 = b - 0x80000000;
+ if (t1 >= 0) {
+ if (t2 >= 0) {
+ return (t1 ^ t2);
+ } else {
+ return ((t1 ^ b) + 0x80000000);
+ }
+ } else {
+ if (t2 >= 0) {
+ return ((a ^ t2) + 0x80000000);
+ } else {
+ return (a ^ b);
+ }
+ }
+}
+
+function not(a) {
+ a = integer(a);
+ return 0xffffffff - a;
+}
+
+/* Here begin the real algorithm */
+
+var state = new array(4);
+var count = new array(2);
+ count[0] = 0;
+ count[1] = 0;
+var buffer = new array(64);
+var transformBuffer = new array(16);
+var digestBits = new array(16);
+
+var S11 = 7;
+var S12 = 12;
+var S13 = 17;
+var S14 = 22;
+var S21 = 5;
+var S22 = 9;
+var S23 = 14;
+var S24 = 20;
+var S31 = 4;
+var S32 = 11;
+var S33 = 16;
+var S34 = 23;
+var S41 = 6;
+var S42 = 10;
+var S43 = 15;
+var S44 = 21;
+
+function F(x, y, z) {
+ return or(and(x, y), and(not(x), z));
+}
+
+function G(x, y, z) {
+ return or(and(x, z), and(y, not(z)));
+}
+
+function H(x, y, z) {
+ return xor(xor(x, y), z);
+}
+
+function I(x, y, z) {
+ return xor(y ,or(x , not(z)));
+}
+
+function rotateLeft(a, n) {
+ return or(shl(a, n), (shr(a, (32 - n))));
+}
+
+function FF(a, b, c, d, x, s, ac) {
+ a = a + F(b, c, d) + x + ac;
+ a = rotateLeft(a, s);
+ a = a + b;
+ return a;
+}
+
+function GG(a, b, c, d, x, s, ac) {
+ a = a + G(b, c, d) + x + ac;
+ a = rotateLeft(a, s);
+ a = a + b;
+ return a;
+}
+
+function HH(a, b, c, d, x, s, ac) {
+ a = a + H(b, c, d) + x + ac;
+ a = rotateLeft(a, s);
+ a = a + b;
+ return a;
+}
+
+function II(a, b, c, d, x, s, ac) {
+ a = a + I(b, c, d) + x + ac;
+ a = rotateLeft(a, s);
+ a = a + b;
+ return a;
+}
+
+function transform(buf, offset) {
+ var a = 0, b = 0, c = 0, d = 0;
+ var x = transformBuffer;
+
+ a = state[0];
+ b = state[1];
+ c = state[2];
+ d = state[3];
+
+ for (i = 0; i < 16; i++) {
+ x[i] = and(buf[i * 4 + offset], 0xFF);
+ for (j = 1; j < 4; j++) {
+ x[i] += shl(and(buf[i * 4 + j + offset] ,0xFF), j * 8);
+ }
+ }
+
+ /* Round 1 */
+ a = FF( a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
+ d = FF( d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
+ c = FF( c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
+ b = FF( b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
+ a = FF( a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
+ d = FF( d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
+ c = FF( c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
+ b = FF( b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
+ a = FF( a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
+ d = FF( d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
+ c = FF( c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
+ b = FF( b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
+ a = FF( a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
+ d = FF( d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
+ c = FF( c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
+ b = FF( b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
+
+ /* Round 2 */
+ a = GG( a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
+ d = GG( d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
+ c = GG( c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
+ b = GG( b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
+ a = GG( a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
+ d = GG( d, a, b, c, x[10], S22, 0x2441453); /* 22 */
+ c = GG( c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
+ b = GG( b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
+ a = GG( a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
+ d = GG( d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
+ c = GG( c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
+ b = GG( b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
+ a = GG( a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
+ d = GG( d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
+ c = GG( c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
+ b = GG( b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
+
+ /* Round 3 */
+ a = HH( a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
+ d = HH( d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
+ c = HH( c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
+ b = HH( b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
+ a = HH( a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
+ d = HH( d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
+ c = HH( c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
+ b = HH( b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
+ a = HH( a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
+ d = HH( d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
+ c = HH( c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
+ b = HH( b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
+ a = HH( a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
+ d = HH( d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
+ c = HH( c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
+ b = HH( b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
+
+ /* Round 4 */
+ a = II( a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
+ d = II( d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
+ c = II( c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
+ b = II( b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
+ a = II( a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
+ d = II( d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
+ c = II( c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
+ b = II( b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
+ a = II( a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
+ d = II( d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
+ c = II( c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
+ b = II( b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
+ a = II( a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
+ d = II( d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
+ c = II( c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
+ b = II( b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
+
+ state[0] += a;
+ state[1] += b;
+ state[2] += c;
+ state[3] += d;
+
+}
+
+function md5_init() {
+ count[0] = count[1] = 0;
+ state[0] = 0x67452301;
+ state[1] = 0xefcdab89;
+ state[2] = 0x98badcfe;
+ state[3] = 0x10325476;
+ for (i = 0; i < digestBits.length; i++) {
+ digestBits[i] = 0;
+ }
+}
+
+function md5_update(b) {
+ var index, i;
+
+ index = and(shr(count[0],3) , 0x3F);
+ if (count[0] < 0xFFFFFFFF - 7) {
+ count[0] += 8;
+ } else {
+ count[1]++;
+ count[0] -= 0xFFFFFFFF + 1;
+ count[0] += 8;
+ }
+ buffer[index] = and(b, 0xff);
+ if (index >= 63) {
+ transform(buffer, 0);
+ }
+}
+
+function md5_finish() {
+ var bits = new array(8);
+ var padding;
+ var i = 0, index = 0, padLen = 0;
+
+ for (i = 0; i < 4; i++) {
+ bits[i] = and(shr(count[0], (i * 8)), 0xFF);
+ }
+ for (i = 0; i < 4; i++) {
+ bits[i + 4] = and(shr(count[1], (i * 8)), 0xFF);
+ }
+ index = and(shr(count[0], 3), 0x3F);
+ padLen = (index < 56) ? (56 - index) : (120 - index);
+ padding = new array(64);
+ padding[0] = 0x80;
+ for (i = 0; i < padLen; i++) {
+ md5_update(padding[i]);
+ }
+ for (i = 0; i < 8; i++) {
+ md5_update(bits[i]);
+ }
+
+ for (i = 0; i < 4; i++) {
+ for (j = 0; j < 4; j++) {
+ digestBits[i * 4 + j] = and(shr(state[i], (j * 8)) , 0xFF);
+ }
+ }
+}
+
+/* End of the MD5 algorithm */
+
+//#############################################################################
+// Downloaded on March 30, 2006 from http://www.fourmilab.ch/javascrypt/javascrypt.zip (aes.js)
+//#############################################################################
+
+
+/* rijndael.js Rijndael Reference Implementation
+
+ This is a modified version of the software described below,
+ produced in September 2003 by John Walker for use in the
+ JavsScrypt browser-based encryption package. The principal
+ changes are replacing the original getRandomBytes function with
+ one which calls our pseudorandom generator (which must
+ be instantiated and seeded before the first call on getRandomBytes),
+ and changing keySizeInBits to 256. Some code not required by the
+ JavsScrypt application has been commented out. Please see
+ http://www.fourmilab.ch/javascrypt/ for further information on
+ JavaScrypt.
+
+ The following is the original copyright and application
+ information.
+
+ Copyright (c) 2001 Fritz Schneider
+
+ This software is provided as-is, without express or implied warranty.
+ Permission to use, copy, modify, distribute or sell this software, with or
+ without fee, for any purpose and by any individual or organization, is hereby
+ granted, provided that the above copyright notice and this paragraph appear
+ in all copies. Distribution as a part of an application or binary must
+ include the above copyright notice in the documentation and/or other materials
+ provided with the application or distribution.
+
+ As the above disclaimer notes, you are free to use this code however you
+ want. However, I would request that you send me an email
+ (fritz /at/ cs /dot/ ucsd /dot/ edu) to say hi if you find this code useful
+ or instructional. Seeing that people are using the code acts as
+ encouragement for me to continue development. If you *really* want to thank
+ me you can buy the book I wrote with Thomas Powell, _JavaScript:
+ _The_Complete_Reference_ :)
+
+ This code is an UNOPTIMIZED REFERENCE implementation of Rijndael.
+ If there is sufficient interest I can write an optimized (word-based,
+ table-driven) version, although you might want to consider using a
+ compiled language if speed is critical to your application. As it stands,
+ one run of the monte carlo test (10,000 encryptions) can take up to
+ several minutes, depending upon your processor. You shouldn't expect more
+ than a few kilobytes per second in throughput.
+
+ Also note that there is very little error checking in these functions.
+ Doing proper error checking is always a good idea, but the ideal
+ implementation (using the instanceof operator and exceptions) requires
+ IE5+/NS6+, and I've chosen to implement this code so that it is compatible
+ with IE4/NS4.
+
+ And finally, because JavaScript doesn't have an explicit byte/char data
+ type (although JavaScript 2.0 most likely will), when I refer to "byte"
+ in this code I generally mean "32 bit integer with value in the interval
+ [0,255]" which I treat as a byte.
+
+ See http://www-cse.ucsd.edu/~fritz/rijndael.html for more documentation
+ of the (very simple) API provided by this code.
+
+ Fritz Schneider
+ fritz at cs.ucsd.edu
+
+*/
+
+
+// Rijndael parameters -- Valid values are 128, 192, or 256
+
+var keySizeInBits = 256;
+var blockSizeInBits = 128;
+
+//
+// Note: in the following code the two dimensional arrays are indexed as
+// you would probably expect, as array[row][column]. The state arrays
+// are 2d arrays of the form state[4][Nb].
+
+
+// The number of rounds for the cipher, indexed by [Nk][Nb]
+var roundsArray = [ ,,,,[,,,,10,, 12,, 14],,
+ [,,,,12,, 12,, 14],,
+ [,,,,14,, 14,, 14] ];
+
+// The number of bytes to shift by in shiftRow, indexed by [Nb][row]
+var shiftOffsets = [ ,,,,[,1, 2, 3],,[,1, 2, 3],,[,1, 3, 4] ];
+
+// The round constants used in subkey expansion
+var Rcon = [
+0x01, 0x02, 0x04, 0x08, 0x10, 0x20,
+0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8,
+0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc,
+0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4,
+0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91 ];
+
+// Precomputed lookup table for the SBox
+var SBox = [
+ 99, 124, 119, 123, 242, 107, 111, 197, 48, 1, 103, 43, 254, 215, 171,
+118, 202, 130, 201, 125, 250, 89, 71, 240, 173, 212, 162, 175, 156, 164,
+114, 192, 183, 253, 147, 38, 54, 63, 247, 204, 52, 165, 229, 241, 113,
+216, 49, 21, 4, 199, 35, 195, 24, 150, 5, 154, 7, 18, 128, 226,
+235, 39, 178, 117, 9, 131, 44, 26, 27, 110, 90, 160, 82, 59, 214,
+179, 41, 227, 47, 132, 83, 209, 0, 237, 32, 252, 177, 91, 106, 203,
+190, 57, 74, 76, 88, 207, 208, 239, 170, 251, 67, 77, 51, 133, 69,
+249, 2, 127, 80, 60, 159, 168, 81, 163, 64, 143, 146, 157, 56, 245,
+188, 182, 218, 33, 16, 255, 243, 210, 205, 12, 19, 236, 95, 151, 68,
+23, 196, 167, 126, 61, 100, 93, 25, 115, 96, 129, 79, 220, 34, 42,
+144, 136, 70, 238, 184, 20, 222, 94, 11, 219, 224, 50, 58, 10, 73,
+ 6, 36, 92, 194, 211, 172, 98, 145, 149, 228, 121, 231, 200, 55, 109,
+141, 213, 78, 169, 108, 86, 244, 234, 101, 122, 174, 8, 186, 120, 37,
+ 46, 28, 166, 180, 198, 232, 221, 116, 31, 75, 189, 139, 138, 112, 62,
+181, 102, 72, 3, 246, 14, 97, 53, 87, 185, 134, 193, 29, 158, 225,
+248, 152, 17, 105, 217, 142, 148, 155, 30, 135, 233, 206, 85, 40, 223,
+140, 161, 137, 13, 191, 230, 66, 104, 65, 153, 45, 15, 176, 84, 187,
+ 22 ];
+
+// Precomputed lookup table for the inverse SBox
+var SBoxInverse = [
+ 82, 9, 106, 213, 48, 54, 165, 56, 191, 64, 163, 158, 129, 243, 215,
+251, 124, 227, 57, 130, 155, 47, 255, 135, 52, 142, 67, 68, 196, 222,
+233, 203, 84, 123, 148, 50, 166, 194, 35, 61, 238, 76, 149, 11, 66,
+250, 195, 78, 8, 46, 161, 102, 40, 217, 36, 178, 118, 91, 162, 73,
+109, 139, 209, 37, 114, 248, 246, 100, 134, 104, 152, 22, 212, 164, 92,
+204, 93, 101, 182, 146, 108, 112, 72, 80, 253, 237, 185, 218, 94, 21,
+ 70, 87, 167, 141, 157, 132, 144, 216, 171, 0, 140, 188, 211, 10, 247,
+228, 88, 5, 184, 179, 69, 6, 208, 44, 30, 143, 202, 63, 15, 2,
+193, 175, 189, 3, 1, 19, 138, 107, 58, 145, 17, 65, 79, 103, 220,
+234, 151, 242, 207, 206, 240, 180, 230, 115, 150, 172, 116, 34, 231, 173,
+ 53, 133, 226, 249, 55, 232, 28, 117, 223, 110, 71, 241, 26, 113, 29,
+ 41, 197, 137, 111, 183, 98, 14, 170, 24, 190, 27, 252, 86, 62, 75,
+198, 210, 121, 32, 154, 219, 192, 254, 120, 205, 90, 244, 31, 221, 168,
+ 51, 136, 7, 199, 49, 177, 18, 16, 89, 39, 128, 236, 95, 96, 81,
+127, 169, 25, 181, 74, 13, 45, 229, 122, 159, 147, 201, 156, 239, 160,
+224, 59, 77, 174, 42, 245, 176, 200, 235, 187, 60, 131, 83, 153, 97,
+ 23, 43, 4, 126, 186, 119, 214, 38, 225, 105, 20, 99, 85, 33, 12,
+125 ];
+
+// This method circularly shifts the array left by the number of elements
+// given in its parameter. It returns the resulting array and is used for
+// the ShiftRow step. Note that shift() and push() could be used for a more
+// elegant solution, but they require IE5.5+, so I chose to do it manually.
+
+function cyclicShiftLeft(theArray, positions) {
+ var temp = theArray.slice(0, positions);
+ theArray = theArray.slice(positions).concat(temp);
+ return theArray;
+}
+
+// Cipher parameters ... do not change these
+var Nk = keySizeInBits / 32;
+var Nb = blockSizeInBits / 32;
+var Nr = roundsArray[Nk][Nb];
+
+// Multiplies the element "poly" of GF(2^8) by x. See the Rijndael spec.
+
+function xtime(poly) {
+ poly <<= 1;
+ return ((poly & 0x100) ? (poly ^ 0x11B) : (poly));
+}
+
+// Multiplies the two elements of GF(2^8) together and returns the result.
+// See the Rijndael spec, but should be straightforward: for each power of
+// the indeterminant that has a 1 coefficient in x, add y times that power
+// to the result. x and y should be bytes representing elements of GF(2^8)
+
+function mult_GF256(x, y) {
+ var bit, result = 0;
+
+ for (bit = 1; bit < 256; bit *= 2, y = xtime(y)) {
+ if (x & bit)
+ result ^= y;
+ }
+ return result;
+}
+
+// Performs the substitution step of the cipher. State is the 2d array of
+// state information (see spec) and direction is string indicating whether
+// we are performing the forward substitution ("encrypt") or inverse
+// substitution (anything else)
+
+function byteSub(state, direction) {
+ var S;
+ if (direction == "encrypt") // Point S to the SBox we're using
+ S = SBox;
+ else
+ S = SBoxInverse;
+ for (var i = 0; i < 4; i++) // Substitute for every byte in state
+ for (var j = 0; j < Nb; j++)
+ state[i][j] = S[state[i][j]];
+}
+
+// Performs the row shifting step of the cipher.
+
+function shiftRow(state, direction) {
+ for (var i=1; i<4; i++) // Row 0 never shifts
+ if (direction == "encrypt")
+ state[i] = cyclicShiftLeft(state[i], shiftOffsets[Nb][i]);
+ else
+ state[i] = cyclicShiftLeft(state[i], Nb - shiftOffsets[Nb][i]);
+
+}
+
+// Performs the column mixing step of the cipher. Most of these steps can
+// be combined into table lookups on 32bit values (at least for encryption)
+// to greatly increase the speed.
+
+function mixColumn(state, direction) {
+ var b = []; // Result of matrix multiplications
+ for (var j = 0; j < Nb; j++) { // Go through each column...
+ for (var i = 0; i < 4; i++) { // and for each row in the column...
+ if (direction == "encrypt")
+ b[i] = mult_GF256(state[i][j], 2) ^ // perform mixing
+ mult_GF256(state[(i+1)%4][j], 3) ^
+ state[(i+2)%4][j] ^
+ state[(i+3)%4][j];
+ else
+ b[i] = mult_GF256(state[i][j], 0xE) ^
+ mult_GF256(state[(i+1)%4][j], 0xB) ^
+ mult_GF256(state[(i+2)%4][j], 0xD) ^
+ mult_GF256(state[(i+3)%4][j], 9);
+ }
+ for (var i = 0; i < 4; i++) // Place result back into column
+ state[i][j] = b[i];
+ }
+}
+
+// Adds the current round key to the state information. Straightforward.
+
+function addRoundKey(state, roundKey) {
+ for (var j = 0; j < Nb; j++) { // Step through columns...
+ state[0][j] ^= (roundKey[j] & 0xFF); // and XOR
+ state[1][j] ^= ((roundKey[j]>>8) & 0xFF);
+ state[2][j] ^= ((roundKey[j]>>16) & 0xFF);
+ state[3][j] ^= ((roundKey[j]>>24) & 0xFF);
+ }
+}
+
+// This function creates the expanded key from the input (128/192/256-bit)
+// key. The parameter key is an array of bytes holding the value of the key.
+// The returned value is an array whose elements are the 32-bit words that
+// make up the expanded key.
+
+function keyExpansion(key) {
+ var expandedKey = new Array();
+ var temp;
+
+ // in case the key size or parameters were changed...
+ Nk = keySizeInBits / 32;
+ Nb = blockSizeInBits / 32;
+ Nr = roundsArray[Nk][Nb];
+
+ for (var j=0; j < Nk; j++) // Fill in input key first
+ expandedKey[j] =
+ (key[4*j]) | (key[4*j+1]<<8) | (key[4*j+2]<<16) | (key[4*j+3]<<24);
+
+ // Now walk down the rest of the array filling in expanded key bytes as
+ // per Rijndael's spec
+ for (j = Nk; j < Nb * (Nr + 1); j++) { // For each word of expanded key
+ temp = expandedKey[j - 1];
+ if (j % Nk == 0)
+ temp = ( (SBox[(temp>>8) & 0xFF]) |
+ (SBox[(temp>>16) & 0xFF]<<8) |
+ (SBox[(temp>>24) & 0xFF]<<16) |
+ (SBox[temp & 0xFF]<<24) ) ^ Rcon[Math.floor(j / Nk) - 1];
+ else if (Nk > 6 && j % Nk == 4)
+ temp = (SBox[(temp>>24) & 0xFF]<<24) |
+ (SBox[(temp>>16) & 0xFF]<<16) |
+ (SBox[(temp>>8) & 0xFF]<<8) |
+ (SBox[temp & 0xFF]);
+ expandedKey[j] = expandedKey[j-Nk] ^ temp;
+ }
+ return expandedKey;
+}
+
+// Rijndael's round functions...
+
+function Round(state, roundKey) {
+ byteSub(state, "encrypt");
+ shiftRow(state, "encrypt");
+ mixColumn(state, "encrypt");
+ addRoundKey(state, roundKey);
+}
+
+function InverseRound(state, roundKey) {
+ addRoundKey(state, roundKey);
+ mixColumn(state, "decrypt");
+ shiftRow(state, "decrypt");
+ byteSub(state, "decrypt");
+}
+
+function FinalRound(state, roundKey) {
+ byteSub(state, "encrypt");
+ shiftRow(state, "encrypt");
+ addRoundKey(state, roundKey);
+}
+
+function InverseFinalRound(state, roundKey){
+ addRoundKey(state, roundKey);
+ shiftRow(state, "decrypt");
+ byteSub(state, "decrypt");
+}
+
+// encrypt is the basic encryption function. It takes parameters
+// block, an array of bytes representing a plaintext block, and expandedKey,
+// an array of words representing the expanded key previously returned by
+// keyExpansion(). The ciphertext block is returned as an array of bytes.
+
+function encrypt(block, expandedKey) {
+ var i;
+ if (!block || block.length*8 != blockSizeInBits)
+ return;
+ if (!expandedKey)
+ return;
+
+ block = packBytes(block);
+ addRoundKey(block, expandedKey);
+ for (i=1; i<Nr; i++)
+ Round(block, expandedKey.slice(Nb*i, Nb*(i+1)));
+ FinalRound(block, expandedKey.slice(Nb*Nr));
+ return unpackBytes(block);
+}
+
+// decrypt is the basic decryption function. It takes parameters
+// block, an array of bytes representing a ciphertext block, and expandedKey,
+// an array of words representing the expanded key previously returned by
+// keyExpansion(). The decrypted block is returned as an array of bytes.
+
+function decrypt(block, expandedKey) {
+ var i;
+ if (!block || block.length*8 != blockSizeInBits)
+ return;
+ if (!expandedKey)
+ return;
+
+ block = packBytes(block);
+ InverseFinalRound(block, expandedKey.slice(Nb*Nr));
+ for (i = Nr - 1; i>0; i--)
+ InverseRound(block, expandedKey.slice(Nb*i, Nb*(i+1)));
+ addRoundKey(block, expandedKey);
+ return unpackBytes(block);
+}
+
+/* !NEEDED
+// This method takes a byte array (byteArray) and converts it to a string by
+// applying String.fromCharCode() to each value and concatenating the result.
+// The resulting string is returned. Note that this function SKIPS zero bytes
+// under the assumption that they are padding added in formatPlaintext().
+// Obviously, do not invoke this method on raw data that can contain zero
+// bytes. It is really only appropriate for printable ASCII/Latin-1
+// values. Roll your own function for more robust functionality :)
+
+function byteArrayToString(byteArray) {
+ var result = "";
+ for(var i=0; i<byteArray.length; i++)
+ if (byteArray[i] != 0)
+ result += String.fromCharCode(byteArray[i]);
+ return result;
+}
+*/
+
+// This function takes an array of bytes (byteArray) and converts them
+// to a hexadecimal string. Array element 0 is found at the beginning of
+// the resulting string, high nibble first. Consecutive elements follow
+// similarly, for example [16, 255] --> "10ff". The function returns a
+// string.
+
+function byteArrayToHex(byteArray) {
+ var result = "";
+ if (!byteArray)
+ return;
+ for (var i=0; i<byteArray.length; i++)
+ result += ((byteArray[i]<16) ? "0" : "") + byteArray[i].toString(16);
+
+ return result;
+}
+
+// This function converts a string containing hexadecimal digits to an
+// array of bytes. The resulting byte array is filled in the order the
+// values occur in the string, for example "10FF" --> [16, 255]. This
+// function returns an array.
+
+function hexToByteArray(hexString) {
+ var byteArray = [];
+ if (hexString.length % 2) // must have even length
+ return;
+ if (hexString.indexOf("0x") == 0 || hexString.indexOf("0X") == 0)
+ hexString = hexString.substring(2);
+ for (var i = 0; i<hexString.length; i += 2)
+ byteArray[Math.floor(i/2)] = parseInt(hexString.slice(i, i+2), 16);
+ return byteArray;
+}
+
+// This function packs an array of bytes into the four row form defined by
+// Rijndael. It assumes the length of the array of bytes is divisible by
+// four. Bytes are filled in according to the Rijndael spec (starting with
+// column 0, row 0 to 3). This function returns a 2d array.
+
+function packBytes(octets) {
+ var state = new Array();
+ if (!octets || octets.length % 4)
+ return;
+
+ state[0] = new Array(); state[1] = new Array();
+ state[2] = new Array(); state[3] = new Array();
+ for (var j=0; j<octets.length; j+= 4) {
+ state[0][j/4] = octets[j];
+ state[1][j/4] = octets[j+1];
+ state[2][j/4] = octets[j+2];
+ state[3][j/4] = octets[j+3];
+ }
+ return state;
+}
+
+// This function unpacks an array of bytes from the four row format preferred
+// by Rijndael into a single 1d array of bytes. It assumes the input "packed"
+// is a packed array. Bytes are filled in according to the Rijndael spec.
+// This function returns a 1d array of bytes.
+
+function unpackBytes(packed) {
+ var result = new Array();
+ for (var j=0; j<packed[0].length; j++) {
+ result[result.length] = packed[0][j];
+ result[result.length] = packed[1][j];
+ result[result.length] = packed[2][j];
+ result[result.length] = packed[3][j];
+ }
+ return result;
+}
+
+// This function takes a prospective plaintext (string or array of bytes)
+// and pads it with pseudorandom bytes if its length is not a multiple of the block
+// size. If plaintext is a string, it is converted to an array of bytes
+// in the process. The type checking can be made much nicer using the
+// instanceof operator, but this operator is not available until IE5.0 so I
+// chose to use the heuristic below.
+
+function formatPlaintext(plaintext) {
+ var bpb = blockSizeInBits / 8; // bytes per block
+ var fillWithRandomBits;
+ var i;
+
+ // if primitive string or String instance
+ if ((!((typeof plaintext == "object") &&
+ ((typeof (plaintext[0])) == "number"))) &&
+ ((typeof plaintext == "string") || plaintext.indexOf))
+ {
+ plaintext = plaintext.split("");
+ // Unicode issues here (ignoring high byte)
+ for (i=0; i<plaintext.length; i++) {
+ plaintext[i] = plaintext[i].charCodeAt(0) & 0xFF;
+ }
+ }
+
+ i = plaintext.length % bpb;
+ if (i > 0) {
+//alert("adding " + (bpb - 1) + " bytes");
+// plaintext = plaintext.concat(getRandomBytes(bpb - i));
+ {
+ var paddingBytes;
+ var ii,cc;
+
+ paddingBytes = new Array();
+ cc = bpb - i;
+ for (ii=0; ii<cc; ii++) {
+ paddingBytes[ii] = cc;
+ }
+
+//is("cc", cc);
+//is(getRandomBytes(bpb - i) + "", paddingBytes + "");
+ plaintext = plaintext.concat(paddingBytes);
+ }
+ }
+
+ return plaintext;
+}
+
+// Returns an array containing "howMany" random bytes.
+
+function getRandomBytes(howMany) {
+ var i, bytes = new Array();
+
+//alert("getting some random bytes");
+ for (i = 0; i < howMany; i++) {
+ bytes[i] = prng.nextInt(255);
+ }
+ return bytes;
+}
+
+// rijndaelEncrypt(plaintext, key, mode)
+// Encrypts the plaintext using the given key and in the given mode.
+// The parameter "plaintext" can either be a string or an array of bytes.
+// The parameter "key" must be an array of key bytes. If you have a hex
+// string representing the key, invoke hexToByteArray() on it to convert it
+// to an array of bytes. The third parameter "mode" is a string indicating
+// the encryption mode to use, either "ECB" or "CBC". If the parameter is
+// omitted, ECB is assumed.
+//
+// An array of bytes representing the cihpertext is returned. To convert
+// this array to hex, invoke byteArrayToHex() on it.
+
+function rijndaelEncrypt(plaintext, key, mode) {
+ var expandedKey, i, aBlock;
+ var bpb = blockSizeInBits / 8; // bytes per block
+ var ct; // ciphertext
+
+ if (!plaintext || !key)
+ return;
+ if (key.length*8 != keySizeInBits)
+ return;
+ if (mode == "CBC") {
+ ct = getRandomBytes(bpb); // get IV
+//dump("IV", byteArrayToHex(ct));
+ } else {
+ mode = "ECB";
+ ct = new Array();
+ }
+
+ // convert plaintext to byte array and pad with zeros if necessary.
+ plaintext = formatPlaintext(plaintext);
+
+ expandedKey = keyExpansion(key);
+
+ for (var block = 0; block < plaintext.length / bpb; block++) {
+ aBlock = plaintext.slice(block * bpb, (block + 1) * bpb);
+ if (mode == "CBC") {
+ for (var i = 0; i < bpb; i++) {
+ aBlock[i] ^= ct[(block * bpb) + i];
+ }
+ }
+ ct = ct.concat(encrypt(aBlock, expandedKey));
+ }
+
+ return ct;
+}
+
+// rijndaelDecrypt(ciphertext, key, mode)
+// Decrypts the using the given key and mode. The parameter "ciphertext"
+// must be an array of bytes. The parameter "key" must be an array of key
+// bytes. If you have a hex string representing the ciphertext or key,
+// invoke hexToByteArray() on it to convert it to an array of bytes. The
+// parameter "mode" is a string, either "CBC" or "ECB".
+//
+// An array of bytes representing the plaintext is returned. To convert
+// this array to a hex string, invoke byteArrayToHex() on it. To convert it
+// to a string of characters, you can use byteArrayToString().
+
+function rijndaelDecrypt(ciphertext, key, mode) {
+ var expandedKey;
+ var bpb = blockSizeInBits / 8; // bytes per block
+ var pt = new Array(); // plaintext array
+ var aBlock; // a decrypted block
+ var block; // current block number
+
+ if (!ciphertext || !key || typeof ciphertext == "string")
+ return;
+ if (key.length*8 != keySizeInBits)
+ return;
+ if (!mode) {
+ mode = "ECB"; // assume ECB if mode omitted
+ }
+
+ expandedKey = keyExpansion(key);
+
+ // work backwards to accomodate CBC mode
+ for (block=(ciphertext.length / bpb)-1; block>0; block--) {
+ aBlock =
+ decrypt(ciphertext.slice(block*bpb,(block+1)*bpb), expandedKey);
+ if (mode == "CBC")
+ for (var i=0; i<bpb; i++)
+ pt[(block-1)*bpb + i] = aBlock[i] ^ ciphertext[(block-1)*bpb + i];
+ else
+ pt = aBlock.concat(pt);
+ }
+
+ // do last block if ECB (skips the IV in CBC)
+ if (mode == "ECB")
+ pt = decrypt(ciphertext.slice(0, bpb), expandedKey).concat(pt);
+
+ return pt;
+}
+
+//#############################################################################
+// Downloaded on March 30, 2006 from http://www.fourmilab.ch/javascrypt/javascrypt.zip (utf-8.js)
+//#############################################################################
+
+
+ /* Encoding and decoding of Unicode character strings as
+ UTF-8 byte streams. */
+
+ // UNICODE_TO_UTF8 -- Encode Unicode argument string as UTF-8 return value
+
+ function unicode_to_utf8(s) {
+ var utf8 = "";
+
+ for (var n = 0; n < s.length; n++) {
+ var c = s.charCodeAt(n);
+
+ if (c <= 0x7F) {
+ // 0x00 - 0x7F: Emit as single byte, unchanged
+ utf8 += String.fromCharCode(c);
+ } else if ((c >= 0x80) && (c <= 0x7FF)) {
+ // 0x80 - 0x7FF: Output as two byte code, 0xC0 in first byte
+ // 0x80 in second byte
+ utf8 += String.fromCharCode((c >> 6) | 0xC0);
+ utf8 += String.fromCharCode((c & 0x3F) | 0x80);
+ } else {
+ // 0x800 - 0xFFFF: Output as three bytes, 0xE0 in first byte
+ // 0x80 in second byte
+ // 0x80 in third byte
+ utf8 += String.fromCharCode((c >> 12) | 0xE0);
+ utf8 += String.fromCharCode(((c >> 6) & 0x3F) | 0x80);
+ utf8 += String.fromCharCode((c & 0x3F) | 0x80);
+ }
+ }
+ return utf8;
+ }
+
+ // UTF8_TO_UNICODE -- Decode UTF-8 argument into Unicode string return value
+
+ function utf8_to_unicode(utf8) {
+ var s = "", i = 0, b1, b2, b2;
+
+ while (i < utf8.length) {
+ b1 = utf8.charCodeAt(i);
+ if (b1 < 0x80) { // One byte code: 0x00 0x7F
+ s += String.fromCharCode(b1);
+ i++;
+ } else if((b1 >= 0xC0) && (b1 < 0xE0)) { // Two byte code: 0x80 - 0x7FF
+ b2 = utf8.charCodeAt(i + 1);
+ s += String.fromCharCode(((b1 & 0x1F) << 6) | (b2 & 0x3F));
+ i += 2;
+ } else { // Three byte code: 0x800 - 0xFFFF
+ b2 = utf8.charCodeAt(i + 1);
+ b3 = utf8.charCodeAt(i + 2);
+ s += String.fromCharCode(((b1 & 0xF) << 12) |
+ ((b2 & 0x3F) << 6) |
+ (b3 & 0x3F));
+ i += 3;
+ }
+ }
+ return s;
+ }
+
+ /* ENCODE_UTF8 -- Encode string as UTF8 only if it contains
+ a character of 0x9D (Unicode OPERATING
+ SYSTEM COMMAND) or a character greater
+ than 0xFF. This permits all strings
+ consisting exclusively of 8 bit
+ graphic characters to be encoded as
+ themselves. We choose 0x9D as the sentinel
+ character as opposed to one of the more
+ logical PRIVATE USE characters because 0x9D
+ is not overloaded by the regrettable
+ "Windows-1252" character set. Now such characters
+ don't belong in JavaScript strings, but you never
+ know what somebody is going to paste into a
+ text box, so this choice keeps Windows-encoded
+ strings from bloating to UTF-8 encoding. */
+
+ function encode_utf8(s) {
+ var i, necessary = false;
+
+ for (i = 0; i < s.length; i++) {
+ if ((s.charCodeAt(i) == 0x9D) ||
+ (s.charCodeAt(i) > 0xFF)) {
+ necessary = true;
+ break;
+ }
+ }
+ if (!necessary) {
+ return s;
+ }
+ return String.fromCharCode(0x9D) + unicode_to_utf8(s);
+ }
+
+ /* DECODE_UTF8 -- Decode a string encoded with encode_utf8
+ above. If the string begins with the
+ sentinel character 0x9D (OPERATING
+ SYSTEM COMMAND), then we decode the
+ balance as a UTF-8 stream. Otherwise,
+ the string is output unchanged, as
+ it's guaranteed to contain only 8 bit
+ characters excluding 0x9D. */
+
+ function decode_utf8(s) {
+ if ((s.length > 0) && (s.charCodeAt(0) == 0x9D)) {
+ return utf8_to_unicode(s.substring(1));
+ }
+ return s;
+ }
+
+
+//#############################################################################
+// Downloaded on April 26, 2006 from http://pajhome.org.uk/crypt/md5/md5.js
+//#############################################################################
+
+/*
+ * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
+ * Digest Algorithm, as defined in RFC 1321.
+ * Version 2.1 Copyright (C) Paul Johnston 1999 - 2002.
+ * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
+ * Distributed under the BSD License
+ * See http://pajhome.org.uk/crypt/md5 for more info.
+ */
+
+/*
+ * Configurable variables. You may need to tweak these to be compatible with
+ * the server-side, but the defaults work in most cases.
+ */
+var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */
+var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */
+var chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode */
+
+/*
+ * These are the functions you'll usually want to call
+ * They take string arguments and return either hex or base-64 encoded strings
+ */
+function hex_md5(s){ return binl2hex(core_md5(str2binl(s), s.length * chrsz));}
+function b64_md5(s){ return binl2b64(core_md5(str2binl(s), s.length * chrsz));}
+function str_md5(s){ return binl2str(core_md5(str2binl(s), s.length * chrsz));}
+function hex_hmac_md5(key, data) { return binl2hex(core_hmac_md5(key, data)); }
+function b64_hmac_md5(key, data) { return binl2b64(core_hmac_md5(key, data)); }
+function str_hmac_md5(key, data) { return binl2str(core_hmac_md5(key, data)); }
+
+/*
+ * Perform a simple self-test to see if the VM is working
+ */
+function md5_vm_test()
+{
+ return hex_md5("abc") == "900150983cd24fb0d6963f7d28e17f72";
+}
+
+/*
+ * Calculate the MD5 of an array of little-endian words, and a bit length
+ */
+function core_md5(x, len)
+{
+ /* append padding */
+ x[len >> 5] |= 0x80 << ((len) % 32);
+ x[(((len + 64) >>> 9) << 4) + 14] = len;
+
+ var a = 1732584193;
+ var b = -271733879;
+ var c = -1732584194;
+ var d = 271733878;
+
+ for(var i = 0; i < x.length; i += 16)
+ {
+ var olda = a;
+ var oldb = b;
+ var oldc = c;
+ var oldd = d;
+
+ a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);
+ d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);
+ c = md5_ff(c, d, a, b, x[i+ 2], 17, 606105819);
+ b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);
+ a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
+ d = md5_ff(d, a, b, c, x[i+ 5], 12, 1200080426);
+ c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);
+ b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);
+ a = md5_ff(a, b, c, d, x[i+ 8], 7 , 1770035416);
+ d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);
+ c = md5_ff(c, d, a, b, x[i+10], 17, -42063);
+ b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);
+ a = md5_ff(a, b, c, d, x[i+12], 7 , 1804603682);
+ d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);
+ c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);
+ b = md5_ff(b, c, d, a, x[i+15], 22, 1236535329);
+
+ a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);
+ d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
+ c = md5_gg(c, d, a, b, x[i+11], 14, 643717713);
+ b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);
+ a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);
+ d = md5_gg(d, a, b, c, x[i+10], 9 , 38016083);
+ c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);
+ b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);
+ a = md5_gg(a, b, c, d, x[i+ 9], 5 , 568446438);
+ d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);
+ c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);
+ b = md5_gg(b, c, d, a, x[i+ 8], 20, 1163531501);
+ a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);
+ d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);
+ c = md5_gg(c, d, a, b, x[i+ 7], 14, 1735328473);
+ b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);
+
+ a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);
+ d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);
+ c = md5_hh(c, d, a, b, x[i+11], 16, 1839030562);
+ b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);
+ a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
+ d = md5_hh(d, a, b, c, x[i+ 4], 11, 1272893353);
+ c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);
+ b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);
+ a = md5_hh(a, b, c, d, x[i+13], 4 , 681279174);
+ d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);
+ c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);
+ b = md5_hh(b, c, d, a, x[i+ 6], 23, 76029189);
+ a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);
+ d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);
+ c = md5_hh(c, d, a, b, x[i+15], 16, 530742520);
+ b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);
+
+ a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);
+ d = md5_ii(d, a, b, c, x[i+ 7], 10, 1126891415);
+ c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);
+ b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);
+ a = md5_ii(a, b, c, d, x[i+12], 6 , 1700485571);
+ d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);
+ c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);
+ b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);
+ a = md5_ii(a, b, c, d, x[i+ 8], 6 , 1873313359);
+ d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);
+ c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);
+ b = md5_ii(b, c, d, a, x[i+13], 21, 1309151649);
+ a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);
+ d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);
+ c = md5_ii(c, d, a, b, x[i+ 2], 15, 718787259);
+ b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);
+
+ a = safe_add(a, olda);
+ b = safe_add(b, oldb);
+ c = safe_add(c, oldc);
+ d = safe_add(d, oldd);
+ }
+ return Array(a, b, c, d);
+
+}
+
+/*
+ * These functions implement the four basic operations the algorithm uses.
+ */
+function md5_cmn(q, a, b, x, s, t)
+{
+ return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);
+}
+function md5_ff(a, b, c, d, x, s, t)
+{
+ return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
+}
+function md5_gg(a, b, c, d, x, s, t)
+{
+ return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
+}
+function md5_hh(a, b, c, d, x, s, t)
+{
+ return md5_cmn(b ^ c ^ d, a, b, x, s, t);
+}
+function md5_ii(a, b, c, d, x, s, t)
+{
+ return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
+}
+
+/*
+ * Calculate the HMAC-MD5, of a key and some data
+ */
+function core_hmac_md5(key, data)
+{
+ var bkey = str2binl(key);
+ if(bkey.length > 16) bkey = core_md5(bkey, key.length * chrsz);
+
+ var ipad = Array(16), opad = Array(16);
+ for(var i = 0; i < 16; i++)
+ {
+ ipad[i] = bkey[i] ^ 0x36363636;
+ opad[i] = bkey[i] ^ 0x5C5C5C5C;
+ }
+
+ var hash = core_md5(ipad.concat(str2binl(data)), 512 + data.length * chrsz);
+ return core_md5(opad.concat(hash), 512 + 128);
+}
+
+/*
+ * Add integers, wrapping at 2^32. This uses 16-bit operations internally
+ * to work around bugs in some JS interpreters.
+ */
+function safe_add(x, y)
+{
+ var lsw = (x & 0xFFFF) + (y & 0xFFFF);
+ var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
+ return (msw << 16) | (lsw & 0xFFFF);
+}
+
+/*
+ * Bitwise rotate a 32-bit number to the left.
+ */
+function bit_rol(num, cnt)
+{
+ return (num << cnt) | (num >>> (32 - cnt));
+}
+
+/*
+ * Convert a string to an array of little-endian words
+ * If chrsz is ASCII, characters >255 have their hi-byte silently ignored.
+ */
+function str2binl(str)
+{
+ var bin = Array();
+ var mask = (1 << chrsz) - 1;
+ for(var i = 0; i < str.length * chrsz; i += chrsz)
+ bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (i%32);
+ return bin;
+}
+
+/*
+ * Convert an array of little-endian words to a string
+ */
+function binl2str(bin)
+{
+ var str = "";
+ var mask = (1 << chrsz) - 1;
+ for(var i = 0; i < bin.length * 32; i += chrsz)
+ str += String.fromCharCode((bin[i>>5] >>> (i % 32)) & mask);
+ return str;
+}
+
+/*
+ * Convert an array of little-endian words to a hex string.
+ */
+function binl2hex(binarray)
+{
+ var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
+ var str = "";
+ for(var i = 0; i < binarray.length * 4; i++)
+ {
+ str += hex_tab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) +
+ hex_tab.charAt((binarray[i>>2] >> ((i%4)*8 )) & 0xF);
+ }
+ return str;
+}
+
+/*
+ * Convert an array of little-endian words to a base-64 string
+ */
+function binl2b64(binarray)
+{
+ var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+ var str = "";
+ for(var i = 0; i < binarray.length * 4; i += 3)
+ {
+ var triplet = (((binarray[i >> 2] >> 8 * ( i %4)) & 0xFF) << 16)
+ | (((binarray[i+1 >> 2] >> 8 * ((i+1)%4)) & 0xFF) << 8 )
+ | ((binarray[i+2 >> 2] >> 8 * ((i+2)%4)) & 0xFF);
+ for(var j = 0; j < 4; j++)
+ {
+ if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
+ else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
+ }
+ }
+ return str;
+}
+
+
+//#############################################################################
+//#############################################################################
+//#############################################################################
+
+
+
+MochiKit.Base.update(Clipperz.Crypto.Base, {
+
+ '__repr__': function () {
+ return "[" + this.NAME + " " + this.VERSION + "]";
+ },
+
+ 'toString': function () {
+ return this.__repr__();
+ },
+
+ //-----------------------------------------------------------------------------
+
+ 'encryptUsingSecretKey': function (aKey, aMessage) {
+//Clipperz.Profile.start("Clipperz.Crypto.Base.encryptUsingSecretKey");
+ var result;
+ var plaintext;
+ var header;
+ var key;
+
+ key = hexToByteArray(Clipperz.Crypto.Base.computeHashValue(aKey));
+
+ addEntropyTime();
+ prng = new AESprng(keyFromEntropy());
+
+ plaintext = encode_utf8(aMessage);
+
+ header = Clipperz.Base.byteArrayToString(hexToByteArray(Clipperz.Crypto.Base.computeMD5HashValue(plaintext)));
+
+ // Add message length in bytes to header
+ i = plaintext.length;
+ header += String.fromCharCode(i >>> 24);
+ header += String.fromCharCode(i >>> 16);
+ header += String.fromCharCode(i >>> 8);
+ header += String.fromCharCode(i & 0xFF);
+
+ // The format of the actual message passed to rijndaelEncrypt
+ // is:
+ //
+ // Bytes Content
+ // 0-15 MD5 signature of plaintext
+ // 16-19 Length of plaintext, big-endian order
+ // 20-end Plaintext
+ //
+ // Note that this message will be padded with zero bytes
+ // to an integral number of AES blocks (blockSizeInBits / 8).
+ // This does not include the initial vector for CBC
+ // encryption, which is added internally by rijndaelEncrypt.
+ result = byteArrayToHex(rijndaelEncrypt(header + plaintext, key, "CBC"));
+
+ delete prng;
+
+//Clipperz.Profile.stop("Clipperz.Crypto.Base.encryptUsingSecretKey");
+ return result;
+ },
+
+ //.............................................................................
+
+ 'decryptUsingSecretKey': function (aKey, aMessage) {
+//Clipperz.Profile.start("Clipperz.Crypto.Base.decryptUsingSecretKey");
+ var key;
+ var decryptedText;
+ var textLength;
+ var header;
+ var headerDigest;
+ var plaintext;
+ var i;
+
+ key = hexToByteArray(Clipperz.Crypto.Base.computeHashValue(aKey));
+
+ decryptedText = rijndaelDecrypt(hexToByteArray(aMessage), key, "CBC");
+
+ header = decryptedText.slice(0, 20);
+ decryptedText = decryptedText.slice(20);
+
+ headerDigest = byteArrayToHex(header.slice(0,16));
+ textLength = (header[16] << 24) | (header[17] << 16) | (header[18] << 8) | header[19];
+
+ if ((textLength < 0) || (textLength > decryptedText.length)) {
+// jslog.warning("Message (length " + decryptedText.length + ") truncated. " + textLength + " characters expected.");
+ // Try to sauve qui peut by setting length to entire message
+ textLength = decryptedText.length;
+ }
+
+ plainText = "";
+
+ for (i=0; i<textLength; i++) {
+ plainText += String.fromCharCode(decryptedText[i]);
+ }
+
+ if (Clipperz.Crypto.Base.computeMD5HashValue(plainText) != headerDigest) {
+// jslog.warning("Message corrupted. Checksum of decrypted message does not match.");
+ throw Clipperz.Crypto.Base.exception.CorruptedMessage;
+// throw new Error("Message corrupted. Checksum of decrypted message does not match. Parsed result: " + decode_utf8(plainText));
+ }
+
+ // That's it; plug plaintext into the result field
+
+ result = decode_utf8(plainText);
+
+//Clipperz.Profile.stop("Clipperz.Crypto.Base.decryptUsingSecretKey");
+ return result;
+ },
+
+ //-----------------------------------------------------------------------------
+
+ 'computeHashValue': function (aMessage) {
+//Clipperz.Profile.start("Clipperz.Crypto.Base.computeHashValue");
+ var result;
+
+ result = hex_sha256(aMessage);
+//Clipperz.Profile.stop("Clipperz.Crypto.Base.computeHashValue");
+
+ return result;
+ },
+
+ //.........................................................................
+
+ 'computeMD5HashValue': function (aMessage) {
+ var result;
+//Clipperz.Profile.start("Clipperz.Crypto.Base.computeMD5HashValue");
+ result = hex_md5(aMessage);
+//Clipperz.Profile.stop("Clipperz.Crypto.Base.computeMD5HashValue");
+
+ return result;
+ },
+
+ //-----------------------------------------------------------------------------
+
+ 'generateRandomSeed': function () {
+//Clipperz.Profile.start("Clipperz.Crypto.Base.generateRandomSeed");
+ var result;
+ var seed;
+ var prng;
+ var charA;
+ var i;
+
+ addEntropyTime();
+
+ seed = keyFromEntropy();
+ prng = new AESprng(seed);
+
+ result = "";
+ charA = ("A").charCodeAt(0);
+
+ for (i = 0; i < 64; i++) {
+ result += String.fromCharCode(charA + prng.nextInt(25));
+ }
+
+ delete prng;
+
+ result = Clipperz.Crypto.Base.computeHashValue(result);
+
+//Clipperz.Profile.stop("Clipperz.Crypto.Base.generateRandomSeed");
+ return result;
+ },
+
+ //-----------------------------------------------------------------------------
+
+ 'exception': {
+ 'CorruptedMessage': new MochiKit.Base.NamedError("Clipperz.Crypto.Base.exception.CorruptedMessage")
+ },
+
+ //.........................................................................
+ __syntaxFix__: "syntax fix"
+});
+
diff --git a/frontend/beta/js/Clipperz/Crypto/BigInt.js b/frontend/beta/js/Clipperz/Crypto/BigInt.js
new file mode 100644
index 0000000..d4d05d2
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/Crypto/BigInt.js
@@ -0,0 +1,1760 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
+if (typeof(Clipperz.Crypto) == 'undefined') { Clipperz.Crypto = {}; }
+
+//#############################################################################
+// Downloaded on March 05, 2007 from http://www.leemon.com/crypto/BigInt.js
+//#############################################################################
+
+
+////////////////////////////////////////////////////////////////////////////////////////
+// Big Integer Library v. 5.0
+// Created 2000, last modified 2006
+// Leemon Baird
+// www.leemon.com
+//
+// This file is public domain. You can use it for any purpose without restriction.
+// I do not guarantee that it is correct, so use it at your own risk. If you use
+// it for something interesting, I'd appreciate hearing about it. If you find
+// any bugs or make any improvements, I'd appreciate hearing about those too.
+// It would also be nice if my name and address were left in the comments.
+// But none of that is required.
+//
+// This code defines a bigInt library for arbitrary-precision integers.
+// A bigInt is an array of integers storing the value in chunks of bpe bits,
+// little endian (buff[0] is the least significant word).
+// Negative bigInts are stored two's complement.
+// Some functions assume their parameters have at least one leading zero element.
+// Functions with an underscore at the end of the name have unpredictable behavior in case of overflow,
+// so the caller must make sure overflow won't happen.
+// For each function where a parameter is modified, that same
+// variable must not be used as another argument too.
+// So, you cannot square x by doing multMod_(x,x,n).
+// You must use squareMod_(x,n) instead, or do y=dup(x); multMod_(x,y,n).
+//
+// These functions are designed to avoid frequent dynamic memory allocation in the inner loop.
+// For most functions, if it needs a BigInt as a local variable it will actually use
+// a global, and will only allocate to it when it's not the right size. This ensures
+// that when a function is called repeatedly with same-sized parameters, it only allocates
+// memory on the first call.
+//
+// Note that for cryptographic purposes, the calls to Math.random() must
+// be replaced with calls to a better pseudorandom number generator.
+//
+// In the following, "bigInt" means a bigInt with at least one leading zero element,
+// and "integer" means a nonnegative integer less than radix. In some cases, integer
+// can be negative. Negative bigInts are 2s complement.
+//
+// The following functions do not modify their inputs, but dynamically allocate memory every time they are called:
+//
+// function bigInt2str(x,base) //convert a bigInt into a string in a given base, from base 2 up to base 95
+// function dup(x) //returns a copy of bigInt x
+// function findPrimes(n) //return array of all primes less than integer n
+// function int2bigInt(t,n,m) //convert integer t to a bigInt with at least n bits and m array elements
+// function int2bigInt(s,b,n,m) //convert string s in base b to a bigInt with at least n bits and m array elements
+// function trim(x,k) //return a copy of x with exactly k leading zero elements
+//
+// The following functions do not modify their inputs, so there is never a problem with the result being too big:
+//
+// function bitSize(x) //returns how many bits long the bigInt x is, not counting leading zeros
+// function equals(x,y) //is the bigInt x equal to the bigint y?
+// function equalsInt(x,y) //is bigint x equal to integer y?
+// function greater(x,y) //is x>y? (x and y are nonnegative bigInts)
+// function greaterShift(x,y,shift)//is (x <<(shift*bpe)) > y?
+// function isZero(x) //is the bigInt x equal to zero?
+// function millerRabin(x,b) //does one round of Miller-Rabin base integer b say that bigInt x is possibly prime (as opposed to definitely composite)?
+// function modInt(x,n) //return x mod n for bigInt x and integer n.
+// function negative(x) //is bigInt x negative?
+//
+// The following functions do not modify their inputs, but allocate memory and call functions with underscores
+//
+// function add(x,y) //return (x+y) for bigInts x and y.
+// function addInt(x,n) //return (x+n) where x is a bigInt and n is an integer.
+// function expand(x,n) //return a copy of x with at least n elements, adding leading zeros if needed
+// function inverseMod(x,n) //return (x**(-1) mod n) for bigInts x and n. If no inverse exists, it returns null
+// function mod(x,n) //return a new bigInt equal to (x mod n) for bigInts x and n.
+// function mult(x,y) //return x*y for bigInts x and y. This is faster when y<x.
+// function multMod(x,y,n) //return (x*y mod n) for bigInts x,y,n. For greater speed, let y<x.
+// function powMod(x,y,n) //return (x**y mod n) where x,y,n are bigInts and ** is exponentiation. 0**0=1. Faster for odd n.
+// function randTruePrime(k) //return a new, random, k-bit, true prime using Maurer's algorithm.
+// function sub(x,y) //return (x-y) for bigInts x and y. Negative answers will be 2s complement
+//
+// The following functions write a bigInt result to one of the parameters, but
+// the result is never bigger than the original, so there can't be overflow problems:
+//
+// function divInt_(x,n) //do x=floor(x/n) for bigInt x and integer n, and return the remainder
+// function GCD_(x,y) //set x to the greatest common divisor of bigInts x and y, (y is destroyed).
+// function halve_(x) //do x=floor(|x|/2)*sgn(x) for bigInt x in 2's complement
+// function mod_(x,n) //do x=x mod n for bigInts x and n.
+// function rightShift_(x,n) //right shift bigInt x by n bits. 0 <= n < bpe.
+//
+// The following functions write a bigInt result to one of the parameters. The caller is responsible for
+// ensuring it is large enough to hold the result.
+//
+// function addInt_(x,n) //do x=x+n where x is a bigInt and n is an integer
+// function add_(x,y) //do x=x+y for bigInts x and y
+// function addShift_(x,y,ys) //do x=x+(y<<(ys*bpe))
+// function copy_(x,y) //do x=y on bigInts x and y
+// function copyInt_(x,n) //do x=n on bigInt x and integer n
+// function carry_(x) //do carries and borrows so each element of the bigInt x fits in bpe bits.
+// function divide_(x,y,q,r) //divide_ x by y giving quotient q and remainder r
+// function eGCD_(x,y,d,a,b) //sets a,b,d to positive big integers such that d = GCD_(x,y) = a*x-b*y
+// function inverseMod_(x,n) //do x=x**(-1) mod n, for bigInts x and n. Returns 1 (0) if inverse does (doesn't) exist
+// function inverseModInt_(x,n) //return x**(-1) mod n, for integers x and n. Return 0 if there is no inverse
+// function leftShift_(x,n) //left shift bigInt x by n bits. n<bpe.
+// function linComb_(x,y,a,b) //do x=a*x+b*y for bigInts x and y and integers a and b
+// function linCombShift_(x,y,b,ys) //do x=x+b*(y<<(ys*bpe)) for bigInts x and y, and integers b and ys
+// function mont_(x,y,n,np) //Montgomery multiplication (see comments where the function is defined)
+// function mult_(x,y) //do x=x*y for bigInts x and y.
+// function multInt_(x,n) //do x=x*n where x is a bigInt and n is an integer.
+// function multMod_(x,y,n) //do x=x*y mod n for bigInts x,y,n.
+// function powMod_(x,y,n) //do x=x**y mod n, where x,y,n are bigInts (n is odd) and ** is exponentiation. 0**0=1.
+// function randBigInt_(b,n,s) //do b = an n-bit random BigInt. if s=1, then nth bit (most significant bit) is set to 1. n>=1.
+// function randTruePrime_(ans,k) //do ans = a random k-bit true random prime (not just probable prime) with 1 in the msb.
+// function squareMod_(x,n) //do x=x*x mod n for bigInts x,n
+// function sub_(x,y) //do x=x-y for bigInts x and y. Negative answers will be 2s complement.
+// function subShift_(x,y,ys) //do x=x-(y<<(ys*bpe)). Negative answers will be 2s complement.
+//
+// The following functions are based on algorithms from the _Handbook of Applied Cryptography_
+// powMod_() = algorithm 14.94, Montgomery exponentiation
+// eGCD_,inverseMod_() = algorithm 14.61, Binary extended GCD_
+// GCD_() = algorothm 14.57, Lehmer's algorithm
+// mont_() = algorithm 14.36, Montgomery multiplication
+// divide_() = algorithm 14.20 Multiple-precision division
+// squareMod_() = algorithm 14.16 Multiple-precision squaring
+// randTruePrime_() = algorithm 4.62, Maurer's algorithm
+// millerRabin() = algorithm 4.24, Miller-Rabin algorithm
+//
+// Profiling shows:
+// randTruePrime_() spends:
+// 10% of its time in calls to powMod_()
+// 85% of its time in calls to millerRabin()
+// millerRabin() spends:
+// 99% of its time in calls to powMod_() (always with a base of 2)
+// powMod_() spends:
+// 94% of its time in calls to mont_() (almost always with x==y)
+//
+// This suggests there are several ways to speed up this library slightly:
+// - convert powMod_ to use a Montgomery form of k-ary window (or maybe a Montgomery form of sliding window)
+// -- this should especially focus on being fast when raising 2 to a power mod n
+// - convert randTruePrime_() to use a minimum r of 1/3 instead of 1/2 with the appropriate change to the test
+// - tune the parameters in randTruePrime_(), including c, m, and recLimit
+// - speed up the single loop in mont_() that takes 95% of the runtime, perhaps by reducing checking
+// within the loop when all the parameters are the same length.
+//
+// There are several ideas that look like they wouldn't help much at all:
+// - replacing trial division in randTruePrime_() with a sieve (that speeds up something taking almost no time anyway)
+// - increase bpe from 15 to 30 (that would help if we had a 32*32->64 multiplier, but not with JavaScript's 32*32->32)
+// - speeding up mont_(x,y,n,np) when x==y by doing a non-modular, non-Montgomery square
+// followed by a Montgomery reduction. The intermediate answer will be twice as long as x, so that
+// method would be slower. This is unfortunate because the code currently spends almost all of its time
+// doing mont_(x,x,...), both for randTruePrime_() and powMod_(). A faster method for Montgomery squaring
+// would have a large impact on the speed of randTruePrime_() and powMod_(). HAC has a couple of poorly-worded
+// sentences that seem to imply it's faster to do a non-modular square followed by a single
+// Montgomery reduction, but that's obviously wrong.
+////////////////////////////////////////////////////////////////////////////////////////
+
+//globals
+bpe=0; //bits stored per array element
+mask=0; //AND this with an array element to chop it down to bpe bits
+radix=mask+1; //equals 2^bpe. A single 1 bit to the left of the last bit of mask.
+
+//the digits for converting to different bases
+digitsStr='0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_=!@#$%^&*()[]{}|;:,.<>/?`~ \\\'\"+-';
+
+//initialize the global variables
+for (bpe=0; (1<<(bpe+1)) > (1<<bpe); bpe++); //bpe=number of bits in the mantissa on this platform
+bpe>>=1; //bpe=number of bits in one element of the array representing the bigInt
+mask=(1<<bpe)-1; //AND the mask with an integer to get its bpe least significant bits
+radix=mask+1; //2^bpe. a single 1 bit to the left of the first bit of mask
+one=int2bigInt(1,1,1); //constant used in powMod_()
+
+//the following global variables are scratchpad memory to
+//reduce dynamic memory allocation in the inner loop
+t=new Array(0);
+ss=t; //used in mult_()
+s0=t; //used in multMod_(), squareMod_()
+s1=t; //used in powMod_(), multMod_(), squareMod_()
+s2=t; //used in powMod_(), multMod_()
+s3=t; //used in powMod_()
+s4=t; s5=t; //used in mod_()
+s6=t; //used in bigInt2str()
+s7=t; //used in powMod_()
+T=t; //used in GCD_()
+sa=t; //used in mont_()
+mr_x1=t; mr_r=t; mr_a=t; //used in millerRabin()
+eg_v=t; eg_u=t; eg_A=t; eg_B=t; eg_C=t; eg_D=t; //used in eGCD_(), inverseMod_()
+md_q1=t; md_q2=t; md_q3=t; md_r=t; md_r1=t; md_r2=t; md_tt=t; //used in mod_()
+
+primes=t; pows=t; s_i=t; s_i2=t; s_R=t; s_rm=t; s_q=t; s_n1=t;
+ s_a=t; s_r2=t; s_n=t; s_b=t; s_d=t; s_x1=t; s_x2=t, s_aa=t; //used in randTruePrime_()
+
+////////////////////////////////////////////////////////////////////////////////////////
+
+//return array of all primes less than integer n
+function findPrimes(n) {
+ var i,s,p,ans;
+ s=new Array(n);
+ for (i=0;i<n;i++)
+ s[i]=0;
+ s[0]=2;
+ p=0; //first p elements of s are primes, the rest are a sieve
+ for(;s[p]<n;) { //s[p] is the pth prime
+ for(i=s[p]*s[p]; i<n; i+=s[p]) //mark multiples of s[p]
+ s[i]=1;
+ p++;
+ s[p]=s[p-1]+1;
+ for(; s[p]<n && s[s[p]]; s[p]++); //find next prime (where s[p]==0)
+ }
+ ans=new Array(p);
+ for(i=0;i<p;i++)
+ ans[i]=s[i];
+ return ans;
+}
+
+//does a single round of Miller-Rabin base b consider x to be a possible prime?
+//x is a bigInt, and b is an integer
+function millerRabin(x,b) {
+ var i,j,k,s;
+
+ if (mr_x1.length!=x.length) {
+ mr_x1=dup(x);
+ mr_r=dup(x);
+ mr_a=dup(x);
+ }
+
+ copyInt_(mr_a,b);
+ copy_(mr_r,x);
+ copy_(mr_x1,x);
+
+ addInt_(mr_r,-1);
+ addInt_(mr_x1,-1);
+
+ //s=the highest power of two that divides mr_r
+ k=0;
+ for (i=0;i<mr_r.length;i++)
+ for (j=1;j<mask;j<<=1)
+ if (x[i] & j) {
+ s=(k<mr_r.length+bpe ? k : 0);
+ i=mr_r.length;
+ j=mask;
+ } else
+ k++;
+
+ if (s)
+ rightShift_(mr_r,s);
+
+ powMod_(mr_a,mr_r,x);
+
+ if (!equalsInt(mr_a,1) && !equals(mr_a,mr_x1)) {
+ j=1;
+ while (j<=s-1 && !equals(mr_a,mr_x1)) {
+ squareMod_(mr_a,x);
+ if (equalsInt(mr_a,1)) {
+ return 0;
+ }
+ j++;
+ }
+ if (!equals(mr_a,mr_x1)) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+//returns how many bits long the bigInt is, not counting leading zeros.
+function bitSize(x) {
+ var j,z,w;
+ for (j=x.length-1; (x[j]==0) && (j>0); j--);
+ for (z=0,w=x[j]; w; (w>>=1),z++);
+ z+=bpe*j;
+ return z;
+}
+
+//return a copy of x with at least n elements, adding leading zeros if needed
+function expand(x,n) {
+ var ans=int2bigInt(0,(x.length>n ? x.length : n)*bpe,0);
+ copy_(ans,x);
+ return ans;
+}
+
+//return a k-bit true random prime using Maurer's algorithm.
+function randTruePrime(k) {
+ var ans=int2bigInt(0,k,0);
+ randTruePrime_(ans,k);
+ return trim(ans,1);
+}
+
+//return a new bigInt equal to (x mod n) for bigInts x and n.
+function mod(x,n) {
+ var ans=dup(x);
+ mod_(ans,n);
+ return trim(ans,1);
+}
+
+//return (x+n) where x is a bigInt and n is an integer.
+function addInt(x,n) {
+ var ans=expand(x,x.length+1);
+ addInt_(ans,n);
+ return trim(ans,1);
+}
+
+//return x*y for bigInts x and y. This is faster when y<x.
+function mult(x,y) {
+ var ans=expand(x,x.length+y.length);
+ mult_(ans,y);
+ return trim(ans,1);
+}
+
+//return (x**y mod n) where x,y,n are bigInts and ** is exponentiation. 0**0=1. Faster for odd n.
+function powMod(x,y,n) {
+ var ans=expand(x,n.length);
+ powMod_(ans,trim(y,2),trim(n,2),0); //this should work without the trim, but doesn't
+ return trim(ans,1);
+}
+
+//return (x-y) for bigInts x and y. Negative answers will be 2s complement
+function sub(x,y) {
+ var ans=expand(x,(x.length>y.length ? x.length+1 : y.length+1));
+ sub_(ans,y);
+ return trim(ans,1);
+}
+
+//return (x+y) for bigInts x and y.
+function add(x,y) {
+ var ans=expand(x,(x.length>y.length ? x.length+1 : y.length+1));
+ add_(ans,y);
+ return trim(ans,1);
+}
+
+//return (x**(-1) mod n) for bigInts x and n. If no inverse exists, it returns null
+function inverseMod(x,n) {
+ var ans=expand(x,n.length);
+ var s;
+ s=inverseMod_(ans,n);
+ return s ? trim(ans,1) : null;
+}
+
+//return (x*y mod n) for bigInts x,y,n. For greater speed, let y<x.
+function multMod(x,y,n) {
+ var ans=expand(x,n.length);
+ multMod_(ans,y,n);
+ return trim(ans,1);
+}
+
+//generate a k-bit true random prime using Maurer's algorithm,
+//and put it into ans. The bigInt ans must be large enough to hold it.
+function randTruePrime_(ans,k) {
+ var c,m,pm,dd,j,r,B,divisible,z,zz,recSize;
+
+ if (primes.length==0)
+ primes=findPrimes(30000); //check for divisibility by primes <=30000
+
+ if (pows.length==0) {
+ pows=new Array(512);
+ for (j=0;j<512;j++) {
+ pows[j]=Math.pow(2,j/511.-1.);
+ }
+ }
+
+ //c and m should be tuned for a particular machine and value of k, to maximize speed
+ //this was: c=primes[primes.length-1]/k/k; //check using all the small primes. (c=0.1 in HAC)
+ c=0.1;
+ m=20; //generate this k-bit number by first recursively generating a number that has between k/2 and k-m bits
+ recLimit=20; /*must be at least 2 (was 29)*/ //stop recursion when k <=recLimit
+
+ if (s_i2.length!=ans.length) {
+ s_i2=dup(ans);
+ s_R =dup(ans);
+ s_n1=dup(ans);
+ s_r2=dup(ans);
+ s_d =dup(ans);
+ s_x1=dup(ans);
+ s_x2=dup(ans);
+ s_b =dup(ans);
+ s_n =dup(ans);
+ s_i =dup(ans);
+ s_rm=dup(ans);
+ s_q =dup(ans);
+ s_a =dup(ans);
+ s_aa=dup(ans);
+ }
+
+ if (k <= recLimit) { //generate small random primes by trial division up to its square root
+ pm=(1<<((k+2)>>1))-1; //pm is binary number with all ones, just over sqrt(2^k)
+ copyInt_(ans,0);
+ for (dd=1;dd;) {
+ dd=0;
+ ans[0]= 1 | (1<<(k-1)) | Math.floor(Math.random()*(1<<k)); //random, k-bit, odd integer, with msb 1
+ for (j=1;(j<primes.length) && ((primes[j]&pm)==primes[j]);j++) { //trial division by all primes 3...sqrt(2^k)
+ if (0==(ans[0]%primes[j])) {
+ dd=1;
+ break;
+ }
+ }
+ }
+ carry_(ans);
+ return;
+ }
+
+ B=c*k*k; //try small primes up to B (or all the primes[] array if the largest is less than B).
+ if (k>2*m) //generate this k-bit number by first recursively generating a number that has between k/2 and k-m bits
+ for (r=1; k-k*r<=m; )
+ r=pows[Math.floor(Math.random()*512)]; //r=Math.pow(2,Math.random()-1);
+ else
+ r=.5;
+
+ //simulation suggests the more complex algorithm using r=.333 is only slightly faster.
+
+ recSize=Math.floor(r*k)+1;
+
+ randTruePrime_(s_q,recSize);
+ copyInt_(s_i2,0);
+ s_i2[Math.floor((k-2)/bpe)] |= (1<<((k-2)%bpe)); //s_i2=2^(k-2)
+ divide_(s_i2,s_q,s_i,s_rm); //s_i=floor((2^(k-1))/(2q))
+
+ z=bitSize(s_i);
+
+ for (;;) {
+ for (;;) { //generate z-bit numbers until one falls in the range [0,s_i-1]
+ randBigInt_(s_R,z,0);
+ if (greater(s_i,s_R))
+ break;
+ } //now s_R is in the range [0,s_i-1]
+ addInt_(s_R,1); //now s_R is in the range [1,s_i]
+ add_(s_R,s_i); //now s_R is in the range [s_i+1,2*s_i]
+
+ copy_(s_n,s_q);
+ mult_(s_n,s_R);
+ multInt_(s_n,2);
+ addInt_(s_n,1); //s_n=2*s_R*s_q+1
+
+ copy_(s_r2,s_R);
+ multInt_(s_r2,2); //s_r2=2*s_R
+
+ //check s_n for divisibility by small primes up to B
+ for (divisible=0,j=0; (j<primes.length) && (primes[j]<B); j++)
+ if (modInt(s_n,primes[j])==0) {
+ divisible=1;
+ break;
+ }
+
+ if (!divisible) //if it passes small primes check, then try a single Miller-Rabin base 2
+ if (!millerRabin(s_n,2)) //this line represents 75% of the total runtime for randTruePrime_
+ divisible=1;
+
+ if (!divisible) { //if it passes that test, continue checking s_n
+ addInt_(s_n,-3);
+ for (j=s_n.length-1;(s_n[j]==0) && (j>0); j--); //strip leading zeros
+ for (zz=0,w=s_n[j]; w; (w>>=1),zz++);
+ zz+=bpe*j; //zz=number of bits in s_n, ignoring leading zeros
+ for (;;) { //generate z-bit numbers until one falls in the range [0,s_n-1]
+ randBigInt_(s_a,zz,0);
+ if (greater(s_n,s_a))
+ break;
+ } //now s_a is in the range [0,s_n-1]
+ addInt_(s_n,3); //now s_a is in the range [0,s_n-4]
+ addInt_(s_a,2); //now s_a is in the range [2,s_n-2]
+ copy_(s_b,s_a);
+ copy_(s_n1,s_n);
+ addInt_(s_n1,-1);
+ powMod_(s_b,s_n1,s_n); //s_b=s_a^(s_n-1) modulo s_n
+ addInt_(s_b,-1);
+ if (isZero(s_b)) {
+ copy_(s_b,s_a);
+ powMod_(s_b,s_r2,s_n);
+ addInt_(s_b,-1);
+ copy_(s_aa,s_n);
+ copy_(s_d,s_b);
+ GCD_(s_d,s_n); //if s_b and s_n are relatively prime, then s_n is a prime
+ if (equalsInt(s_d,1)) {
+ copy_(ans,s_aa);
+ return; //if we've made it this far, then s_n is absolutely guaranteed to be prime
+ }
+ }
+ }
+ }
+}
+
+//set b to an n-bit random BigInt. If s=1, then nth bit (most significant bit) is set to 1.
+//array b must be big enough to hold the result. Must have n>=1
+function randBigInt_(b,n,s) {
+ var i,a;
+ for (i=0;i<b.length;i++)
+ b[i]=0;
+ a=Math.floor((n-1)/bpe)+1; //# array elements to hold the BigInt
+ for (i=0;i<a;i++) {
+ b[i]=Math.floor(Math.random()*(1<<(bpe-1)));
+ }
+ b[a-1] &= (2<<((n-1)%bpe))-1;
+ if (s)
+ b[a-1] |= (1<<((n-1)%bpe));
+}
+
+//set x to the greatest common divisor of x and y.
+//x,y are bigInts with the same number of elements. y is destroyed.
+function GCD_(x,y) {
+ var i,xp,yp,A,B,C,D,q,sing;
+ if (T.length!=x.length)
+ T=dup(x);
+
+ sing=1;
+ while (sing) { //while y has nonzero elements other than y[0]
+ sing=0;
+ for (i=1;i<y.length;i++) //check if y has nonzero elements other than 0
+ if (y[i]) {
+ sing=1;
+ break;
+ }
+ if (!sing) break; //quit when y all zero elements except possibly y[0]
+
+ for (i=x.length;!x[i] && i>=0;i--); //find most significant element of x
+ xp=x[i];
+ yp=y[i];
+ A=1; B=0; C=0; D=1;
+ while ((yp+C) && (yp+D)) {
+ q =Math.floor((xp+A)/(yp+C));
+ qp=Math.floor((xp+B)/(yp+D));
+ if (q!=qp)
+ break;
+ t= A-q*C; A=C; C=t; // do (A,B,xp, C,D,yp) = (C,D,yp, A,B,xp) - q*(0,0,0, C,D,yp)
+ t= B-q*D; B=D; D=t;
+ t=xp-q*yp; xp=yp; yp=t;
+ }
+ if (B) {
+ copy_(T,x);
+ linComb_(x,y,A,B); //x=A*x+B*y
+ linComb_(y,T,D,C); //y=D*y+C*T
+ } else {
+ mod_(x,y);
+ copy_(T,x);
+ copy_(x,y);
+ copy_(y,T);
+ }
+ }
+ if (y[0]==0)
+ return;
+ t=modInt(x,y[0]);
+ copyInt_(x,y[0]);
+ y[0]=t;
+ while (y[0]) {
+ x[0]%=y[0];
+ t=x[0]; x[0]=y[0]; y[0]=t;
+ }
+}
+
+//do x=x**(-1) mod n, for bigInts x and n.
+//If no inverse exists, it sets x to zero and returns 0, else it returns 1.
+//The x array must be at least as large as the n array.
+function inverseMod_(x,n) {
+ var k=1+2*Math.max(x.length,n.length);
+
+ if(!(x[0]&1) && !(n[0]&1)) { //if both inputs are even, then inverse doesn't exist
+ copyInt_(x,0);
+ return 0;
+ }
+
+ if (eg_u.length!=k) {
+ eg_u=new Array(k);
+ eg_v=new Array(k);
+ eg_A=new Array(k);
+ eg_B=new Array(k);
+ eg_C=new Array(k);
+ eg_D=new Array(k);
+ }
+
+ copy_(eg_u,x);
+ copy_(eg_v,n);
+ copyInt_(eg_A,1);
+ copyInt_(eg_B,0);
+ copyInt_(eg_C,0);
+ copyInt_(eg_D,1);
+ for (;;) {
+ while(!(eg_u[0]&1)) { //while eg_u is even
+ halve_(eg_u);
+ if (!(eg_A[0]&1) && !(eg_B[0]&1)) { //if eg_A==eg_B==0 mod 2
+ halve_(eg_A);
+ halve_(eg_B);
+ } else {
+ add_(eg_A,n); halve_(eg_A);
+ sub_(eg_B,x); halve_(eg_B);
+ }
+ }
+
+ while (!(eg_v[0]&1)) { //while eg_v is even
+ halve_(eg_v);
+ if (!(eg_C[0]&1) && !(eg_D[0]&1)) { //if eg_C==eg_D==0 mod 2
+ halve_(eg_C);
+ halve_(eg_D);
+ } else {
+ add_(eg_C,n); halve_(eg_C);
+ sub_(eg_D,x); halve_(eg_D);
+ }
+ }
+
+ if (!greater(eg_v,eg_u)) { //eg_v <= eg_u
+ sub_(eg_u,eg_v);
+ sub_(eg_A,eg_C);
+ sub_(eg_B,eg_D);
+ } else { //eg_v > eg_u
+ sub_(eg_v,eg_u);
+ sub_(eg_C,eg_A);
+ sub_(eg_D,eg_B);
+ }
+
+ if (equalsInt(eg_u,0)) {
+ if (negative(eg_C)) //make sure answer is nonnegative
+ add_(eg_C,n);
+ copy_(x,eg_C);
+
+ if (!equalsInt(eg_v,1)) { //if GCD_(x,n)!=1, then there is no inverse
+ copyInt_(x,0);
+ return 0;
+ }
+ return 1;
+ }
+ }
+}
+
+//return x**(-1) mod n, for integers x and n. Return 0 if there is no inverse
+function inverseModInt_(x,n) {
+ var a=1,b=0,t;
+ for (;;) {
+ if (x==1) return a;
+ if (x==0) return 0;
+ b-=a*Math.floor(n/x);
+ n%=x;
+
+ if (n==1) return b; //to avoid negatives, change this b to n-b, and each -= to +=
+ if (n==0) return 0;
+ a-=b*Math.floor(x/n);
+ x%=n;
+ }
+}
+
+//Given positive bigInts x and y, change the bigints v, a, and b to positive bigInts such that:
+// v = GCD_(x,y) = a*x-b*y
+//The bigInts v, a, b, must have exactly as many elements as the larger of x and y.
+function eGCD_(x,y,v,a,b) {
+ var g=0;
+ var k=Math.max(x.length,y.length);
+ if (eg_u.length!=k) {
+ eg_u=new Array(k);
+ eg_A=new Array(k);
+ eg_B=new Array(k);
+ eg_C=new Array(k);
+ eg_D=new Array(k);
+ }
+ while(!(x[0]&1) && !(y[0]&1)) { //while x and y both even
+ halve_(x);
+ halve_(y);
+ g++;
+ }
+ copy_(eg_u,x);
+ copy_(v,y);
+ copyInt_(eg_A,1);
+ copyInt_(eg_B,0);
+ copyInt_(eg_C,0);
+ copyInt_(eg_D,1);
+ for (;;) {
+ while(!(eg_u[0]&1)) { //while u is even
+ halve_(eg_u);
+ if (!(eg_A[0]&1) && !(eg_B[0]&1)) { //if A==B==0 mod 2
+ halve_(eg_A);
+ halve_(eg_B);
+ } else {
+ add_(eg_A,y); halve_(eg_A);
+ sub_(eg_B,x); halve_(eg_B);
+ }
+ }
+
+ while (!(v[0]&1)) { //while v is even
+ halve_(v);
+ if (!(eg_C[0]&1) && !(eg_D[0]&1)) { //if C==D==0 mod 2
+ halve_(eg_C);
+ halve_(eg_D);
+ } else {
+ add_(eg_C,y); halve_(eg_C);
+ sub_(eg_D,x); halve_(eg_D);
+ }
+ }
+
+ if (!greater(v,eg_u)) { //v<=u
+ sub_(eg_u,v);
+ sub_(eg_A,eg_C);
+ sub_(eg_B,eg_D);
+ } else { //v>u
+ sub_(v,eg_u);
+ sub_(eg_C,eg_A);
+ sub_(eg_D,eg_B);
+ }
+ if (equalsInt(eg_u,0)) {
+ if (negative(eg_C)) { //make sure a (C)is nonnegative
+ add_(eg_C,y);
+ sub_(eg_D,x);
+ }
+ multInt_(eg_D,-1); ///make sure b (D) is nonnegative
+ copy_(a,eg_C);
+ copy_(b,eg_D);
+ leftShift_(v,g);
+ return;
+ }
+ }
+}
+
+
+//is bigInt x negative?
+function negative(x) {
+ return ((x[x.length-1]>>(bpe-1))&1);
+}
+
+
+//is (x << (shift*bpe)) > y?
+//x and y are nonnegative bigInts
+//shift is a nonnegative integer
+function greaterShift(x,y,shift) {
+ var kx=x.length, ky=y.length;
+ k=((kx+shift)<ky) ? (kx+shift) : ky;
+ for (i=ky-1-shift; i<kx && i>=0; i++)
+ if (x[i]>0)
+ return 1; //if there are nonzeros in x to the left of the first column of y, then x is bigger
+ for (i=kx-1+shift; i<ky; i++)
+ if (y[i]>0)
+ return 0; //if there are nonzeros in y to the left of the first column of x, then x is not bigger
+ for (i=k-1; i>=shift; i--)
+ if (x[i-shift]>y[i]) return 1;
+ else if (x[i-shift]<y[i]) return 0;
+ return 0;
+}
+
+//is x > y? (x and y both nonnegative)
+function greater(x,y) {
+ var i;
+ var k=(x.length<y.length) ? x.length : y.length;
+
+ for (i=x.length;i<y.length;i++)
+ if (y[i])
+ return 0; //y has more digits
+
+ for (i=y.length;i<x.length;i++)
+ if (x[i])
+ return 1; //x has more digits
+
+ for (i=k-1;i>=0;i--)
+ if (x[i]>y[i])
+ return 1;
+ else if (x[i]<y[i])
+ return 0;
+ return 0;
+}
+
+//divide_ x by y giving quotient q and remainder r. (q=floor(x/y), r=x mod y). All 4 are bigints.
+//x must have at least one leading zero element.
+//y must be nonzero.
+//q and r must be arrays that are exactly the same length as x.
+//the x array must have at least as many elements as y.
+function divide_(x,y,q,r) {
+ var kx, ky;
+ var i,j,y1,y2,c,a,b;
+ copy_(r,x);
+ for (ky=y.length;y[ky-1]==0;ky--); //kx,ky is number of elements in x,y, not including leading zeros
+ for (kx=r.length;r[kx-1]==0 && kx>ky;kx--);
+
+ //normalize: ensure the most significant element of y has its highest bit set
+ b=y[ky-1];
+ for (a=0; b; a++)
+ b>>=1;
+ a=bpe-a; //a is how many bits to shift so that the high order bit of y is leftmost in its array element
+ leftShift_(y,a); //multiply both by 1<<a now, then divide_ both by that at the end
+ leftShift_(r,a);
+
+ copyInt_(q,0); // q=0
+ while (!greaterShift(y,r,kx-ky)) { // while (leftShift_(y,kx-ky) <= r) {
+ subShift_(r,y,kx-ky); // r=r-leftShift_(y,kx-ky)
+ q[kx-ky]++; // q[kx-ky]++;
+ } // }
+
+ for (i=kx-1; i>=ky; i--) {
+ if (r[i]==y[ky-1])
+ q[i-ky]=mask;
+ else
+ q[i-ky]=Math.floor((r[i]*radix+r[i-1])/y[ky-1]);
+
+ //The following for(;;) loop is equivalent to the commented while loop,
+ //except that the uncommented version avoids overflow.
+ //The commented loop comes from HAC, which assumes r[-1]==y[-1]==0
+ // while (q[i-ky]*(y[ky-1]*radix+y[ky-2]) > r[i]*radix*radix+r[i-1]*radix+r[i-2])
+ // q[i-ky]--;
+ for (;;) {
+ y2=(ky>1 ? y[ky-2] : 0)*q[i-ky];
+ c=y2>>bpe;
+ y2=y2 & mask;
+ y1=c+q[i-ky]*y[ky-1];
+ c=y1>>bpe;
+ y1=y1 & mask;
+
+ if (c==r[i] ? y1==r[i-1] ? y2>(i>1 ? r[i-2] : 0) : y1>r[i-1] : c>r[i])
+ q[i-ky]--;
+ else
+ break;
+ }
+
+ linCombShift_(r,y,-q[i-ky],i-ky); //r=r-q[i-ky]*leftShift_(y,i-ky)
+ if (negative(r)) {
+ addShift_(r,y,i-ky); //r=r+leftShift_(y,i-ky)
+ q[i-ky]--;
+ }
+ }
+
+ rightShift_(y,a); //undo the normalization step
+ rightShift_(r,a); //undo the normalization step
+}
+
+//do carries and borrows so each element of the bigInt x fits in bpe bits.
+function carry_(x) {
+ var i,k,c,b;
+ k=x.length;
+ c=0;
+ for (i=0;i<k;i++) {
+ c+=x[i];
+ b=0;
+ if (c<0) {
+ b=-(c>>bpe);
+ c+=b*radix;
+ }
+ x[i]=c & mask;
+ c=(c>>bpe)-b;
+ }
+}
+
+//return x mod n for bigInt x and integer n.
+function modInt(x,n) {
+ var i,c=0;
+ for (i=x.length-1; i>=0; i--)
+ c=(c*radix+x[i])%n;
+ return c;
+}
+
+//convert the integer t into a bigInt with at least the given number of bits.
+//the returned array stores the bigInt in bpe-bit chunks, little endian (buff[0] is least significant word)
+//Pad the array with leading zeros so that it has at least minSize elements.
+//There will always be at least one leading 0 element.
+function int2bigInt(t,bits,minSize) {
+ var i,k;
+ k=Math.ceil(bits/bpe)+1;
+ k=minSize>k ? minSize : k;
+ buff=new Array(k);
+ copyInt_(buff,t);
+ return buff;
+}
+
+//return the bigInt given a string representation in a given base.
+//Pad the array with leading zeros so that it has at least minSize elements.
+//If base=-1, then it reads in a space-separated list of array elements in decimal.
+//The array will always have at least one leading zero, unless base=-1.
+function str2bigInt(s,base,minSize) {
+ var d, i, j, x, y, kk;
+ var k=s.length;
+ if (base==-1) { //comma-separated list of array elements in decimal
+ x=new Array(0);
+ for (;;) {
+ y=new Array(x.length+1);
+ for (i=0;i<x.length;i++)
+ y[i+1]=x[i];
+ y[0]=parseInt(s,10);
+ x=y;
+ d=s.indexOf(',',0);
+ if (d<1)
+ break;
+ s=s.substring(d+1);
+ if (s.length==0)
+ break;
+ }
+ if (x.length<minSize) {
+ y=new Array(minSize);
+ copy_(y,x);
+ return y;
+ }
+ return x;
+ }
+
+ x=int2bigInt(0,base*k,0);
+ for (i=0;i<k;i++) {
+ d=digitsStr.indexOf(s.substring(i,i+1),0);
+ if (base<=36 && d>=36) //convert lowercase to uppercase if base<=36
+ d-=26;
+ if (d<base && d>=0) { //ignore illegal characters
+ multInt_(x,base);
+ addInt_(x,d);
+ }
+ }
+
+ for (k=x.length;k>0 && !x[k-1];k--); //strip off leading zeros
+ k=minSize>k+1 ? minSize : k+1;
+ y=new Array(k);
+ kk=k<x.length ? k : x.length;
+ for (i=0;i<kk;i++)
+ y[i]=x[i];
+ for (;i<k;i++)
+ y[i]=0;
+ return y;
+}
+
+//is bigint x equal to integer y?
+//y must have less than bpe bits
+function equalsInt(x,y) {
+ var i;
+ if (x[0]!=y)
+ return 0;
+ for (i=1;i<x.length;i++)
+ if (x[i])
+ return 0;
+ return 1;
+}
+
+//are bigints x and y equal?
+//this works even if x and y are different lengths and have arbitrarily many leading zeros
+function equals(x,y) {
+ var i;
+ var k=x.length<y.length ? x.length : y.length;
+ for (i=0;i<k;i++)
+ if (x[i]!=y[i])
+ return 0;
+ if (x.length>y.length) {
+ for (;i<x.length;i++)
+ if (x[i])
+ return 0;
+ } else {
+ for (;i<y.length;i++)
+ if (y[i])
+ return 0;
+ }
+ return 1;
+}
+
+//is the bigInt x equal to zero?
+function isZero(x) {
+ var i;
+ for (i=0;i<x.length;i++)
+ if (x[i])
+ return 0;
+ return 1;
+}
+
+//convert a bigInt into a string in a given base, from base 2 up to base 95.
+//Base -1 prints the contents of the array representing the number.
+function bigInt2str(x,base) {
+ var i,t,s="";
+
+ if (s6.length!=x.length)
+ s6=dup(x);
+ else
+ copy_(s6,x);
+
+ if (base==-1) { //return the list of array contents
+ for (i=x.length-1;i>0;i--)
+ s+=x[i]+',';
+ s+=x[0];
+ }
+ else { //return it in the given base
+ while (!isZero(s6)) {
+ t=divInt_(s6,base); //t=s6 % base; s6=floor(s6/base);
+ s=digitsStr.substring(t,t+1)+s;
+ }
+ }
+ if (s.length==0)
+ s="0";
+ return s;
+}
+
+//returns a duplicate of bigInt x
+function dup(x) {
+ var i;
+ buff=new Array(x.length);
+ copy_(buff,x);
+ return buff;
+}
+
+//do x=y on bigInts x and y. x must be an array at least as big as y (not counting the leading zeros in y).
+function copy_(x,y) {
+ var i;
+ var k=x.length<y.length ? x.length : y.length;
+ for (i=0;i<k;i++)
+ x[i]=y[i];
+ for (i=k;i<x.length;i++)
+ x[i]=0;
+}
+
+//do x=y on bigInt x and integer y.
+function copyInt_(x,n) {
+ var i,c;
+ for (c=n,i=0;i<x.length;i++) {
+ x[i]=c & mask;
+ c>>=bpe;
+ }
+}
+
+//do x=x+n where x is a bigInt and n is an integer.
+//x must be large enough to hold the result.
+function addInt_(x,n) {
+ var i,k,c,b;
+ x[0]+=n;
+ k=x.length;
+ c=0;
+ for (i=0;i<k;i++) {
+ c+=x[i];
+ b=0;
+ if (c<0) {
+ b=-(c>>bpe);
+ c+=b*radix;
+ }
+ x[i]=c & mask;
+ c=(c>>bpe)-b;
+ if (!c) return; //stop carrying as soon as the carry_ is zero
+ }
+}
+
+//right shift bigInt x by n bits. 0 <= n < bpe.
+function rightShift_(x,n) {
+ var i;
+ var k=Math.floor(n/bpe);
+ if (k) {
+ for (i=0;i<x.length-k;i++) //right shift x by k elements
+ x[i]=x[i+k];
+ for (;i<x.length;i++)
+ x[i]=0;
+ n%=bpe;
+ }
+ for (i=0;i<x.length-1;i++) {
+ x[i]=mask & ((x[i+1]<<(bpe-n)) | (x[i]>>n));
+ }
+ x[i]>>=n;
+}
+
+//do x=floor(|x|/2)*sgn(x) for bigInt x in 2's complement
+function halve_(x) {
+ var i;
+ for (i=0;i<x.length-1;i++) {
+ x[i]=mask & ((x[i+1]<<(bpe-1)) | (x[i]>>1));
+ }
+ x[i]=(x[i]>>1) | (x[i] & (radix>>1)); //most significant bit stays the same
+}
+
+//left shift bigInt x by n bits.
+function leftShift_(x,n) {
+ var i;
+ var k=Math.floor(n/bpe);
+ if (k) {
+ for (i=x.length; i>=k; i--) //left shift x by k elements
+ x[i]=x[i-k];
+ for (;i>=0;i--)
+ x[i]=0;
+ n%=bpe;
+ }
+ if (!n)
+ return;
+ for (i=x.length-1;i>0;i--) {
+ x[i]=mask & ((x[i]<<n) | (x[i-1]>>(bpe-n)));
+ }
+ x[i]=mask & (x[i]<<n);
+}
+
+//do x=x*n where x is a bigInt and n is an integer.
+//x must be large enough to hold the result.
+function multInt_(x,n) {
+ var i,k,c,b;
+ if (!n)
+ return;
+ k=x.length;
+ c=0;
+ for (i=0;i<k;i++) {
+ c+=x[i]*n;
+ b=0;
+ if (c<0) {
+ b=-(c>>bpe);
+ c+=b*radix;
+ }
+ x[i]=c & mask;
+ c=(c>>bpe)-b;
+ }
+}
+
+//do x=floor(x/n) for bigInt x and integer n, and return the remainder
+function divInt_(x,n) {
+ var i,r=0,s;
+ for (i=x.length-1;i>=0;i--) {
+ s=r*radix+x[i];
+ x[i]=Math.floor(s/n);
+ r=s%n;
+ }
+ return r;
+}
+
+//do the linear combination x=a*x+b*y for bigInts x and y, and integers a and b.
+//x must be large enough to hold the answer.
+function linComb_(x,y,a,b) {
+ var i,c,k,kk;
+ k=x.length<y.length ? x.length : y.length;
+ kk=x.length;
+ for (c=0,i=0;i<k;i++) {
+ c+=a*x[i]+b*y[i];
+ x[i]=c & mask;
+ c>>=bpe;
+ }
+ for (i=k;i<kk;i++) {
+ c+=a*x[i];
+ x[i]=c & mask;
+ c>>=bpe;
+ }
+}
+
+//do the linear combination x=a*x+b*(y<<(ys*bpe)) for bigInts x and y, and integers a, b and ys.
+//x must be large enough to hold the answer.
+function linCombShift_(x,y,b,ys) {
+ var i,c,k,kk;
+ k=x.length<ys+y.length ? x.length : ys+y.length;
+ kk=x.length;
+ for (c=0,i=ys;i<k;i++) {
+ c+=x[i]+b*y[i-ys];
+ x[i]=c & mask;
+ c>>=bpe;
+ }
+ for (i=k;c && i<kk;i++) {
+ c+=x[i];
+ x[i]=c & mask;
+ c>>=bpe;
+ }
+}
+
+//do x=x+(y<<(ys*bpe)) for bigInts x and y, and integers a,b and ys.
+//x must be large enough to hold the answer.
+function addShift_(x,y,ys) {
+ var i,c,k,kk;
+ k=x.length<ys+y.length ? x.length : ys+y.length;
+ kk=x.length;
+ for (c=0,i=ys;i<k;i++) {
+ c+=x[i]+y[i-ys];
+ x[i]=c & mask;
+ c>>=bpe;
+ }
+ for (i=k;c && i<kk;i++) {
+ c+=x[i];
+ x[i]=c & mask;
+ c>>=bpe;
+ }
+}
+
+//do x=x-(y<<(ys*bpe)) for bigInts x and y, and integers a,b and ys.
+//x must be large enough to hold the answer.
+function subShift_(x,y,ys) {
+ var i,c,k,kk;
+ k=x.length<ys+y.length ? x.length : ys+y.length;
+ kk=x.length;
+ for (c=0,i=ys;i<k;i++) {
+ c+=x[i]-y[i-ys];
+ x[i]=c & mask;
+ c>>=bpe;
+ }
+ for (i=k;c && i<kk;i++) {
+ c+=x[i];
+ x[i]=c & mask;
+ c>>=bpe;
+ }
+}
+
+//do x=x-y for bigInts x and y.
+//x must be large enough to hold the answer.
+//negative answers will be 2s complement
+function sub_(x,y) {
+ var i,c,k,kk;
+ k=x.length<y.length ? x.length : y.length;
+ for (c=0,i=0;i<k;i++) {
+ c+=x[i]-y[i];
+ x[i]=c & mask;
+ c>>=bpe;
+ }
+ for (i=k;c && i<x.length;i++) {
+ c+=x[i];
+ x[i]=c & mask;
+ c>>=bpe;
+ }
+}
+
+//do x=x+y for bigInts x and y.
+//x must be large enough to hold the answer.
+function add_(x,y) {
+ var i,c,k,kk;
+ k=x.length<y.length ? x.length : y.length;
+ for (c=0,i=0;i<k;i++) {
+ c+=x[i]+y[i];
+ x[i]=c & mask;
+ c>>=bpe;
+ }
+ for (i=k;c && i<x.length;i++) {
+ c+=x[i];
+ x[i]=c & mask;
+ c>>=bpe;
+ }
+}
+
+//do x=x*y for bigInts x and y. This is faster when y<x.
+function mult_(x,y) {
+ var i;
+ if (ss.length!=2*x.length)
+ ss=new Array(2*x.length);
+ copyInt_(ss,0);
+ for (i=0;i<y.length;i++)
+ if (y[i])
+ linCombShift_(ss,x,y[i],i); //ss=1*ss+y[i]*(x<<(i*bpe))
+ copy_(x,ss);
+}
+
+//do x=x mod n for bigInts x and n.
+function mod_(x,n) {
+ if (s4.length!=x.length)
+ s4=dup(x);
+ else
+ copy_(s4,x);
+ if (s5.length!=x.length)
+ s5=dup(x);
+ divide_(s4,n,s5,x); //x = remainder of s4 / n
+}
+
+//do x=x*y mod n for bigInts x,y,n.
+//for greater speed, let y<x.
+function multMod_(x,y,n) {
+ var i;
+ if (s0.length!=2*x.length)
+ s0=new Array(2*x.length);
+ copyInt_(s0,0);
+ for (i=0;i<y.length;i++)
+ if (y[i])
+ linCombShift_(s0,x,y[i],i); //s0=1*s0+y[i]*(x<<(i*bpe))
+ mod_(s0,n);
+ copy_(x,s0);
+}
+
+//do x=x*x mod n for bigInts x,n.
+function squareMod_(x,n) {
+ var i,j,d,c,kx,kn,k;
+ for (kx=x.length; kx>0 && !x[kx-1]; kx--); //ignore leading zeros in x
+ k=kx>n.length ? 2*kx : 2*n.length; //k=# elements in the product, which is twice the elements in the larger of x and n
+ if (s0.length!=k)
+ s0=new Array(k);
+ copyInt_(s0,0);
+ for (i=0;i<kx;i++) {
+ c=s0[2*i]+x[i]*x[i];
+ s0[2*i]=c & mask;
+ c>>=bpe;
+ for (j=i+1;j<kx;j++) {
+ c=s0[i+j]+2*x[i]*x[j]+c;
+ s0[i+j]=(c & mask);
+ c>>=bpe;
+ }
+ s0[i+kx]=c;
+ }
+ mod_(s0,n);
+ copy_(x,s0);
+}
+
+//return x with exactly k leading zero elements
+function trim(x,k) {
+ var i,y;
+ for (i=x.length; i>0 && !x[i-1]; i--);
+ y=new Array(i+k);
+ copy_(y,x);
+ return y;
+}
+
+//do x=x**y mod n, where x,y,n are bigInts and ** is exponentiation. 0**0=1.
+//this is faster when n is odd. x usually needs to have as many elements as n.
+function powMod_(x,y,n) {
+ var k1,k2,kn,np;
+ if(s7.length!=n.length)
+ s7=dup(n);
+
+ //for even modulus, use a simple square-and-multiply algorithm,
+ //rather than using the more complex Montgomery algorithm.
+ if ((n[0]&1)==0) {
+ copy_(s7,x);
+ copyInt_(x,1);
+ while(!equalsInt(y,0)) {
+ if (y[0]&1)
+ multMod_(x,s7,n);
+ divInt_(y,2);
+ squareMod_(s7,n);
+ }
+ return;
+ }
+
+ //calculate np from n for the Montgomery multiplications
+ copyInt_(s7,0);
+ for (kn=n.length;kn>0 && !n[kn-1];kn--);
+ np=radix-inverseModInt_(modInt(n,radix),radix);
+ s7[kn]=1;
+ multMod_(x ,s7,n); // x = x * 2**(kn*bp) mod n
+
+ if (s3.length!=x.length)
+ s3=dup(x);
+ else
+ copy_(s3,x);
+
+ for (k1=y.length-1;k1>0 & !y[k1]; k1--); //k1=first nonzero element of y
+ if (y[k1]==0) { //anything to the 0th power is 1
+ copyInt_(x,1);
+ return;
+ }
+ for (k2=1<<(bpe-1);k2 && !(y[k1] & k2); k2>>=1); //k2=position of first 1 bit in y[k1]
+ for (;;) {
+ if (!(k2>>=1)) { //look at next bit of y
+ k1--;
+ if (k1<0) {
+ mont_(x,one,n,np);
+ return;
+ }
+ k2=1<<(bpe-1);
+ }
+ mont_(x,x,n,np);
+
+ if (k2 & y[k1]) //if next bit is a 1
+ mont_(x,s3,n,np);
+ }
+}
+
+//do x=x*y*Ri mod n for bigInts x,y,n,
+// where Ri = 2**(-kn*bpe) mod n, and kn is the
+// number of elements in the n array, not
+// counting leading zeros.
+//x must be large enough to hold the answer.
+//It's OK if x and y are the same variable.
+//must have:
+// x,y < n
+// n is odd
+// np = -(n^(-1)) mod radix
+function mont_(x,y,n,np) {
+ var i,j,c,ui,t;
+ var kn=n.length;
+ var ky=y.length;
+
+ if (sa.length!=kn)
+ sa=new Array(kn);
+
+ for (;kn>0 && n[kn-1]==0;kn--); //ignore leading zeros of n
+ //this function sometimes gives wrong answers when the next line is uncommented
+ //for (;ky>0 && y[ky-1]==0;ky--); //ignore leading zeros of y
+
+ copyInt_(sa,0);
+
+ //the following loop consumes 95% of the runtime for randTruePrime_() and powMod_() for large keys
+ for (i=0; i<kn; i++) {
+ t=sa[0]+x[i]*y[0];
+ ui=((t & mask) * np) & mask; //the inner "& mask" is needed on Macintosh MSIE, but not windows MSIE
+ c=(t+ui*n[0]) >> bpe;
+ t=x[i];
+
+ //do sa=(sa+x[i]*y+ui*n)/b where b=2**bpe
+ for (j=1;j<ky;j++) {
+ c+=sa[j]+t*y[j]+ui*n[j];
+ sa[j-1]=c & mask;
+ c>>=bpe;
+ }
+ for (;j<kn;j++) {
+ c+=sa[j]+ui*n[j];
+ sa[j-1]=c & mask;
+ c>>=bpe;
+ }
+ sa[j-1]=c & mask;
+ }
+
+ if (!greater(n,sa))
+ sub_(sa,n);
+ copy_(x,sa);
+}
+
+
+
+
+//#############################################################################
+//#############################################################################
+//#############################################################################
+//#############################################################################
+//#############################################################################
+//#############################################################################
+//#############################################################################
+
+
+
+
+
+//#############################################################################
+
+Clipperz.Crypto.BigInt = function (aValue, aBase) {
+ var base;
+ var value;
+
+ if (typeof(aValue) == 'object') {
+ this._internalValue = aValue;
+ } else {
+ if (typeof(aValue) == 'undefined') {
+ value = "0";
+ } else {
+ value = aValue + "";
+ }
+
+ if (typeof(aBase) == 'undefined') {
+ base = 10;
+ } else {
+ base = aBase;
+ }
+
+ this._internalValue = str2bigInt(value, base, 1, 1);
+ }
+
+ return this;
+}
+
+//=============================================================================
+
+MochiKit.Base.update(Clipperz.Crypto.BigInt.prototype, {
+
+ 'clone': function() {
+ return new Clipperz.Crypto.BigInt(this.internalValue());
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'internalValue': function () {
+ return this._internalValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'isBigInt': true,
+
+ //-------------------------------------------------------------------------
+
+ 'toString': function(aBase) {
+ return this.asString(aBase);
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'asString': function (aBase, minimumLength) {
+ var result;
+ var base;
+
+ if (typeof(aBase) == 'undefined') {
+ base = 10;
+ } else {
+ base = aBase;
+ }
+
+ result = bigInt2str(this.internalValue(), base).toLowerCase();
+
+ if ((typeof(minimumLength) != 'undefined') && (result.length < minimumLength)) {
+ var i, c;
+//MochiKit.Logging.logDebug(">>> FIXING BigInt.asString length issue")
+ c = (minimumLength - result.length);
+ for (i=0; i<c; i++) {
+ result = '0' + result;
+ }
+ }
+
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'asByteArray': function() {
+ return new Clipperz.ByteArray("0x" + this.asString(16), 16);
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'equals': function (aValue) {
+ var result;
+
+ if (aValue.isBigInt) {
+ result = equals(this.internalValue(), aValue.internalValue());
+ } else if (typeof(aValue) == "number") {
+ result = equalsInt(this.internalValue(), aValue);
+ } else {
+ throw Clipperz.Crypt.BigInt.exception.UnknownType;
+ }
+
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'compare': function(aValue) {
+/*
+ var result;
+ var thisAsString;
+ var aValueAsString;
+
+ thisAsString = this.asString(10);
+ aValueAsString = aValue.asString(10);
+
+ result = MochiKit.Base.compare(thisAsString.length, aValueAsString.length);
+ if (result == 0) {
+ result = MochiKit.Base.compare(thisAsString, aValueAsString);
+ }
+
+ return result;
+*/
+ var result;
+
+ if (equals(this.internalValue(), aValue.internalValue())) {
+ result = 0;
+ } else if (greater(this.internalValue(), aValue.internalValue())) {
+ result = 1;
+ } else {
+ result = -1;
+ }
+
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'add': function (aValue) {
+ var result;
+
+ if (aValue.isBigInt) {
+ result = add(this.internalValue(), aValue.internalValue());
+ } else {
+ result = addInt(this.internalValue(), aValue);
+ }
+
+ return new Clipperz.Crypto.BigInt(result);
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'subtract': function (aValue) {
+ var result;
+ var value;
+
+ if (aValue.isBigInt) {
+ value = aValue;
+ } else {
+ value = new Clipperz.Crypto.BigInt(aValue);
+ }
+
+ result = sub(this.internalValue(), value.internalValue());
+
+ return new Clipperz.Crypto.BigInt(result);
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'multiply': function (aValue, aModule) {
+ var result;
+ var value;
+
+ if (aValue.isBigInt) {
+ value = aValue;
+ } else {
+ value = new Clipperz.Crypto.BigInt(aValue);
+ }
+
+ if (typeof(aModule) == 'undefined') {
+ result = mult(this.internalValue(), value.internalValue());
+ } else {
+ if (greater(this.internalValue(), value.internalValue())) {
+ result = multMod(this.internalValue(), value.internalValue(), aModule);
+ } else {
+ result = multMod(value.internalValue(), this.internalValue(), aModule);
+ }
+ }
+
+ return new Clipperz.Crypto.BigInt(result);
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'module': function (aModule) {
+ var result;
+ var module;
+
+ if (aModule.isBigInt) {
+ module = aModule;
+ } else {
+ module = new Clipperz.Crypto.BigInt(aModule);
+ }
+
+ result = mod(this.internalValue(), module.internalValue());
+
+ return new Clipperz.Crypto.BigInt(result);
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'powerModule': function(aValue, aModule) {
+ var result;
+ var value;
+ var module;
+
+ if (aValue.isBigInt) {
+ value = aValue;
+ } else {
+ value = new Clipperz.Crypto.BigInt(aValue);
+ }
+
+ if (aModule.isBigInt) {
+ module = aModule;
+ } else {
+ module = new Clipperz.Crypto.BigInt(aModule);
+ }
+
+ if (aValue == -1) {
+ result = inverseMod(this.internalValue(), module.internalValue());
+ } else {
+ result = powMod(this.internalValue(), value.internalValue(), module.internalValue());
+ }
+
+ return new Clipperz.Crypto.BigInt(result);
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'xor': function(aValue) {
+ var result;
+ var thisByteArray;
+ var aValueByteArray;
+ var xorArray;
+
+ thisByteArray = new Clipperz.ByteArray("0x" + this.asString(16), 16);
+ aValueByteArray = new Clipperz.ByteArray("0x" + aValue.asString(16), 16);
+ xorArray = thisByteArray.xorMergeWithBlock(aValueByteArray, 'right');
+ result = new Clipperz.Crypto.BigInt(xorArray.toHexString(), 16);
+
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'shiftLeft': function(aNumberOfBitsToShift) {
+ var result;
+ var internalResult;
+ var wholeByteToShift;
+ var bitsLeftToShift;
+
+ wholeByteToShift = Math.floor(aNumberOfBitsToShift / 8);
+ bitsLeftToShift = aNumberOfBitsToShift % 8;
+
+ if (wholeByteToShift == 0) {
+ internalResult = this.internalValue();
+ } else {
+ var hexValue;
+ var i,c;
+
+ hexValue = this.asString(16);
+ c = wholeByteToShift;
+ for (i=0; i<c; i++) {
+ hexValue += "00";
+ }
+ internalResult = str2bigInt(hexValue, 16, 1, 1);
+ }
+
+ if (bitsLeftToShift > 0) {
+ leftShift_(internalResult, bitsLeftToShift);
+ }
+ result = new Clipperz.Crypto.BigInt(internalResult);
+
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'bitSize': function() {
+ return bitSize(this.internalValue());
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'isBitSet': function(aBitPosition) {
+ var result;
+
+ if (this.asByteArray().bitAtIndex(aBitPosition) == 0) {
+ result = false;
+ } else {
+ result = true;
+ };
+
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+
+});
+
+//#############################################################################
+
+Clipperz.Crypto.BigInt.randomPrime = function(aBitSize) {
+ return new Clipperz.Crypto.BigInt(randTruePrime(aBitSize));
+}
+
+//#############################################################################
+//#############################################################################
+
+Clipperz.Crypto.BigInt.ZERO = new Clipperz.Crypto.BigInt(0);
+
+//#############################################################################
+
+Clipperz.Crypto.BigInt.equals = function(a, b) {
+ return a.equals(b);
+}
+
+Clipperz.Crypto.BigInt.add = function(a, b) {
+ return a.add(b);
+}
+
+Clipperz.Crypto.BigInt.subtract = function(a, b) {
+ return a.subtract(b);
+}
+
+Clipperz.Crypto.BigInt.multiply = function(a, b, module) {
+ return a.multiply(b, module);
+}
+
+Clipperz.Crypto.BigInt.module = function(a, module) {
+ return a.module(module);
+}
+
+Clipperz.Crypto.BigInt.powerModule = function(a, b, module) {
+ return a.powerModule(b, module);
+}
+
+Clipperz.Crypto.BigInt.exception = {
+ UnknownType: new MochiKit.Base.NamedError("Clipperz.Crypto.BigInt.exception.UnknownType")
+}
diff --git a/frontend/beta/js/Clipperz/Crypto/BigInt_scoped.js b/frontend/beta/js/Clipperz/Crypto/BigInt_scoped.js
new file mode 100644
index 0000000..e91e823
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/Crypto/BigInt_scoped.js
@@ -0,0 +1,1649 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
+if (typeof(Clipperz.Crypto) == 'undefined') { Clipperz.Crypto = {}; }
+
+if (typeof(Leemon) == 'undefined') { Leemon = {}; }
+if (typeof(Baird.Crypto) == 'undefined') { Baird.Crypto = {}; }
+if (typeof(Baird.Crypto.BigInt) == 'undefined') { Baird.Crypto.BigInt = {}; }
+
+
+//#############################################################################
+// Downloaded on March 05, 2007 from http://www.leemon.com/crypto/BigInt.js
+//#############################################################################
+
+////////////////////////////////////////////////////////////////////////////////////////
+// Big Integer Library v. 5.0
+// Created 2000, last modified 2006
+// Leemon Baird
+// www.leemon.com
+//
+// This file is public domain. You can use it for any purpose without restriction.
+// I do not guarantee that it is correct, so use it at your own risk. If you use
+// it for something interesting, I'd appreciate hearing about it. If you find
+// any bugs or make any improvements, I'd appreciate hearing about those too.
+// It would also be nice if my name and address were left in the comments.
+// But none of that is required.
+//
+// This code defines a bigInt library for arbitrary-precision integers.
+// A bigInt is an array of integers storing the value in chunks of bpe bits,
+// little endian (buff[0] is the least significant word).
+// Negative bigInts are stored two's complement.
+// Some functions assume their parameters have at least one leading zero element.
+// Functions with an underscore at the end of the name have unpredictable behavior in case of overflow,
+// so the caller must make sure overflow won't happen.
+// For each function where a parameter is modified, that same
+// variable must not be used as another argument too.
+// So, you cannot square x by doing multMod_(x,x,n).
+// You must use squareMod_(x,n) instead, or do y=dup(x); multMod_(x,y,n).
+//
+// These functions are designed to avoid frequent dynamic memory allocation in the inner loop.
+// For most functions, if it needs a BigInt as a local variable it will actually use
+// a global, and will only allocate to it when it's not the right size. This ensures
+// that when a function is called repeatedly with same-sized parameters, it only allocates
+// memory on the first call.
+//
+// Note that for cryptographic purposes, the calls to Math.random() must
+// be replaced with calls to a better pseudorandom number generator.
+//
+// In the following, "bigInt" means a bigInt with at least one leading zero element,
+// and "integer" means a nonnegative integer less than radix. In some cases, integer
+// can be negative. Negative bigInts are 2s complement.
+//
+// The following functions do not modify their inputs, but dynamically allocate memory every time they are called:
+//
+// function bigInt2str(x,base) //convert a bigInt into a string in a given base, from base 2 up to base 95
+// function dup(x) //returns a copy of bigInt x
+// function findPrimes(n) //return array of all primes less than integer n
+// function int2bigInt(t,n,m) //convert integer t to a bigInt with at least n bits and m array elements
+// function str2bigInt(s,b,n,m) //convert string s in base b to a bigInt with at least n bits and m array elements
+// function trim(x,k) //return a copy of x with exactly k leading zero elements
+//
+// The following functions do not modify their inputs, so there is never a problem with the result being too big:
+//
+// function bitSize(x) //returns how many bits long the bigInt x is, not counting leading zeros
+// function equals(x,y) //is the bigInt x equal to the bigint y?
+// function equalsInt(x,y) //is bigint x equal to integer y?
+// function greater(x,y) //is x>y? (x and y are nonnegative bigInts)
+// function greaterShift(x,y,shift)//is (x <<(shift*bpe)) > y?
+// function isZero(x) //is the bigInt x equal to zero?
+// function millerRabin(x,b) //does one round of Miller-Rabin base integer b say that bigInt x is possibly prime (as opposed to definitely composite)?
+// function modInt(x,n) //return x mod n for bigInt x and integer n.
+// function negative(x) //is bigInt x negative?
+//
+// The following functions do not modify their inputs, but allocate memory and call functions with underscores
+//
+// function add(x,y) //return (x+y) for bigInts x and y.
+// function addInt(x,n) //return (x+n) where x is a bigInt and n is an integer.
+// function expand(x,n) //return a copy of x with at least n elements, adding leading zeros if needed
+// function inverseMod(x,n) //return (x**(-1) mod n) for bigInts x and n. If no inverse exists, it returns null
+// function mod(x,n) //return a new bigInt equal to (x mod n) for bigInts x and n.
+// function mult(x,y) //return x*y for bigInts x and y. This is faster when y<x.
+// function multMod(x,y,n) //return (x*y mod n) for bigInts x,y,n. For greater speed, let y<x.
+// function powMod(x,y,n) //return (x**y mod n) where x,y,n are bigInts and ** is exponentiation. 0**0=1. Faster for odd n.
+// function randTruePrime(k) //return a new, random, k-bit, true prime using Maurer's algorithm.
+// function sub(x,y) //return (x-y) for bigInts x and y. Negative answers will be 2s complement
+//
+// The following functions write a bigInt result to one of the parameters, but
+// the result is never bigger than the original, so there can't be overflow problems:
+//
+// function divInt_(x,n) //do x=floor(x/n) for bigInt x and integer n, and return the remainder
+// function GCD_(x,y) //set x to the greatest common divisor of bigInts x and y, (y is destroyed).
+// function halve_(x) //do x=floor(|x|/2)*sgn(x) for bigInt x in 2's complement
+// function mod_(x,n) //do x=x mod n for bigInts x and n.
+// function rightShift_(x,n) //right shift bigInt x by n bits. 0 <= n < bpe.
+//
+// The following functions write a bigInt result to one of the parameters. The caller is responsible for
+// ensuring it is large enough to hold the result.
+//
+// function addInt_(x,n) //do x=x+n where x is a bigInt and n is an integer
+// function add_(x,y) //do x=x+y for bigInts x and y
+// function addShift_(x,y,ys) //do x=x+(y<<(ys*bpe))
+// function copy_(x,y) //do x=y on bigInts x and y
+// function copyInt_(x,n) //do x=n on bigInt x and integer n
+// function carry_(x) //do carries and borrows so each element of the bigInt x fits in bpe bits.
+// function divide_(x,y,q,r) //divide_ x by y giving quotient q and remainder r
+// function eGCD_(x,y,d,a,b) //sets a,b,d to positive big integers such that d = GCD_(x,y) = a*x-b*y
+// function inverseMod_(x,n) //do x=x**(-1) mod n, for bigInts x and n. Returns 1 (0) if inverse does (doesn't) exist
+// function inverseModInt_(x,n) //return x**(-1) mod n, for integers x and n. Return 0 if there is no inverse
+// function leftShift_(x,n) //left shift bigInt x by n bits. n<bpe.
+// function linComb_(x,y,a,b) //do x=a*x+b*y for bigInts x and y and integers a and b
+// function linCombShift_(x,y,b,ys) //do x=x+b*(y<<(ys*bpe)) for bigInts x and y, and integers b and ys
+// function mont_(x,y,n,np) //Montgomery multiplication (see comments where the function is defined)
+// function mult_(x,y) //do x=x*y for bigInts x and y.
+// function multInt_(x,n) //do x=x*n where x is a bigInt and n is an integer.
+// function multMod_(x,y,n) //do x=x*y mod n for bigInts x,y,n.
+// function powMod_(x,y,n) //do x=x**y mod n, where x,y,n are bigInts (n is odd) and ** is exponentiation. 0**0=1.
+// function randBigInt_(b,n,s) //do b = an n-bit random BigInt. if s=1, then nth bit (most significant bit) is set to 1. n>=1.
+// function randTruePrime_(ans,k) //do ans = a random k-bit true random prime (not just probable prime) with 1 in the msb.
+// function squareMod_(x,n) //do x=x*x mod n for bigInts x,n
+// function sub_(x,y) //do x=x-y for bigInts x and y. Negative answers will be 2s complement.
+// function subShift_(x,y,ys) //do x=x-(y<<(ys*bpe)). Negative answers will be 2s complement.
+//
+// The following functions are based on algorithms from the _Handbook of Applied Cryptography_
+// powMod_() = algorithm 14.94, Montgomery exponentiation
+// eGCD_,inverseMod_() = algorithm 14.61, Binary extended GCD_
+// GCD_() = algorothm 14.57, Lehmer's algorithm
+// mont_() = algorithm 14.36, Montgomery multiplication
+// divide_() = algorithm 14.20 Multiple-precision division
+// squareMod_() = algorithm 14.16 Multiple-precision squaring
+// randTruePrime_() = algorithm 4.62, Maurer's algorithm
+// millerRabin() = algorithm 4.24, Miller-Rabin algorithm
+//
+// Profiling shows:
+// randTruePrime_() spends:
+// 10% of its time in calls to powMod_()
+// 85% of its time in calls to millerRabin()
+// millerRabin() spends:
+// 99% of its time in calls to powMod_() (always with a base of 2)
+// powMod_() spends:
+// 94% of its time in calls to mont_() (almost always with x==y)
+//
+// This suggests there are several ways to speed up this library slightly:
+// - convert powMod_ to use a Montgomery form of k-ary window (or maybe a Montgomery form of sliding window)
+// -- this should especially focus on being fast when raising 2 to a power mod n
+// - convert randTruePrime_() to use a minimum r of 1/3 instead of 1/2 with the appropriate change to the test
+// - tune the parameters in randTruePrime_(), including c, m, and recLimit
+// - speed up the single loop in mont_() that takes 95% of the runtime, perhaps by reducing checking
+// within the loop when all the parameters are the same length.
+//
+// There are several ideas that look like they wouldn't help much at all:
+// - replacing trial division in randTruePrime_() with a sieve (that speeds up something taking almost no time anyway)
+// - increase bpe from 15 to 30 (that would help if we had a 32*32->64 multiplier, but not with JavaScript's 32*32->32)
+// - speeding up mont_(x,y,n,np) when x==y by doing a non-modular, non-Montgomery square
+// followed by a Montgomery reduction. The intermediate answer will be twice as long as x, so that
+// method would be slower. This is unfortunate because the code currently spends almost all of its time
+// doing mont_(x,x,...), both for randTruePrime_() and powMod_(). A faster method for Montgomery squaring
+// would have a large impact on the speed of randTruePrime_() and powMod_(). HAC has a couple of poorly-worded
+// sentences that seem to imply it's faster to do a non-modular square followed by a single
+// Montgomery reduction, but that's obviously wrong.
+////////////////////////////////////////////////////////////////////////////////////////
+
+//
+// The whole library has been moved into the Baird.Crypto.BigInt scope by Giulio Cesare Solaroli <giulio.cesare@clipperz.com>
+//
+Baird.Crypto.BigInt.VERSION = "5.0";
+Baird.Crypto.BigInt.NAME = "Baird.Crypto.BigInt";
+
+MochiKit.Base.update(Baird.Crypto.BigInt, {
+ //globals
+ 'bpe': 0, //bits stored per array element
+ 'mask': 0, //AND this with an array element to chop it down to bpe bits
+ 'radix': Baird.Crypto.BigInt.mask + 1, //equals 2^bpe. A single 1 bit to the left of the last bit of mask.
+
+ //the digits for converting to different bases
+ 'digitsStr': '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_=!@#$%^&*()[]{}|;:,.<>/?`~ \\\'\"+-',
+
+//initialize the global variables
+for (bpe=0; (1<<(bpe+1)) > (1<<bpe); bpe++); //bpe=number of bits in the mantissa on this platform
+bpe>>=1; //bpe=number of bits in one element of the array representing the bigInt
+mask=(1<<bpe)-1; //AND the mask with an integer to get its bpe least significant bits
+radix=mask+1; //2^bpe. a single 1 bit to the left of the first bit of mask
+one=int2bigInt(1,1,1); //constant used in powMod_()
+
+//the following global variables are scratchpad memory to
+//reduce dynamic memory allocation in the inner loop
+t=new Array(0);
+ss=t; //used in mult_()
+s0=t; //used in multMod_(), squareMod_()
+s1=t; //used in powMod_(), multMod_(), squareMod_()
+s2=t; //used in powMod_(), multMod_()
+s3=t; //used in powMod_()
+s4=t; s5=t; //used in mod_()
+s6=t; //used in bigInt2str()
+s7=t; //used in powMod_()
+T=t; //used in GCD_()
+sa=t; //used in mont_()
+mr_x1=t; mr_r=t; mr_a=t; //used in millerRabin()
+eg_v=t; eg_u=t; eg_A=t; eg_B=t; eg_C=t; eg_D=t; //used in eGCD_(), inverseMod_()
+md_q1=t; md_q2=t; md_q3=t; md_r=t; md_r1=t; md_r2=t; md_tt=t; //used in mod_()
+
+primes=t; pows=t; s_i=t; s_i2=t; s_R=t; s_rm=t; s_q=t; s_n1=t;
+ s_a=t; s_r2=t; s_n=t; s_b=t; s_d=t; s_x1=t; s_x2=t, s_aa=t; //used in randTruePrime_()
+
+////////////////////////////////////////////////////////////////////////////////////////
+
+ //return array of all primes less than integer n
+ 'findPrimes': function(n) {
+ var i,s,p,ans;
+ s=new Array(n);
+ for (i=0;i<n;i++)
+ s[i]=0;
+ s[0]=2;
+ p=0; //first p elements of s are primes, the rest are a sieve
+ for(;s[p]<n;) { //s[p] is the pth prime
+ for(i=s[p]*s[p]; i<n; i+=s[p]) //mark multiples of s[p]
+ s[i]=1;
+ p++;
+ s[p]=s[p-1]+1;
+ for(; s[p]<n && s[s[p]]; s[p]++); //find next prime (where s[p]==0)
+ }
+ ans=new Array(p);
+ for(i=0;i<p;i++)
+ ans[i]=s[i];
+ return ans;
+ },
+
+ //does a single round of Miller-Rabin base b consider x to be a possible prime?
+ //x is a bigInt, and b is an integer
+ 'millerRabin': function(x,b) {
+ var i,j,k,s;
+
+ if (mr_x1.length!=x.length) {
+ mr_x1=dup(x);
+ mr_r=dup(x);
+ mr_a=dup(x);
+ }
+
+ copyInt_(mr_a,b);
+ copy_(mr_r,x);
+ copy_(mr_x1,x);
+
+ addInt_(mr_r,-1);
+ addInt_(mr_x1,-1);
+
+ //s=the highest power of two that divides mr_r
+ k=0;
+ for (i=0;i<mr_r.length;i++)
+ for (j=1;j<mask;j<<=1)
+ if (x[i] & j) {
+ s=(k<mr_r.length+bpe ? k : 0);
+ i=mr_r.length;
+ j=mask;
+ } else
+ k++;
+
+ if (s)
+ rightShift_(mr_r,s);
+
+ powMod_(mr_a,mr_r,x);
+
+ if (!equalsInt(mr_a,1) && !equals(mr_a,mr_x1)) {
+ j=1;
+ while (j<=s-1 && !equals(mr_a,mr_x1)) {
+ squareMod_(mr_a,x);
+ if (equalsInt(mr_a,1)) {
+ return 0;
+ }
+ j++;
+ }
+ if (!equals(mr_a,mr_x1)) {
+ return 0;
+ }
+ }
+
+ return 1;
+ },
+
+ //returns how many bits long the bigInt is, not counting leading zeros.
+ 'bitSize': function(x) {
+ var j,z,w;
+ for (j=x.length-1; (x[j]==0) && (j>0); j--);
+ for (z=0,w=x[j]; w; (w>>=1),z++);
+ z+=bpe*j;
+ return z;
+ },
+
+ //return a copy of x with at least n elements, adding leading zeros if needed
+ 'expand': function(x,n) {
+ var ans=int2bigInt(0,(x.length>n ? x.length : n)*bpe,0);
+ copy_(ans,x);
+ return ans;
+ },
+
+ //return a k-bit true random prime using Maurer's algorithm.
+ 'randTruePrime': function(k) {
+ var ans=int2bigInt(0,k,0);
+ randTruePrime_(ans,k);
+ return trim(ans,1);
+ },
+
+ //return a new bigInt equal to (x mod n) for bigInts x and n.
+ 'mod': function(x,n) {
+ var ans=dup(x);
+ mod_(ans,n);
+ return trim(ans,1);
+ },
+
+ //return (x+n) where x is a bigInt and n is an integer.
+ 'addInt': function(x,n) {
+ var ans=expand(x,x.length+1);
+ addInt_(ans,n);
+ return trim(ans,1);
+ },
+
+ //return x*y for bigInts x and y. This is faster when y<x.
+ 'mult': function(x,y) {
+ var ans=expand(x,x.length+y.length);
+ mult_(ans,y);
+ return trim(ans,1);
+ },
+
+ //return (x**y mod n) where x,y,n are bigInts and ** is exponentiation. 0**0=1. Faster for odd n.
+ 'powMod': function(x,y,n) {
+ var ans=expand(x,n.length);
+ powMod_(ans,trim(y,2),trim(n,2),0); //this should work without the trim, but doesn't
+ return trim(ans,1);
+ },
+
+ //return (x-y) for bigInts x and y. Negative answers will be 2s complement
+ 'sub': function(x,y) {
+ var ans=expand(x,(x.length>y.length ? x.length+1 : y.length+1));
+ sub_(ans,y);
+ return trim(ans,1);
+ },
+
+ //return (x+y) for bigInts x and y.
+ 'add': function(x,y) {
+ var ans=expand(x,(x.length>y.length ? x.length+1 : y.length+1));
+ add_(ans,y);
+ return trim(ans,1);
+ },
+
+ //return (x**(-1) mod n) for bigInts x and n. If no inverse exists, it returns null
+ 'inverseMod': function(x,n) {
+ var ans=expand(x,n.length);
+ var s;
+ s=inverseMod_(ans,n);
+ return s ? trim(ans,1) : null;
+ },
+
+ //return (x*y mod n) for bigInts x,y,n. For greater speed, let y<x.
+ 'multMod': function(x,y,n) {
+ var ans=expand(x,n.length);
+ multMod_(ans,y,n);
+ return trim(ans,1);
+ },
+
+ //generate a k-bit true random prime using Maurer's algorithm,
+ //and put it into ans. The bigInt ans must be large enough to hold it.
+ 'randTruePrime_': function(ans,k) {
+ var c,m,pm,dd,j,r,B,divisible,z,zz,recSize;
+
+ if (primes.length==0)
+ primes=findPrimes(30000); //check for divisibility by primes <=30000
+
+ if (pows.length==0) {
+ pows=new Array(512);
+ for (j=0;j<512;j++) {
+ pows[j]=Math.pow(2,j/511.-1.);
+ }
+ }
+
+ //c and m should be tuned for a particular machine and value of k, to maximize speed
+ //this was: c=primes[primes.length-1]/k/k; //check using all the small primes. (c=0.1 in HAC)
+ c=0.1;
+ m=20; //generate this k-bit number by first recursively generating a number that has between k/2 and k-m bits
+ recLimit=20; /*must be at least 2 (was 29)*/ //stop recursion when k <=recLimit
+
+ if (s_i2.length!=ans.length) {
+ s_i2=dup(ans);
+ s_R =dup(ans);
+ s_n1=dup(ans);
+ s_r2=dup(ans);
+ s_d =dup(ans);
+ s_x1=dup(ans);
+ s_x2=dup(ans);
+ s_b =dup(ans);
+ s_n =dup(ans);
+ s_i =dup(ans);
+ s_rm=dup(ans);
+ s_q =dup(ans);
+ s_a =dup(ans);
+ s_aa=dup(ans);
+ }
+
+ if (k <= recLimit) { //generate small random primes by trial division up to its square root
+ pm=(1<<((k+2)>>1))-1; //pm is binary number with all ones, just over sqrt(2^k)
+ copyInt_(ans,0);
+ for (dd=1;dd;) {
+ dd=0;
+ ans[0]= 1 | (1<<(k-1)) | Math.floor(Math.random()*(1<<k)); //random, k-bit, odd integer, with msb 1
+ for (j=1;(j<primes.length) && ((primes[j]&pm)==primes[j]);j++) { //trial division by all primes 3...sqrt(2^k)
+ if (0==(ans[0]%primes[j])) {
+ dd=1;
+ break;
+ }
+ }
+ }
+ carry_(ans);
+ return;
+ }
+
+ B=c*k*k; //try small primes up to B (or all the primes[] array if the largest is less than B).
+ if (k>2*m) //generate this k-bit number by first recursively generating a number that has between k/2 and k-m bits
+ for (r=1; k-k*r<=m; )
+ r=pows[Math.floor(Math.random()*512)]; //r=Math.pow(2,Math.random()-1);
+ else
+ r=.5;
+
+ //simulation suggests the more complex algorithm using r=.333 is only slightly faster.
+
+ recSize=Math.floor(r*k)+1;
+
+ randTruePrime_(s_q,recSize);
+ copyInt_(s_i2,0);
+ s_i2[Math.floor((k-2)/bpe)] |= (1<<((k-2)%bpe)); //s_i2=2^(k-2)
+ divide_(s_i2,s_q,s_i,s_rm); //s_i=floor((2^(k-1))/(2q))
+
+ z=bitSize(s_i);
+
+ for (;;) {
+ for (;;) { //generate z-bit numbers until one falls in the range [0,s_i-1]
+ randBigInt_(s_R,z,0);
+ if (greater(s_i,s_R))
+ break;
+ } //now s_R is in the range [0,s_i-1]
+ addInt_(s_R,1); //now s_R is in the range [1,s_i]
+ add_(s_R,s_i); //now s_R is in the range [s_i+1,2*s_i]
+
+ copy_(s_n,s_q);
+ mult_(s_n,s_R);
+ multInt_(s_n,2);
+ addInt_(s_n,1); //s_n=2*s_R*s_q+1
+
+ copy_(s_r2,s_R);
+ multInt_(s_r2,2); //s_r2=2*s_R
+
+ //check s_n for divisibility by small primes up to B
+ for (divisible=0,j=0; (j<primes.length) && (primes[j]<B); j++)
+ if (modInt(s_n,primes[j])==0) {
+ divisible=1;
+ break;
+ }
+
+ if (!divisible) //if it passes small primes check, then try a single Miller-Rabin base 2
+ if (!millerRabin(s_n,2)) //this line represents 75% of the total runtime for randTruePrime_
+ divisible=1;
+
+ if (!divisible) { //if it passes that test, continue checking s_n
+ addInt_(s_n,-3);
+ for (j=s_n.length-1;(s_n[j]==0) && (j>0); j--); //strip leading zeros
+ for (zz=0,w=s_n[j]; w; (w>>=1),zz++);
+ zz+=bpe*j; //zz=number of bits in s_n, ignoring leading zeros
+ for (;;) { //generate z-bit numbers until one falls in the range [0,s_n-1]
+ randBigInt_(s_a,zz,0);
+ if (greater(s_n,s_a))
+ break;
+ } //now s_a is in the range [0,s_n-1]
+ addInt_(s_n,3); //now s_a is in the range [0,s_n-4]
+ addInt_(s_a,2); //now s_a is in the range [2,s_n-2]
+ copy_(s_b,s_a);
+ copy_(s_n1,s_n);
+ addInt_(s_n1,-1);
+ powMod_(s_b,s_n1,s_n); //s_b=s_a^(s_n-1) modulo s_n
+ addInt_(s_b,-1);
+ if (isZero(s_b)) {
+ copy_(s_b,s_a);
+ powMod_(s_b,s_r2,s_n);
+ addInt_(s_b,-1);
+ copy_(s_aa,s_n);
+ copy_(s_d,s_b);
+ GCD_(s_d,s_n); //if s_b and s_n are relatively prime, then s_n is a prime
+ if (equalsInt(s_d,1)) {
+ copy_(ans,s_aa);
+ return; //if we've made it this far, then s_n is absolutely guaranteed to be prime
+ }
+ }
+ }
+ }
+ },
+
+ //set b to an n-bit random BigInt. If s=1, then nth bit (most significant bit) is set to 1.
+ //array b must be big enough to hold the result. Must have n>=1
+ 'randBigInt_': function(b,n,s) {
+ var i,a;
+ for (i=0;i<b.length;i++)
+ b[i]=0;
+ a=Math.floor((n-1)/bpe)+1; //# array elements to hold the BigInt
+ for (i=0;i<a;i++) {
+ b[i]=Math.floor(Math.random()*(1<<(bpe-1)));
+ }
+ b[a-1] &= (2<<((n-1)%bpe))-1;
+ if (s)
+ b[a-1] |= (1<<((n-1)%bpe));
+ },
+
+ //set x to the greatest common divisor of x and y.
+ //x,y are bigInts with the same number of elements. y is destroyed.
+ 'GCD_': function(x,y) {
+ var i,xp,yp,A,B,C,D,q,sing;
+ if (T.length!=x.length)
+ T=dup(x);
+
+ sing=1;
+ while (sing) { //while y has nonzero elements other than y[0]
+ sing=0;
+ for (i=1;i<y.length;i++) //check if y has nonzero elements other than 0
+ if (y[i]) {
+ sing=1;
+ break;
+ }
+ if (!sing) break; //quit when y all zero elements except possibly y[0]
+
+ for (i=x.length;!x[i] && i>=0;i--); //find most significant element of x
+ xp=x[i];
+ yp=y[i];
+ A=1; B=0; C=0; D=1;
+ while ((yp+C) && (yp+D)) {
+ q =Math.floor((xp+A)/(yp+C));
+ qp=Math.floor((xp+B)/(yp+D));
+ if (q!=qp)
+ break;
+ t= A-q*C; A=C; C=t; // do (A,B,xp, C,D,yp) = (C,D,yp, A,B,xp) - q*(0,0,0, C,D,yp)
+ t= B-q*D; B=D; D=t;
+ t=xp-q*yp; xp=yp; yp=t;
+ }
+ if (B) {
+ copy_(T,x);
+ linComb_(x,y,A,B); //x=A*x+B*y
+ linComb_(y,T,D,C); //y=D*y+C*T
+ } else {
+ mod_(x,y);
+ copy_(T,x);
+ copy_(x,y);
+ copy_(y,T);
+ }
+ }
+ if (y[0]==0)
+ return;
+ t=modInt(x,y[0]);
+ copyInt_(x,y[0]);
+ y[0]=t;
+ while (y[0]) {
+ x[0]%=y[0];
+ t=x[0]; x[0]=y[0]; y[0]=t;
+ }
+ },
+
+//do x=x**(-1) mod n, for bigInts x and n.
+//If no inverse exists, it sets x to zero and returns 0, else it returns 1.
+//The x array must be at least as large as the n array.
+function inverseMod_(x,n) {
+ var k=1+2*Math.max(x.length,n.length);
+
+ if(!(x[0]&1) && !(n[0]&1)) { //if both inputs are even, then inverse doesn't exist
+ copyInt_(x,0);
+ return 0;
+ }
+
+ if (eg_u.length!=k) {
+ eg_u=new Array(k);
+ eg_v=new Array(k);
+ eg_A=new Array(k);
+ eg_B=new Array(k);
+ eg_C=new Array(k);
+ eg_D=new Array(k);
+ }
+
+ copy_(eg_u,x);
+ copy_(eg_v,n);
+ copyInt_(eg_A,1);
+ copyInt_(eg_B,0);
+ copyInt_(eg_C,0);
+ copyInt_(eg_D,1);
+ for (;;) {
+ while(!(eg_u[0]&1)) { //while eg_u is even
+ halve_(eg_u);
+ if (!(eg_A[0]&1) && !(eg_B[0]&1)) { //if eg_A==eg_B==0 mod 2
+ halve_(eg_A);
+ halve_(eg_B);
+ } else {
+ add_(eg_A,n); halve_(eg_A);
+ sub_(eg_B,x); halve_(eg_B);
+ }
+ }
+
+ while (!(eg_v[0]&1)) { //while eg_v is even
+ halve_(eg_v);
+ if (!(eg_C[0]&1) && !(eg_D[0]&1)) { //if eg_C==eg_D==0 mod 2
+ halve_(eg_C);
+ halve_(eg_D);
+ } else {
+ add_(eg_C,n); halve_(eg_C);
+ sub_(eg_D,x); halve_(eg_D);
+ }
+ }
+
+ if (!greater(eg_v,eg_u)) { //eg_v <= eg_u
+ sub_(eg_u,eg_v);
+ sub_(eg_A,eg_C);
+ sub_(eg_B,eg_D);
+ } else { //eg_v > eg_u
+ sub_(eg_v,eg_u);
+ sub_(eg_C,eg_A);
+ sub_(eg_D,eg_B);
+ }
+
+ if (equalsInt(eg_u,0)) {
+ if (negative(eg_C)) //make sure answer is nonnegative
+ add_(eg_C,n);
+ copy_(x,eg_C);
+
+ if (!equalsInt(eg_v,1)) { //if GCD_(x,n)!=1, then there is no inverse
+ copyInt_(x,0);
+ return 0;
+ }
+ return 1;
+ }
+ }
+}
+
+//return x**(-1) mod n, for integers x and n. Return 0 if there is no inverse
+function inverseModInt_(x,n) {
+ var a=1,b=0,t;
+ for (;;) {
+ if (x==1) return a;
+ if (x==0) return 0;
+ b-=a*Math.floor(n/x);
+ n%=x;
+
+ if (n==1) return b; //to avoid negatives, change this b to n-b, and each -= to +=
+ if (n==0) return 0;
+ a-=b*Math.floor(x/n);
+ x%=n;
+ }
+}
+
+//Given positive bigInts x and y, change the bigints v, a, and b to positive bigInts such that:
+// v = GCD_(x,y) = a*x-b*y
+//The bigInts v, a, b, must have exactly as many elements as the larger of x and y.
+function eGCD_(x,y,v,a,b) {
+ var g=0;
+ var k=Math.max(x.length,y.length);
+ if (eg_u.length!=k) {
+ eg_u=new Array(k);
+ eg_A=new Array(k);
+ eg_B=new Array(k);
+ eg_C=new Array(k);
+ eg_D=new Array(k);
+ }
+ while(!(x[0]&1) && !(y[0]&1)) { //while x and y both even
+ halve_(x);
+ halve_(y);
+ g++;
+ }
+ copy_(eg_u,x);
+ copy_(v,y);
+ copyInt_(eg_A,1);
+ copyInt_(eg_B,0);
+ copyInt_(eg_C,0);
+ copyInt_(eg_D,1);
+ for (;;) {
+ while(!(eg_u[0]&1)) { //while u is even
+ halve_(eg_u);
+ if (!(eg_A[0]&1) && !(eg_B[0]&1)) { //if A==B==0 mod 2
+ halve_(eg_A);
+ halve_(eg_B);
+ } else {
+ add_(eg_A,y); halve_(eg_A);
+ sub_(eg_B,x); halve_(eg_B);
+ }
+ }
+
+ while (!(v[0]&1)) { //while v is even
+ halve_(v);
+ if (!(eg_C[0]&1) && !(eg_D[0]&1)) { //if C==D==0 mod 2
+ halve_(eg_C);
+ halve_(eg_D);
+ } else {
+ add_(eg_C,y); halve_(eg_C);
+ sub_(eg_D,x); halve_(eg_D);
+ }
+ }
+
+ if (!greater(v,eg_u)) { //v<=u
+ sub_(eg_u,v);
+ sub_(eg_A,eg_C);
+ sub_(eg_B,eg_D);
+ } else { //v>u
+ sub_(v,eg_u);
+ sub_(eg_C,eg_A);
+ sub_(eg_D,eg_B);
+ }
+ if (equalsInt(eg_u,0)) {
+ if (negative(eg_C)) { //make sure a (C)is nonnegative
+ add_(eg_C,y);
+ sub_(eg_D,x);
+ }
+ multInt_(eg_D,-1); ///make sure b (D) is nonnegative
+ copy_(a,eg_C);
+ copy_(b,eg_D);
+ leftShift_(v,g);
+ return;
+ }
+ }
+}
+
+
+//is bigInt x negative?
+function negative(x) {
+ return ((x[x.length-1]>>(bpe-1))&1);
+}
+
+
+//is (x << (shift*bpe)) > y?
+//x and y are nonnegative bigInts
+//shift is a nonnegative integer
+function greaterShift(x,y,shift) {
+ var kx=x.length, ky=y.length;
+ k=((kx+shift)<ky) ? (kx+shift) : ky;
+ for (i=ky-1-shift; i<kx && i>=0; i++)
+ if (x[i]>0)
+ return 1; //if there are nonzeros in x to the left of the first column of y, then x is bigger
+ for (i=kx-1+shift; i<ky; i++)
+ if (y[i]>0)
+ return 0; //if there are nonzeros in y to the left of the first column of x, then x is not bigger
+ for (i=k-1; i>=shift; i--)
+ if (x[i-shift]>y[i]) return 1;
+ else if (x[i-shift]<y[i]) return 0;
+ return 0;
+}
+
+//is x > y? (x and y both nonnegative)
+function greater(x,y) {
+ var i;
+ var k=(x.length<y.length) ? x.length : y.length;
+
+ for (i=x.length;i<y.length;i++)
+ if (y[i])
+ return 0; //y has more digits
+
+ for (i=y.length;i<x.length;i++)
+ if (x[i])
+ return 1; //x has more digits
+
+ for (i=k-1;i>=0;i--)
+ if (x[i]>y[i])
+ return 1;
+ else if (x[i]<y[i])
+ return 0;
+ return 0;
+}
+
+//divide_ x by y giving quotient q and remainder r. (q=floor(x/y), r=x mod y). All 4 are bigints.
+//x must have at least one leading zero element.
+//y must be nonzero.
+//q and r must be arrays that are exactly the same length as x.
+//the x array must have at least as many elements as y.
+function divide_(x,y,q,r) {
+ var kx, ky;
+ var i,j,y1,y2,c,a,b;
+ copy_(r,x);
+ for (ky=y.length;y[ky-1]==0;ky--); //kx,ky is number of elements in x,y, not including leading zeros
+ for (kx=r.length;r[kx-1]==0 && kx>ky;kx--);
+
+ //normalize: ensure the most significant element of y has its highest bit set
+ b=y[ky-1];
+ for (a=0; b; a++)
+ b>>=1;
+ a=bpe-a; //a is how many bits to shift so that the high order bit of y is leftmost in its array element
+ leftShift_(y,a); //multiply both by 1<<a now, then divide_ both by that at the end
+ leftShift_(r,a);
+
+ copyInt_(q,0); // q=0
+ while (!greaterShift(y,r,kx-ky)) { // while (leftShift_(y,kx-ky) <= r) {
+ subShift_(r,y,kx-ky); // r=r-leftShift_(y,kx-ky)
+ q[kx-ky]++; // q[kx-ky]++;
+ } // }
+
+ for (i=kx-1; i>=ky; i--) {
+ if (r[i]==y[ky-1])
+ q[i-ky]=mask;
+ else
+ q[i-ky]=Math.floor((r[i]*radix+r[i-1])/y[ky-1]);
+
+ //The following for(;;) loop is equivalent to the commented while loop,
+ //except that the uncommented version avoids overflow.
+ //The commented loop comes from HAC, which assumes r[-1]==y[-1]==0
+ // while (q[i-ky]*(y[ky-1]*radix+y[ky-2]) > r[i]*radix*radix+r[i-1]*radix+r[i-2])
+ // q[i-ky]--;
+ for (;;) {
+ y2=(ky>1 ? y[ky-2] : 0)*q[i-ky];
+ c=y2>>bpe;
+ y2=y2 & mask;
+ y1=c+q[i-ky]*y[ky-1];
+ c=y1>>bpe;
+ y1=y1 & mask;
+
+ if (c==r[i] ? y1==r[i-1] ? y2>(i>1 ? r[i-2] : 0) : y1>r[i-1] : c>r[i])
+ q[i-ky]--;
+ else
+ break;
+ }
+
+ linCombShift_(r,y,-q[i-ky],i-ky); //r=r-q[i-ky]*leftShift_(y,i-ky)
+ if (negative(r)) {
+ addShift_(r,y,i-ky); //r=r+leftShift_(y,i-ky)
+ q[i-ky]--;
+ }
+ }
+
+ rightShift_(y,a); //undo the normalization step
+ rightShift_(r,a); //undo the normalization step
+}
+
+//do carries and borrows so each element of the bigInt x fits in bpe bits.
+function carry_(x) {
+ var i,k,c,b;
+ k=x.length;
+ c=0;
+ for (i=0;i<k;i++) {
+ c+=x[i];
+ b=0;
+ if (c<0) {
+ b=-(c>>bpe);
+ c+=b*radix;
+ }
+ x[i]=c & mask;
+ c=(c>>bpe)-b;
+ }
+}
+
+//return x mod n for bigInt x and integer n.
+function modInt(x,n) {
+ var i,c=0;
+ for (i=x.length-1; i>=0; i--)
+ c=(c*radix+x[i])%n;
+ return c;
+}
+
+//convert the integer t into a bigInt with at least the given number of bits.
+//the returned array stores the bigInt in bpe-bit chunks, little endian (buff[0] is least significant word)
+//Pad the array with leading zeros so that it has at least minSize elements.
+//There will always be at least one leading 0 element.
+function int2bigInt(t,bits,minSize) {
+ var i,k;
+ k=Math.ceil(bits/bpe)+1;
+ k=minSize>k ? minSize : k;
+ buff=new Array(k);
+ copyInt_(buff,t);
+ return buff;
+}
+
+//return the bigInt given a string representation in a given base.
+//Pad the array with leading zeros so that it has at least minSize elements.
+//If base=-1, then it reads in a space-separated list of array elements in decimal.
+//The array will always have at least one leading zero, unless base=-1.
+function str2bigInt(s,base,minSize) {
+ var d, i, j, x, y, kk;
+ var k=s.length;
+ if (base==-1) { //comma-separated list of array elements in decimal
+ x=new Array(0);
+ for (;;) {
+ y=new Array(x.length+1);
+ for (i=0;i<x.length;i++)
+ y[i+1]=x[i];
+ y[0]=parseInt(s,10);
+ x=y;
+ d=s.indexOf(',',0);
+ if (d<1)
+ break;
+ s=s.substring(d+1);
+ if (s.length==0)
+ break;
+ }
+ if (x.length<minSize) {
+ y=new Array(minSize);
+ copy_(y,x);
+ return y;
+ }
+ return x;
+ }
+
+ x=int2bigInt(0,base*k,0);
+ for (i=0;i<k;i++) {
+ d=digitsStr.indexOf(s.substring(i,i+1),0);
+ if (base<=36 && d>=36) //convert lowercase to uppercase if base<=36
+ d-=26;
+ if (d<base && d>=0) { //ignore illegal characters
+ multInt_(x,base);
+ addInt_(x,d);
+ }
+ }
+
+ for (k=x.length;k>0 && !x[k-1];k--); //strip off leading zeros
+ k=minSize>k+1 ? minSize : k+1;
+ y=new Array(k);
+ kk=k<x.length ? k : x.length;
+ for (i=0;i<kk;i++)
+ y[i]=x[i];
+ for (;i<k;i++)
+ y[i]=0;
+ return y;
+}
+
+//is bigint x equal to integer y?
+//y must have less than bpe bits
+function equalsInt(x,y) {
+ var i;
+ if (x[0]!=y)
+ return 0;
+ for (i=1;i<x.length;i++)
+ if (x[i])
+ return 0;
+ return 1;
+}
+
+//are bigints x and y equal?
+//this works even if x and y are different lengths and have arbitrarily many leading zeros
+function equals(x,y) {
+ var i;
+ var k=x.length<y.length ? x.length : y.length;
+ for (i=0;i<k;i++)
+ if (x[i]!=y[i])
+ return 0;
+ if (x.length>y.length) {
+ for (;i<x.length;i++)
+ if (x[i])
+ return 0;
+ } else {
+ for (;i<y.length;i++)
+ if (y[i])
+ return 0;
+ }
+ return 1;
+}
+
+//is the bigInt x equal to zero?
+function isZero(x) {
+ var i;
+ for (i=0;i<x.length;i++)
+ if (x[i])
+ return 0;
+ return 1;
+}
+
+//convert a bigInt into a string in a given base, from base 2 up to base 95.
+//Base -1 prints the contents of the array representing the number.
+function bigInt2str(x,base) {
+ var i,t,s="";
+
+ if (s6.length!=x.length)
+ s6=dup(x);
+ else
+ copy_(s6,x);
+
+ if (base==-1) { //return the list of array contents
+ for (i=x.length-1;i>0;i--)
+ s+=x[i]+',';
+ s+=x[0];
+ }
+ else { //return it in the given base
+ while (!isZero(s6)) {
+ t=divInt_(s6,base); //t=s6 % base; s6=floor(s6/base);
+ s=digitsStr.substring(t,t+1)+s;
+ }
+ }
+ if (s.length==0)
+ s="0";
+ return s;
+}
+
+//returns a duplicate of bigInt x
+function dup(x) {
+ var i;
+ buff=new Array(x.length);
+ copy_(buff,x);
+ return buff;
+}
+
+//do x=y on bigInts x and y. x must be an array at least as big as y (not counting the leading zeros in y).
+function copy_(x,y) {
+ var i;
+ var k=x.length<y.length ? x.length : y.length;
+ for (i=0;i<k;i++)
+ x[i]=y[i];
+ for (i=k;i<x.length;i++)
+ x[i]=0;
+}
+
+//do x=y on bigInt x and integer y.
+function copyInt_(x,n) {
+ var i,c;
+ for (c=n,i=0;i<x.length;i++) {
+ x[i]=c & mask;
+ c>>=bpe;
+ }
+}
+
+//do x=x+n where x is a bigInt and n is an integer.
+//x must be large enough to hold the result.
+function addInt_(x,n) {
+ var i,k,c,b;
+ x[0]+=n;
+ k=x.length;
+ c=0;
+ for (i=0;i<k;i++) {
+ c+=x[i];
+ b=0;
+ if (c<0) {
+ b=-(c>>bpe);
+ c+=b*radix;
+ }
+ x[i]=c & mask;
+ c=(c>>bpe)-b;
+ if (!c) return; //stop carrying as soon as the carry_ is zero
+ }
+}
+
+//right shift bigInt x by n bits. 0 <= n < bpe.
+function rightShift_(x,n) {
+ var i;
+ var k=Math.floor(n/bpe);
+ if (k) {
+ for (i=0;i<x.length-k;i++) //right shift x by k elements
+ x[i]=x[i+k];
+ for (;i<x.length;i++)
+ x[i]=0;
+ n%=bpe;
+ }
+ for (i=0;i<x.length-1;i++) {
+ x[i]=mask & ((x[i+1]<<(bpe-n)) | (x[i]>>n));
+ }
+ x[i]>>=n;
+}
+
+//do x=floor(|x|/2)*sgn(x) for bigInt x in 2's complement
+function halve_(x) {
+ var i;
+ for (i=0;i<x.length-1;i++) {
+ x[i]=mask & ((x[i+1]<<(bpe-1)) | (x[i]>>1));
+ }
+ x[i]=(x[i]>>1) | (x[i] & (radix>>1)); //most significant bit stays the same
+}
+
+//left shift bigInt x by n bits.
+function leftShift_(x,n) {
+ var i;
+ var k=Math.floor(n/bpe);
+ if (k) {
+ for (i=x.length; i>=k; i--) //left shift x by k elements
+ x[i]=x[i-k];
+ for (;i>=0;i--)
+ x[i]=0;
+ n%=bpe;
+ }
+ if (!n)
+ return;
+ for (i=x.length-1;i>0;i--) {
+ x[i]=mask & ((x[i]<<n) | (x[i-1]>>(bpe-n)));
+ }
+ x[i]=mask & (x[i]<<n);
+}
+
+//do x=x*n where x is a bigInt and n is an integer.
+//x must be large enough to hold the result.
+function multInt_(x,n) {
+ var i,k,c,b;
+ if (!n)
+ return;
+ k=x.length;
+ c=0;
+ for (i=0;i<k;i++) {
+ c+=x[i]*n;
+ b=0;
+ if (c<0) {
+ b=-(c>>bpe);
+ c+=b*radix;
+ }
+ x[i]=c & mask;
+ c=(c>>bpe)-b;
+ }
+}
+
+//do x=floor(x/n) for bigInt x and integer n, and return the remainder
+function divInt_(x,n) {
+ var i,r=0,s;
+ for (i=x.length-1;i>=0;i--) {
+ s=r*radix+x[i];
+ x[i]=Math.floor(s/n);
+ r=s%n;
+ }
+ return r;
+}
+
+//do the linear combination x=a*x+b*y for bigInts x and y, and integers a and b.
+//x must be large enough to hold the answer.
+function linComb_(x,y,a,b) {
+ var i,c,k,kk;
+ k=x.length<y.length ? x.length : y.length;
+ kk=x.length;
+ for (c=0,i=0;i<k;i++) {
+ c+=a*x[i]+b*y[i];
+ x[i]=c & mask;
+ c>>=bpe;
+ }
+ for (i=k;i<kk;i++) {
+ c+=a*x[i];
+ x[i]=c & mask;
+ c>>=bpe;
+ }
+}
+
+//do the linear combination x=a*x+b*(y<<(ys*bpe)) for bigInts x and y, and integers a, b and ys.
+//x must be large enough to hold the answer.
+function linCombShift_(x,y,b,ys) {
+ var i,c,k,kk;
+ k=x.length<ys+y.length ? x.length : ys+y.length;
+ kk=x.length;
+ for (c=0,i=ys;i<k;i++) {
+ c+=x[i]+b*y[i-ys];
+ x[i]=c & mask;
+ c>>=bpe;
+ }
+ for (i=k;c && i<kk;i++) {
+ c+=x[i];
+ x[i]=c & mask;
+ c>>=bpe;
+ }
+}
+
+//do x=x+(y<<(ys*bpe)) for bigInts x and y, and integers a,b and ys.
+//x must be large enough to hold the answer.
+function addShift_(x,y,ys) {
+ var i,c,k,kk;
+ k=x.length<ys+y.length ? x.length : ys+y.length;
+ kk=x.length;
+ for (c=0,i=ys;i<k;i++) {
+ c+=x[i]+y[i-ys];
+ x[i]=c & mask;
+ c>>=bpe;
+ }
+ for (i=k;c && i<kk;i++) {
+ c+=x[i];
+ x[i]=c & mask;
+ c>>=bpe;
+ }
+}
+
+//do x=x-(y<<(ys*bpe)) for bigInts x and y, and integers a,b and ys.
+//x must be large enough to hold the answer.
+function subShift_(x,y,ys) {
+ var i,c,k,kk;
+ k=x.length<ys+y.length ? x.length : ys+y.length;
+ kk=x.length;
+ for (c=0,i=ys;i<k;i++) {
+ c+=x[i]-y[i-ys];
+ x[i]=c & mask;
+ c>>=bpe;
+ }
+ for (i=k;c && i<kk;i++) {
+ c+=x[i];
+ x[i]=c & mask;
+ c>>=bpe;
+ }
+}
+
+//do x=x-y for bigInts x and y.
+//x must be large enough to hold the answer.
+//negative answers will be 2s complement
+function sub_(x,y) {
+ var i,c,k,kk;
+ k=x.length<y.length ? x.length : y.length;
+ for (c=0,i=0;i<k;i++) {
+ c+=x[i]-y[i];
+ x[i]=c & mask;
+ c>>=bpe;
+ }
+ for (i=k;c && i<x.length;i++) {
+ c+=x[i];
+ x[i]=c & mask;
+ c>>=bpe;
+ }
+}
+
+//do x=x+y for bigInts x and y.
+//x must be large enough to hold the answer.
+function add_(x,y) {
+ var i,c,k,kk;
+ k=x.length<y.length ? x.length : y.length;
+ for (c=0,i=0;i<k;i++) {
+ c+=x[i]+y[i];
+ x[i]=c & mask;
+ c>>=bpe;
+ }
+ for (i=k;c && i<x.length;i++) {
+ c+=x[i];
+ x[i]=c & mask;
+ c>>=bpe;
+ }
+}
+
+//do x=x*y for bigInts x and y. This is faster when y<x.
+function mult_(x,y) {
+ var i;
+ if (ss.length!=2*x.length)
+ ss=new Array(2*x.length);
+ copyInt_(ss,0);
+ for (i=0;i<y.length;i++)
+ if (y[i])
+ linCombShift_(ss,x,y[i],i); //ss=1*ss+y[i]*(x<<(i*bpe))
+ copy_(x,ss);
+}
+
+//do x=x mod n for bigInts x and n.
+function mod_(x,n) {
+ if (s4.length!=x.length)
+ s4=dup(x);
+ else
+ copy_(s4,x);
+ if (s5.length!=x.length)
+ s5=dup(x);
+ divide_(s4,n,s5,x); //x = remainder of s4 / n
+}
+
+//do x=x*y mod n for bigInts x,y,n.
+//for greater speed, let y<x.
+function multMod_(x,y,n) {
+ var i;
+ if (s0.length!=2*x.length)
+ s0=new Array(2*x.length);
+ copyInt_(s0,0);
+ for (i=0;i<y.length;i++)
+ if (y[i])
+ linCombShift_(s0,x,y[i],i); //s0=1*s0+y[i]*(x<<(i*bpe))
+ mod_(s0,n);
+ copy_(x,s0);
+}
+
+//do x=x*x mod n for bigInts x,n.
+function squareMod_(x,n) {
+ var i,j,d,c,kx,kn,k;
+ for (kx=x.length; kx>0 && !x[kx-1]; kx--); //ignore leading zeros in x
+ k=kx>n.length ? 2*kx : 2*n.length; //k=# elements in the product, which is twice the elements in the larger of x and n
+ if (s0.length!=k)
+ s0=new Array(k);
+ copyInt_(s0,0);
+ for (i=0;i<kx;i++) {
+ c=s0[2*i]+x[i]*x[i];
+ s0[2*i]=c & mask;
+ c>>=bpe;
+ for (j=i+1;j<kx;j++) {
+ c=s0[i+j]+2*x[i]*x[j]+c;
+ s0[i+j]=(c & mask);
+ c>>=bpe;
+ }
+ s0[i+kx]=c;
+ }
+ mod_(s0,n);
+ copy_(x,s0);
+}
+
+//return x with exactly k leading zero elements
+function trim(x,k) {
+ var i,y;
+ for (i=x.length; i>0 && !x[i-1]; i--);
+ y=new Array(i+k);
+ copy_(y,x);
+ return y;
+}
+
+//do x=x**y mod n, where x,y,n are bigInts and ** is exponentiation. 0**0=1.
+//this is faster when n is odd. x usually needs to have as many elements as n.
+function powMod_(x,y,n) {
+ var k1,k2,kn,np;
+ if(s7.length!=n.length)
+ s7=dup(n);
+
+ //for even modulus, use a simple square-and-multiply algorithm,
+ //rather than using the more complex Montgomery algorithm.
+ if ((n[0]&1)==0) {
+ copy_(s7,x);
+ copyInt_(x,1);
+ while(!equalsInt(y,0)) {
+ if (y[0]&1)
+ multMod_(x,s7,n);
+ divInt_(y,2);
+ squareMod_(s7,n);
+ }
+ return;
+ }
+
+ //calculate np from n for the Montgomery multiplications
+ copyInt_(s7,0);
+ for (kn=n.length;kn>0 && !n[kn-1];kn--);
+ np=radix-inverseModInt_(modInt(n,radix),radix);
+ s7[kn]=1;
+ multMod_(x ,s7,n); // x = x * 2**(kn*bp) mod n
+
+ if (s3.length!=x.length)
+ s3=dup(x);
+ else
+ copy_(s3,x);
+
+ for (k1=y.length-1;k1>0 & !y[k1]; k1--); //k1=first nonzero element of y
+ if (y[k1]==0) { //anything to the 0th power is 1
+ copyInt_(x,1);
+ return;
+ }
+ for (k2=1<<(bpe-1);k2 && !(y[k1] & k2); k2>>=1); //k2=position of first 1 bit in y[k1]
+ for (;;) {
+ if (!(k2>>=1)) { //look at next bit of y
+ k1--;
+ if (k1<0) {
+ mont_(x,one,n,np);
+ return;
+ }
+ k2=1<<(bpe-1);
+ }
+ mont_(x,x,n,np);
+
+ if (k2 & y[k1]) //if next bit is a 1
+ mont_(x,s3,n,np);
+ }
+}
+
+//do x=x*y*Ri mod n for bigInts x,y,n,
+// where Ri = 2**(-kn*bpe) mod n, and kn is the
+// number of elements in the n array, not
+// counting leading zeros.
+//x must be large enough to hold the answer.
+//It's OK if x and y are the same variable.
+//must have:
+// x,y < n
+// n is odd
+// np = -(n^(-1)) mod radix
+function mont_(x,y,n,np) {
+ var i,j,c,ui,t;
+ var kn=n.length;
+ var ky=y.length;
+
+ if (sa.length!=kn)
+ sa=new Array(kn);
+
+ for (;kn>0 && n[kn-1]==0;kn--); //ignore leading zeros of n
+ //this function sometimes gives wrong answers when the next line is uncommented
+ //for (;ky>0 && y[ky-1]==0;ky--); //ignore leading zeros of y
+
+ copyInt_(sa,0);
+
+ //the following loop consumes 95% of the runtime for randTruePrime_() and powMod_() for large keys
+ for (i=0; i<kn; i++) {
+ t=sa[0]+x[i]*y[0];
+ ui=((t & mask) * np) & mask; //the inner "& mask" is needed on Macintosh MSIE, but not windows MSIE
+ c=(t+ui*n[0]) >> bpe;
+ t=x[i];
+
+ //do sa=(sa+x[i]*y+ui*n)/b where b=2**bpe
+ for (j=1;j<ky;j++) {
+ c+=sa[j]+t*y[j]+ui*n[j];
+ sa[j-1]=c & mask;
+ c>>=bpe;
+ }
+ for (;j<kn;j++) {
+ c+=sa[j]+ui*n[j];
+ sa[j-1]=c & mask;
+ c>>=bpe;
+ }
+ sa[j-1]=c & mask;
+ }
+
+ if (!greater(n,sa))
+ sub_(sa,n);
+ copy_(x,sa);
+}
+
+
+
+
+//#############################################################################
+//#############################################################################
+//#############################################################################
+//#############################################################################
+//#############################################################################
+//#############################################################################
+//#############################################################################
+
+
+
+
+
+//#############################################################################
+
+Clipperz.Crypto.BigInt = function (aValue, aBase) {
+ var base;
+ var value;
+
+ if (typeof(aValue) == 'object') {
+ this._internalValue = aValue;
+ } else {
+ if (typeof(aValue) == 'undefined') {
+ value = "0";
+ } else {
+ value = aValue + "";
+ }
+
+ if (typeof(aBase) == 'undefined') {
+ base = 10;
+ } else {
+ base = aBase;
+ }
+
+ this._internalValue = str2bigInt(value, base, 1, 1);
+ }
+
+ return this;
+}
+
+//=============================================================================
+
+MochiKit.Base.update(Clipperz.Crypto.BigInt.prototype, {
+
+ //-------------------------------------------------------------------------
+
+ 'internalValue': function () {
+ return this._internalValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'isBigInt': true,
+
+ //-------------------------------------------------------------------------
+
+ 'toString': function(aBase) {
+ return this.asString(aBase);
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'asString': function (aBase) {
+ var base;
+
+ if (typeof(aBase) == 'undefined') {
+ base = 10;
+ } else {
+ base = aBase;
+ }
+
+ return bigInt2str(this.internalValue(), base).toLowerCase();
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'equals': function (aValue) {
+ var result;
+
+ if (aValue.isBigInt) {
+ result = equals(this.internalValue(), aValue.internalValue());
+ } else if (typeof(aValue) == "number") {
+ result = equalsInt(this.internalValue(), aValue);
+ } else {
+ throw Clipperz.Crypt.BigInt.exception.UnknownType;
+ }
+
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'add': function (aValue) {
+ var result;
+
+ if (aValue.isBigInt) {
+ result = add(this.internalValue(), aValue.internalValue());
+ } else {
+ result = addInt(this.internalValue(), aValue);
+ }
+
+ return new Clipperz.Crypto.BigInt(result);
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'subtract': function (aValue) {
+ var result;
+ var value;
+
+ if (aValue.isBigInt) {
+ value = aValue;
+ } else {
+ value = new Clipperz.Crypto.BigInt(aValue);
+ }
+
+ result = sub(this.internalValue(), value.internalValue());
+
+ return new Clipperz.Crypto.BigInt(result);
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'multiply': function (aValue, aModule) {
+ var result;
+ var value;
+
+ if (aValue.isBigInt) {
+ value = aValue;
+ } else {
+ value = new Clipperz.Crypto.BigInt(aValue);
+ }
+
+ if (typeof(aModule) == 'undefined') {
+ result = mult(this.internalValue(), value.internalValue());
+ } else {
+ result = multMod(this.internalValue(), value.internalValue(), aModule);
+ }
+
+ return new Clipperz.Crypto.BigInt(result);
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'module': function (aModule) {
+ var result;
+ var module;
+
+ if (aModule.isBigInt) {
+ module = aModule;
+ } else {
+ module = new Clipperz.Crypto.BigInt(aModule);
+ }
+
+ result = mod(this.internalValue(), module.internalValue());
+
+ return new Clipperz.Crypto.BigInt(result);
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'powerModule': function(aValue, aModule) {
+ var result;
+ var value;
+ var module;
+
+ if (aValue.isBigInt) {
+ value = aValue;
+ } else {
+ value = new Clipperz.Crypto.BigInt(aValue);
+ }
+
+ if (aModule.isBigInt) {
+ module = aModule;
+ } else {
+ module = new Clipperz.Crypto.BigInt(aModule);
+ }
+
+ if (aValue == -1) {
+ result = inverseMod(this.internalValue(), module.internalValue());
+ } else {
+ result = powMod(this.internalValue(), value.internalValue(), module.internalValue());
+ }
+
+ return new Clipperz.Crypto.BigInt(result);
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'bitSize': function() {
+ return bitSize(this.internalValue());
+ },
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+
+});
+
+//#############################################################################
+
+Clipperz.Crypto.BigInt.randomPrime = function(aBitSize) {
+ return new Clipperz.Crypto.BigInt(randTruePrime(aBitSize));
+}
+
+//#############################################################################
+//#############################################################################
+//#############################################################################
+
+Clipperz.Crypto.BigInt.equals = function(a, b) {
+ return a.equals(b);
+}
+
+Clipperz.Crypto.BigInt.add = function(a, b) {
+ return a.add(b);
+}
+
+Clipperz.Crypto.BigInt.subtract = function(a, b) {
+ return a.subtract(b);
+}
+
+Clipperz.Crypto.BigInt.multiply = function(a, b, module) {
+ return a.multiply(b, module);
+}
+
+Clipperz.Crypto.BigInt.module = function(a, module) {
+ return a.module(module);
+}
+
+Clipperz.Crypto.BigInt.powerModule = function(a, b, module) {
+ return a.powerModule(b, module);
+}
+
+Clipperz.Crypto.BigInt.exception = {
+ UnknownType: new MochiKit.Base.NamedError("Clipperz.Crypto.BigInt.exception.UnknownType")
+}
diff --git a/frontend/beta/js/Clipperz/Crypto/ECC.js b/frontend/beta/js/Clipperz/Crypto/ECC.js
new file mode 100644
index 0000000..c3dcec3
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/Crypto/ECC.js
@@ -0,0 +1,960 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. 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 = {}; }
+
+
+//#############################################################################
+
+Clipperz.Crypto.ECC.BinaryField = {};
+
+//#############################################################################
+
+Clipperz.Crypto.ECC.BinaryField.AbstractValue = function(aValue, aBase) {
+ return this;
+}
+
+Clipperz.Crypto.ECC.BinaryField.AbstractValue.prototype = MochiKit.Base.update(null, {
+
+ 'asString': function(aBase) {
+ throw Clipperz.Base.exception.AbstractMethod;
+ },
+
+ 'isZero': function() {
+ throw Clipperz.Base.exception.AbstractMethod;
+ },
+
+ 'shiftLeft': function(aNumberOfBitsToShift) {
+ throw Clipperz.Base.exception.AbstractMethod;
+ },
+
+ 'bitSize': function() {
+ throw Clipperz.Base.exception.AbstractMethod;
+ },
+
+ 'isBitSet': function(aBitPosition) {
+ throw Clipperz.Base.exception.AbstractMethod;
+ },
+
+ 'xor': function(aValue) {
+ throw Clipperz.Base.exception.AbstractMethod;
+ },
+
+ 'compare': function(aValue) {
+ throw Clipperz.Base.exception.AbstractMethod;
+ },
+
+ //-----------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+});
+
+//*****************************************************************************
+/ *
+Clipperz.Crypto.ECC.BinaryField.BigIntValue = function(aValue, aBase) {
+ this._value = new Clipperz.Crypto.BigInt(aValue, aBase);
+ return this;
+}
+
+Clipperz.Crypto.ECC.BinaryField.BigIntValue.prototype = MochiKit.Base.update(new Clipperz.Crypto.ECC.BinaryField.AbstractValue(), {
+
+ 'value': function() {
+ return this._value;
+ },
+
+ //-----------------------------------------------------------------------------
+
+ 'isZero': function() {
+ return (this.value().compare(Clipperz.Crypto.ECC.BinaryField.BigIntValue.O) == 0);
+ },
+
+ //-----------------------------------------------------------------------------
+
+ 'asString': function(aBase) {
+ return this.value().asString(aBase);
+ },
+
+ //-----------------------------------------------------------------------------
+
+ 'shiftLeft': function(aNumberOfBitsToShift) {
+ return new Clipperz.Crypto.ECC.BinaryField.BigIntValue(this.value().shiftLeft(aNumberOfBitsToShift));
+ },
+
+ //-----------------------------------------------------------------------------
+
+ 'bitSize': function() {
+ return this.value().bitSize();
+ },
+
+ //-----------------------------------------------------------------------------
+
+ 'isBitSet': function(aBitPosition) {
+ return this.value().isBitSet(aBitPosition);
+ },
+
+ //-----------------------------------------------------------------------------
+
+ 'xor': function(aValue) {
+ return new Clipperz.Crypto.ECC.BinaryField.BigIntValue(this.value().xor(aValue.value()));
+ },
+
+ //-----------------------------------------------------------------------------
+
+ 'compare': function(aValue) {
+ return this.value().compare(aValue.value());
+ },
+
+ //-----------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+});
+
+Clipperz.Crypto.ECC.BinaryField.BigIntValue.O = new Clipperz.Crypto.BigInt(0);
+Clipperz.Crypto.ECC.BinaryField.BigIntValue.I = new Clipperz.Crypto.BigInt(1);
+* /
+//*****************************************************************************
+
+Clipperz.Crypto.ECC.BinaryField.WordArrayValue = function(aValue, aBase) {
+ if (aValue.constructor == String) {
+ var value;
+ var stringLength;
+ var numberOfWords;
+ var i,c;
+
+ if (aBase != 16) {
+ throw Clipperz.Crypto.ECC.BinaryField.WordArrayValue.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.WordArrayValue.exception.UnsupportedConstructorValueType;
+ }
+
+ return this;
+}
+
+Clipperz.Crypto.ECC.BinaryField.WordArrayValue.prototype = MochiKit.Base.update(new Clipperz.Crypto.ECC.BinaryField.AbstractValue(), {
+
+ 'value': function() {
+ return this._value;
+ },
+
+ //-----------------------------------------------------------------------------
+
+ 'wordSize': function() {
+ return this._value.length
+ },
+
+ //-----------------------------------------------------------------------------
+
+ 'clone': function() {
+ return new Clipperz.Crypto.ECC.BinaryField.WordArrayValue(this._value.slice(0));
+ },
+
+ //-----------------------------------------------------------------------------
+
+ 'isZero': function() {
+ return (this.compare(Clipperz.Crypto.ECC.BinaryField.WordArrayValue.O) == 0);
+ },
+
+ //-----------------------------------------------------------------------------
+
+ 'asString': function(aBase) {
+ var result;
+ var i,c;
+
+ if (aBase != 16) {
+ throw Clipperz.Crypto.ECC.BinaryField.WordArrayValue.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)* SPACEs THAT SHOULD BE REMOVED TO FIX THIS REGEX /, "");
+
+ if (result == "") {
+ result = "0";
+ }
+
+ return result;
+ },
+
+ //-----------------------------------------------------------------------------
+
+ 'shiftLeft': function(aNumberOfBitsToShift) {
+ return new Clipperz.Crypto.ECC.BinaryField.WordArrayValue(Clipperz.Crypto.ECC.BinaryField.WordArrayValue.shiftLeft(this._value, aNumberOfBitsToShift));
+ },
+
+ //-----------------------------------------------------------------------------
+
+ 'bitSize': function() {
+ return Clipperz.Crypto.ECC.BinaryField.WordArrayValue.bitSize(this._value);
+ },
+
+ //-----------------------------------------------------------------------------
+
+ 'isBitSet': function(aBitPosition) {
+ return Clipperz.Crypto.ECC.BinaryField.WordArrayValue.isBitSet(this._value, aBitPosition);
+ },
+
+ //-----------------------------------------------------------------------------
+
+ 'xor': function(aValue) {
+ return new Clipperz.Crypto.ECC.BinaryField.WordArrayValue(Clipperz.Crypto.ECC.BinaryField.WordArrayValue.xor(this._value, aValue._value));
+ },
+
+ //-----------------------------------------------------------------------------
+
+ 'compare': function(aValue) {
+ return Clipperz.Crypto.ECC.BinaryField.WordArrayValue.compare(this._value, aValue._value);
+ },
+
+ //-----------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+});
+
+Clipperz.Crypto.ECC.BinaryField.WordArrayValue.O = new Clipperz.Crypto.ECC.BinaryField.WordArrayValue('0', 16);
+Clipperz.Crypto.ECC.BinaryField.WordArrayValue.I = new Clipperz.Crypto.ECC.BinaryField.WordArrayValue('1', 16);
+
+Clipperz.Crypto.ECC.BinaryField.WordArrayValue.xor = function(a, b) {
+ var result;
+ var resultSize;
+ var i,c;
+
+ resultSize = Math.max(a.length, b.length);
+
+ result = new Array(resultSize);
+ c = resultSize;
+ for (i=0; i<c; i++) {
+// resultValue[i] = (((this.value()[i] || 0) ^ (aValue.value()[i] || 0)) >>> 0);
+ result[i] = (((a[i] || 0) ^ (b[i] || 0)) >>> 0);
+ }
+
+ return result;
+};
+
+Clipperz.Crypto.ECC.BinaryField.WordArrayValue.shiftLeft = 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.WordArrayValue.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 {
+ while((aWordArray[notNullElements - 1] == 0) && (notNullElements > 0)) {
+ notNullElements --;
+ }
+
+ result = (notNullElements - 1) * 32;
+ mostValuableWord = aWordArray[notNullElements - 1];
+
+ matchingBits = 32;
+ mask = 0x80000000;
+
+ while ((matchingBits > 0) && ((mostValuableWord & mask) == 0)) {
+ matchingBits --;
+ mask >>>= 1;
+ }
+
+ result += matchingBits;
+ }
+
+ return result;
+};
+
+Clipperz.Crypto.ECC.BinaryField.WordArrayValue.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.WordArrayValue.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++) {
+//console.log("compare[" + c + " - " + i + " - 1] " + this.value()[c-i-1] + ", " + aValue.value()[c-i-1]);
+// result = MochiKit.Base.compare(this.value()[c-i-1], aValue.value()[c-i-1]);
+ result = MochiKit.Base.compare(a[c-i-1], b[c-i-1]);
+ }
+
+ return result;
+};
+
+
+Clipperz.Crypto.ECC.BinaryField.WordArrayValue['exception']= {
+ 'UnsupportedBase': new MochiKit.Base.NamedError("Clipperz.Crypto.ECC.BinaryField.WordArrayValue.exception.UnsupportedBase"),
+ 'UnsupportedConstructorValueType': new MochiKit.Base.NamedError("Clipperz.Crypto.ECC.BinaryField.WordArrayValue.exception.UnsupportedConstructorValueType")
+};
+
+//*****************************************************************************
+
+//Clipperz.Crypto.ECC.BinaryField.Value = Clipperz.Crypto.ECC.BinaryField.BigIntValue;
+Clipperz.Crypto.ECC.BinaryField.Value = Clipperz.Crypto.ECC.BinaryField.WordArrayValue;
+
+//#############################################################################
+
+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"
+});
+
+//#############################################################################
+
+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;
+//console.log(">>> binaryField.finiteField.(standard)module");
+
+ modulusComparison = Clipperz.Crypto.ECC.BinaryField.WordArrayValue.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.WordArrayValue.bitSize(result);
+ while (resultBitSize >= modulusBitSize) {
+ result = Clipperz.Crypto.ECC.BinaryField.WordArrayValue.xor(result, Clipperz.Crypto.ECC.BinaryField.WordArrayValue.shiftLeft(this.modulus()._value, resultBitSize - modulusBitSize));
+ resultBitSize = Clipperz.Crypto.ECC.BinaryField.WordArrayValue.bitSize(result);
+ }
+ }
+//console.log("<<< binaryField.finiteField.(standard)module");
+
+ return result;
+ },
+
+ 'module': function(aValue) {
+ return new Clipperz.Crypto.ECC.BinaryField.Value(this._module(aValue._value));
+ },
+
+ //-----------------------------------------------------------------------------
+
+ '_add': function(a, b) {
+ return Clipperz.Crypto.ECC.BinaryField.WordArrayValue.xor(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 = Clipperz.Crypto.ECC.BinaryField.Value.O;
+ valueToXor = b;
+ c = a.bitSize();
+ for (i=0; i<c; i++) {
+ if (a.isBitSet(i) === true) {
+ result = result.xor(valueToXor);
+ }
+ valueToXor = valueToXor.shiftLeft(1);
+ }
+ result = this.module(result);
+
+ return result;
+ },
+* /
+
+ '_multiply': function(a, b) {
+ var result;
+ var valueToXor;
+ var i,c;
+
+ result = [0];
+ valueToXor = b;
+ c = Clipperz.Crypto.ECC.BinaryField.WordArrayValue.bitSize(a);
+ for (i=0; i<c; i++) {
+ if (Clipperz.Crypto.ECC.BinaryField.WordArrayValue.isBitSet(a, i) === true) {
+ result = Clipperz.Crypto.ECC.BinaryField.WordArrayValue.xor(result, valueToXor);
+ }
+ valueToXor = Clipperz.Crypto.ECC.BinaryField.WordArrayValue.shiftLeft(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));
+ },
+
+ //-----------------------------------------------------------------------------
+ //
+ // Guide to Elliptic Curve Cryptography
+ // Darrel Hankerson, Alfred Menezes, Scott Vanstone
+ // - Pag: 49, Alorithm 2.34
+ //
+ //-----------------------------------------------------------------------------
+/ *
+ 'square': function(aValue) {
+ var result;
+ var t;
+ var i,c;
+
+ result = [0];
+ t = Math.max(a)
+ c = 32;
+ for (i=0; i<c; i++) {
+ var ii, cc;
+
+ cc =
+ }
+
+
+
+
+ return result;
+ },
+* /
+ //-----------------------------------------------------------------------------
+
+ 'inverse': function(aValue) {
+ var result;
+ var b, c;
+ var u, v;
+
+ b = Clipperz.Crypto.ECC.BinaryField.Value.I;
+ c = Clipperz.Crypto.ECC.BinaryField.Value.O;
+ u = this.module(aValue);
+ v = this.modulus();
+
+ while (u.bitSize() > 1) {
+ var bitDifferenceSize;
+
+ bitDifferenceSize = u.bitSize() - v.bitSize();
+ if (bitDifferenceSize < 0) {
+ var swap;
+
+ swap = u;
+ u = v;
+ v = swap;
+
+ swap = c;
+ c = b;
+ b = swap;
+
+ bitDifferenceSize = -bitDifferenceSize;
+ }
+
+ u = this.add(u, v.shiftLeft(bitDifferenceSize));
+ b = this.add(b, c.shiftLeft(bitDifferenceSize))
+ }
+
+ result = this.module(b);
+
+ return result;
+ },
+
+ //-----------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+});
+
+//#############################################################################
+
+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;
+
+//console.log(">>> ECC.BinaryField.Curve.add");
+ if (aPointA.isZero()) {
+//console.log("--- pointA == zero");
+ result = aPointB;
+ } else if (aPointB.isZero()) {
+//console.log("--- pointB == zero");
+ result = aPointA;
+ } else if ( (aPointA.x().compare(aPointB.x()) == 0) &&
+ ((aPointA.y().compare(aPointB.y()) != 0) || aPointB.x().isZero()))
+ {
+//console.log("compare A.x - B.x: ", aPointA.x().compare(aPointB.x()));
+//console.log("compare A.y - B.y: ", (aPointA.y().compare(aPointB.y()) != 0));
+//console.log("compare B.x.isZero(): ", aPointB.x().isZero());
+
+//console.log("--- result = zero");
+ result = new Clipperz.Crypto.ECC.BinaryField.Point({x:Clipperz.Crypto.ECC.BinaryField.Value.O, y:Clipperz.Crypto.ECC.BinaryField.Value.O});
+ } else {
+//console.log("--- result = ELSE");
+ var f2m;
+ var x, y;
+ var lambda;
+
+ f2m = this.finiteField();
+
+ if (aPointA.x().compare(aPointB.x()) != 0) {
+//console.log(" a.x != b.x");
+ lambda = f2m.multiply(
+ f2m.add(aPointA.y(), aPointB.y()),
+ f2m.inverse(f2m.add(aPointA.x(), aPointB.x()))
+ );
+ x = f2m.add(this.a(), f2m.multiply(lambda, lambda));
+ x = f2m.add(x, lambda);
+ x = f2m.add(x, aPointA.x());
+ x = f2m.add(x, aPointB.x());
+ } else {
+//console.log(" a.x == b.x");
+ lambda = f2m.add(aPointB.x(), f2m.multiply(aPointB.y(), f2m.inverse(aPointB.x())));
+//console.log(" lambda: " + lambda.asString(16));
+ x = f2m.add(this.a(), f2m.multiply(lambda, lambda));
+//console.log(" x (step 1): " + x.asString(16));
+ x = f2m.add(x, lambda);
+//console.log(" x (step 2): " + x.asString(16));
+ }
+
+ y = f2m.multiply(f2m.add(aPointB.x(), x), lambda);
+//console.log(" y (step 1): " + y.asString(16));
+ y = f2m.add(y, x);
+//console.log(" y (step 2): " + y.asString(16));
+ y = f2m.add(y, aPointB.y());
+//console.log(" y (step 3): " + y.asString(16));
+
+ result = new Clipperz.Crypto.ECC.BinaryField.Point({x:x, y:y})
+ }
+//console.log("<<< ECC.BinaryField.Curve.add");
+
+ 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.WordArrayValue.O) > 0) {
+ k = aValue;
+ Q = aPoint;
+ } else {
+MochiKit.Logging.logError("The Clipperz.Crypto.ECC.BinaryFields.Value does not work with negative values!!!!");
+ k = aValue.negate();
+ Q = this.negate(aPoint);
+ }
+
+//console.log("k: " + k.toString(16));
+//console.log("k.bitSize: " + k.bitSize());
+ for (i=k.bitSize()-1; i>=0; i--) {
+ result = this.add(result, result);
+ if (k.isBitSet(i)) {
+ result = this.add(result, Q);
+ }
+
+// if (countIndex==100) {console.log("multiply.break"); break;} else countIndex++;
+ }
+ }
+console.profileEnd();
+
+ return result;
+ },
+
+ //-----------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+});
+
+//#############################################################################
+
+//#############################################################################
+/ *
+Clipperz.Crypto.ECC.Key = function(args) {
+ args = args || {};
+
+ return this;
+}
+
+Clipperz.Crypto.ECC.Key.prototype = MochiKit.Base.update(null, {
+
+ 'asString': function() {
+ return "Clipperz.Crypto.ECC.Key";
+ },
+
+ //-----------------------------------------------------------------------------
+ __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.Curve.Koblitz({
+ exadecimalForm: '80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000425',
+ a: new Clipperz.Crypto.BigInt(0),
+ G: new Clipperz.Crypto.ECC.Point({
+ x: new Clipperz.Crypto.BigInt('26eb7a859923fbc82189631f8103fe4ac9ca2970012d5d46024804801841ca44370958493b205e647da304db4ceb08cbbd1ba39494776fb988b47174dca88c7e2945283a01c8972', 16),
+ y: new Clipperz.Crypto.BigInt('349dc807f4fbf374f4aeade3bca95314dd58cec9f307a54ffc61efc006d8a2c9d4979c0ac44aea74fbebbb9f772aedcb620b01a7ba7af1b320430c8591984f601cd4c143ef1c7a3', 16)
+ }),
+ n: new Clipperz.Crypto.BigInt('1932268761508629172347675945465993672149463664853217499328617625725759571144780212268133978522706711834706712800825351461273674974066617311929682421617092503555733685276673', 16),
+ h: new Clipperz.Crypto.BigInt(4)
+ });
+ }
+
+ return Clipperz.Crypto.ECC.StandardCurves._K571;
+ },
+* /
+ //-----------------------------------------------------------------------------
+
+ '_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('0303001d34b856296c16c0d40d3cd7750a93d1d2955fa80aa5f40fc8db7b2abdbde53950f4c0d293cdd711a35b67fb1499ae60038614f1394abfa3b4c850d927e1e7769c8eec2d19', 16),
+ y: new Clipperz.Crypto.ECC.BinaryField.Value('037bf27342da639b6dccfffeb73d69d78c6c27a6009cbbca1980f8533921e8a684423e43bab08a576291af8f461bb2a8b3531d2f0485c19b16e2f1516e23dd3c1a4827af1b8ac15b', 16)
+ }),
+// r: new Clipperz.Crypto.ECC.BinaryField.Value('3864537523017258344695351890931987344298927329706434998657235251451519142289560424536143999389415773083133881121926944486246872462816813070234528288303332411393191105285703', 10),
+ r: new Clipperz.Crypto.ECC.BinaryField.Value('03ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe661ce18ff55987308059b186823851ec7dd9ca1161de93d5174d66e8382e9bb2fe84e47', 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().module = function(aValue) {
+ var result;
+ var C, T;
+ var i;
+
+//console.log(">>> binaryField.finiteField.(improved)module");
+// C = aValue.value().slice(0);
+ 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.WordArrayValue(C);
+//console.log("<<< binaryField.finiteField.(improved)module");
+
+ return result;
+ };
+ }
+
+ return Clipperz.Crypto.ECC.StandardCurves._B571;
+ },
+
+ //-----------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+});
+
+//#############################################################################
+*/
diff --git a/frontend/beta/js/Clipperz/Crypto/ECC/BinaryField/Curve.js b/frontend/beta/js/Clipperz/Crypto/ECC/BinaryField/Curve.js
new file mode 100644
index 0000000..042ca6c
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/Crypto/ECC/BinaryField/Curve.js
@@ -0,0 +1,461 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. 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;
+
+//console.log(">>> ECC.BinaryField.Curve.add");
+ if (aPointA.isZero()) {
+//console.log("--- pointA == zero");
+ result = aPointB;
+ } else if (aPointB.isZero()) {
+//console.log("--- pointB == zero");
+ result = aPointA;
+ } else if ( (aPointA.x().compare(aPointB.x()) == 0) && ((aPointA.y().compare(aPointB.y()) != 0) || aPointB.x().isZero())) {
+//console.log("compare A.x - B.x: ", aPointA.x().compare(aPointB.x()));
+//console.log("compare A.y - B.y: ", (aPointA.y().compare(aPointB.y()) != 0));
+//console.log("compare B.x.isZero(): ", aPointB.x().isZero());
+
+//console.log("--- result = zero");
+ result = new Clipperz.Crypto.ECC.BinaryField.Point({x:Clipperz.Crypto.ECC.BinaryField.Value.O, y:Clipperz.Crypto.ECC.BinaryField.Value.O});
+ } else {
+//console.log("--- result = 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) {
+//console.log(" a.x != b.x");
+ 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 {
+//console.log(" a.x == b.x");
+ lambda = f2m._add(bX, f2m._fastMultiply(bY, f2m._inverse(bX)));
+//console.log(" lambda: " + lambda.asString(16));
+ x = f2m._add(this.a()._value, f2m._square(lambda));
+//console.log(" x (step 1): " + x.asString(16));
+ f2m._overwriteAdd(x, lambda);
+//console.log(" x (step 2): " + x.asString(16));
+ }
+
+ y = f2m._fastMultiply(f2m._add(bX, x), lambda);
+//console.log(" y (step 1): " + y.asString(16));
+ f2m._overwriteAdd(y, x);
+//console.log(" y (step 2): " + y.asString(16));
+ f2m._overwriteAdd(y, bY);
+//console.log(" y (step 3): " + y.asString(16));
+
+ result = new Clipperz.Crypto.ECC.BinaryField.Point({x:new Clipperz.Crypto.ECC.BinaryField.Value(x), y:new Clipperz.Crypto.ECC.BinaryField.Value(y)})
+ }
+//console.log("<<< ECC.BinaryField.Curve.add");
+
+ return result;
+ },
+
+ //-----------------------------------------------------------------------------
+
+ '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) {
+//console.log(" a.x != b.x");
+ 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 {
+//console.log(" a.x == b.x");
+ lambda = f2m._add(bX, f2m._fastMultiply(bY, f2m._inverse(bX)));
+//console.log(" lambda: " + lambda.asString(16));
+ x = f2m._add(this.a()._value, f2m._square(lambda));
+//console.log(" x (step 1): " + x.asString(16));
+ f2m._overwriteAdd(x, lambda);
+//console.log(" x (step 2): " + x.asString(16));
+ }
+
+ y = f2m._fastMultiply(f2m._add(bX, x), lambda);
+//console.log(" y (step 1): " + y.asString(16));
+ f2m._overwriteAdd(y, x);
+//console.log(" y (step 2): " + y.asString(16));
+ f2m._overwriteAdd(y, bY);
+//console.log(" y (step 3): " + y.asString(16));
+
+// 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;
+
+ }
+//console.log("<<< ECC.BinaryField.Curve.add");
+
+ 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 {
+MochiKit.Logging.logError("The Clipperz.Crypto.ECC.BinaryFields.Value does not work with negative values!!!!");
+ k = aValue.negate();
+ Q = this.negate(aPoint);
+ }
+
+//console.log("k: " + k.toString(16));
+//console.log("k.bitSize: " + k.bitSize());
+ 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) {console.log("multiply.break"); break;} else countIndex++;
+ }
+ }
+//console.profileEnd();
+
+ return result;
+ },
+
+ //-----------------------------------------------------------------------------
+ __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.Curve.Koblitz({
+ exadecimalForm: '80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000425',
+ a: new Clipperz.Crypto.BigInt(0),
+ G: new Clipperz.Crypto.ECC.Point({
+ x: new Clipperz.Crypto.BigInt('26eb7a859923fbc82189631f8103fe4ac9ca2970012d5d46024804801841ca44370958493b205e647da304db4ceb08cbbd1ba39494776fb988b47174dca88c7e2945283a01c8972', 16),
+ y: new Clipperz.Crypto.BigInt('349dc807f4fbf374f4aeade3bca95314dd58cec9f307a54ffc61efc006d8a2c9d4979c0ac44aea74fbebbb9f772aedcb620b01a7ba7af1b320430c8591984f601cd4c143ef1c7a3', 16)
+ }),
+ n: new Clipperz.Crypto.BigInt('1932268761508629172347675945465993672149463664853217499328617625725759571144780212268133978522706711834706712800825351461273674974066617311929682421617092503555733685276673', 16),
+ h: new Clipperz.Crypto.BigInt(4)
+ });
+ }
+
+ return Clipperz.Crypto.ECC.StandardCurves._K571;
+ },
+*/
+ //-----------------------------------------------------------------------------
+
+ '_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) {
+ MochiKit.Logging.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;
+
+//console.log(">>> binaryField.finiteField.(improved)module");
+// C = aValue.value().slice(0);
+ 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);
+//console.log("<<< binaryField.finiteField.(improved)module");
+ }
+
+ 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) {
+ MochiKit.Logging.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;
+
+//console.log(">>> binaryField.finiteField.(improved)module");
+ 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);
+//console.log("<<< binaryField.finiteField.(improved)module");
+ }
+
+ return result;
+ };
+ }
+
+ return Clipperz.Crypto.ECC.StandardCurves._B283;
+ },
+
+ //-----------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+});
+
+//#############################################################################
+
diff --git a/frontend/beta/js/Clipperz/Crypto/ECC/BinaryField/FiniteField.js b/frontend/beta/js/Clipperz/Crypto/ECC/BinaryField/FiniteField.js
new file mode 100644
index 0000000..3ddf2ec
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/Crypto/ECC/BinaryField/FiniteField.js
@@ -0,0 +1,526 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. 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;
+//console.log(">>> binaryField.finiteField.(standard)module");
+
+ 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);
+ }
+ }
+//console.log("<<< binaryField.finiteField.(standard)module");
+
+ 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
+
+]
diff --git a/frontend/beta/js/Clipperz/Crypto/ECC/BinaryField/Point.js b/frontend/beta/js/Clipperz/Crypto/ECC/BinaryField/Point.js
new file mode 100644
index 0000000..f0739bc
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/Crypto/ECC/BinaryField/Point.js
@@ -0,0 +1,67 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. 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"
+});
diff --git a/frontend/beta/js/Clipperz/Crypto/ECC/BinaryField/Value.js b/frontend/beta/js/Clipperz/Crypto/ECC/BinaryField/Value.js
new file mode 100644
index 0000000..10d055e
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/Crypto/ECC/BinaryField/Value.js
@@ -0,0 +1,377 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. 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.Value = function(aValue, aBase) {
+ 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;
+ }
+
+ 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));
+ },
+
+ //-----------------------------------------------------------------------------
+
+ '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) {
+ return new Clipperz.Crypto.ECC.BinaryField.Value(Clipperz.Crypto.ECC.BinaryField.Value._shiftLeft(this._value, aNumberOfBitsToShift));
+ },
+
+ //-----------------------------------------------------------------------------
+
+ 'bitSize': function() {
+ return Clipperz.Crypto.ECC.BinaryField.Value._bitSize(this._value);
+ },
+
+ //-----------------------------------------------------------------------------
+
+ '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 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._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 {
+ while((aWordArray[notNullElements - 1] == 0) && (notNullElements > 0)) {
+ notNullElements --;
+ }
+
+ result = (notNullElements - 1) * 32;
+ mostValuableWord = aWordArray[notNullElements - 1];
+
+ 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++) {
+//console.log("compare[" + c + " - " + i + " - 1] " + this.value()[c-i-1] + ", " + aValue.value()[c-i-1]);
+// result = MochiKit.Base.compare(this.value()[c-i-1], aValue.value()[c-i-1]);
+ 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")
+};
diff --git a/frontend/beta/js/Clipperz/Crypto/PRNG.js b/frontend/beta/js/Clipperz/Crypto/PRNG.js
new file mode 100644
index 0000000..770ceb1
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/Crypto/PRNG.js
@@ -0,0 +1,854 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. 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) {
+MochiKit.Logging.logDebug("### 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 {
+MochiKit.Logging.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;
+
+//MochiKit.Logging.logDebug(">>> PRNG.deferredEntropyCollection");
+
+ if (this.isReadyToGenerateRandomValues()) {
+//MochiKit.Logging.logDebug("--- PRNG.deferredEntropyCollection - 1");
+ result = aValue;
+ } else {
+//MochiKit.Logging.logDebug("--- PRNG.deferredEntropyCollection - 2");
+ var deferredResult;
+
+ Clipperz.NotificationCenter.notify(this, 'updatedProgressState', 'collectingEntropy', true);
+
+ deferredResult = new MochiKit.Async.Deferred();
+// deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("1.2.1 - PRNG.deferredEntropyCollection - 1: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.partial(MochiKit.Async.succeed, aValue));
+// deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("1.2.2 - PRNG.deferredEntropyCollection - 2: " + res); return res;});
+ MochiKit.Signal.connect(this,
+ 'readyToGenerateRandomBytes',
+ deferredResult,
+ 'callback');
+
+ result = deferredResult;
+ }
+//MochiKit.Logging.logDebug("<<< PRNG.deferredEntropyCollection - result: " + result);
+
+ 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);
diff --git a/frontend/beta/js/Clipperz/Crypto/RSA.js b/frontend/beta/js/Clipperz/Crypto/RSA.js
new file mode 100644
index 0000000..4dad8f7
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/Crypto/RSA.js
@@ -0,0 +1,151 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. 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"
+
+ //-------------------------------------------------------------------------
+
+});
+
+//#############################################################################
+
diff --git a/frontend/beta/js/Clipperz/Crypto/SHA.js b/frontend/beta/js/Clipperz/Crypto/SHA.js
new file mode 100644
index 0000000..bb50b4f
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/Crypto/SHA.js
@@ -0,0 +1,296 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. 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;
+ 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"
+
+});
diff --git a/frontend/beta/js/Clipperz/Crypto/SRP.js b/frontend/beta/js/Clipperz/Crypto/SRP.js
new file mode 100644
index 0000000..0eef6ec
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/Crypto/SRP.js
@@ -0,0 +1,331 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. 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);
+//MochiKit.Logging.logDebug("SRP a: " + this._a);
+ }
+
+ 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)) {
+MochiKit.Logging.logError("Clipperz.Crypto.SRP.Connection: trying to set 'A' to 0.");
+ throw Clipperz.Crypto.SRP.exception.InvalidValue;
+ }
+//MochiKit.Logging.logDebug("SRP A: " + this._A);
+ }
+
+ return this._A;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 's': function () {
+ return this._s;
+//MochiKit.Logging.logDebug("SRP s: " + 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;
+//MochiKit.Logging.logDebug("SRP B: " + this._B);
+ } else {
+MochiKit.Logging.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);
+//MochiKit.Logging.logDebug("SRP x: " + this._x);
+ }
+
+ return this._x;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'u': function () {
+ if (this._u == null) {
+ this._u = new Clipperz.Crypto.BigInt(this.stringHash(this.B().asString()), 16);
+//MochiKit.Logging.logDebug("SRP u: " + this._u);
+ }
+
+ 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()
+ )
+//MochiKit.Logging.logDebug("SRP S: " + this._S);
+ }
+
+ return this._S;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'K': function () {
+ if (this._K == null) {
+ this._K = this.stringHash(this.S().asString());
+//MochiKit.Logging.logDebug("SRP K: " + this._K);
+ }
+
+ return this._K;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'M1': function () {
+ if (this._M1 == null) {
+ this._M1 = this.stringHash(this.A().asString(10) + this.B().asString(10) + this.K());
+//MochiKit.Logging.logDebug("SRP M1: " + this._M1);
+ }
+
+ return this._M1;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'M2': function () {
+ if (this._M2 == null) {
+ this._M2 = this.stringHash(this.A().asString(10) + this.M1() + this.K());
+//MochiKit.Logging.logDebug("SRP M2: " + this._M2);
+ }
+
+ 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"
+
+});
+
+//#############################################################################
diff --git a/frontend/beta/js/Clipperz/DOM.js b/frontend/beta/js/Clipperz/DOM.js
new file mode 100644
index 0000000..7c27359
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/DOM.js
@@ -0,0 +1,131 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. 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"
+MochiKit.Logging.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;
+ });
+ },
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+
+});
+
diff --git a/frontend/beta/js/Clipperz/Date.js b/frontend/beta/js/Clipperz/Date.js
new file mode 100644
index 0000000..4103b88
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/Date.js
@@ -0,0 +1,305 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. 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;
+
+//MochiKit.Logging.logDebug(">>> Clipperz.Date.formatDateWithPHPLikeTemplateAndLocale");
+ 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 += ";}";
+//MochiKit.Logging.logDebug("--- Clipperz.Date.formatDateWithPHPLikeTemplateAndLocale - formatterCode: " + formatterCode);
+ eval(formatterCode);
+
+ result = Clipperz.Date.__scratchFormatter.call(this, aDate, aLocale);
+ delete Clipperz.Date.__scratchFormatter;
+//MochiKit.Logging.logDebug("<<< Clipperz.Date.formatDateWithPHPLikeTemplateAndLocale");
+
+ 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"
+
+});
+
diff --git a/frontend/beta/js/Clipperz/KeePassExportProcessor.js b/frontend/beta/js/Clipperz/KeePassExportProcessor.js
new file mode 100644
index 0000000..ba56b8e
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/KeePassExportProcessor.js
@@ -0,0 +1,251 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. 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, {
+
+ //-------------------------------------------------------------------------
+/*
+ 'parse': function(aValue) {
+ var result;
+
+//MochiKit.Logging.logDebug(">>> KeePassExportProcessor.parse");
+ result = [];
+//MochiKit.Logging.logDebug("--- KeePassExportProcessor.parse - result: " + Clipperz.Base.serializeJSON(result));
+//MochiKit.Logging.logDebug("<<< KeePassExportProcessor.parse");
+
+ return result;
+ },
+*/
+ //-------------------------------------------------------------------------
+
+ 'deferredParse_core': function(aContext) {
+ var deferredResult;
+
+//MochiKit.Logging.logDebug(">>> KeePassExportProcessor.deferredParse_core");
+//MochiKit.Logging.logDebug("--- KeePassExportProcessor.deferredParse_core - (1) aContext.line: " + aContext.line.replace(/\n/g, "\\n").substring(0,50));
+//MochiKit.Logging.logDebug("--- KeePassExportProcessor.deferredParse_core - aContext: " + Clipperz.Base.serializeJSON(aContext).substring(0,50));
+//MochiKit.Logging.logDebug("--- KeePassExportProcessor.deferredParse_core - (2) aContext.line: " + aContext.line.replace(/\n/g, "\\n").substring(0,50));
+//console.log("deferredParse_core - aContext", aContext);
+//MochiKit.Logging.logDebug("--- KeePassExportProcessor.deferredParse_core - (3) aContext.line: " + aContext.line.replace(/\n/g, "\\n").substring(0,50));
+ if (aContext.line == "") {
+ deferredResult = MochiKit.Async.succeed(aContext.result);
+ } else {
+ var record;
+
+ record = this.parseRecord(aContext);
+ if (record != null) {
+ aContext.result.push(record);
+ }
+
+//MochiKit.Logging.logDebug("--> KeePassExportProcessor.deferredParse_core - aContext.line: " + aContext.line.replace(/\n/g, "\\n").substring(0,50));
+ aContext.line = aContext.line.replace(/^\n*/g, "").replace(/\n$/g, "");
+//MochiKit.Logging.logDebug("<-- KeePassExportProcessor.deferredParse_core - aContext.line: " + aContext.line.replace(/\n/g, "\\n").substring(0,50));
+
+ deferredResult = new MochiKit.Async.Deferred();
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("KeePassExportProcessor.deferredParse_core - 1.1 " + res); return res;});
+ deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'importProcessorProgressUpdate', {status:'processing', size:aContext.size, progress:(aContext.size - aContext.line.length)});
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("KeePassExportProcessor.deferredParse_core - 1.2 " + res); return res;});
+ deferredResult.addCallback(MochiKit.Async.wait, 0.2);
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("KeePassExportProcessor.deferredParse_core - 1.3 " + res); return res;});
+//deferredResult.addBoth(function(res) {console.log("KeePassExportProcessor.deferredParse_core - 1.3 ", res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(this, 'deferredParse_core'))
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("KeePassExportProcessor.deferredParse_core - 1.4 " + res); return res;});
+ deferredResult.callback(aContext);
+ }
+//MochiKit.Logging.logDebug("<<< KeePassExportProcessor.deferredParse_core");
+
+ return deferredResult;
+ },
+
+ //.........................................................................
+
+ 'deferredParse': function(aValue) {
+ var deferredResult;
+ var lines;
+ var context;
+
+//MochiKit.Logging.logDebug(">>> KeePassExportProcessor.deferredParse");
+//MochiKit.Logging.logDebug("--- KeePassExportProcessor.deferredParse - aValue: " + aValue.length);
+ lines = aValue.replace(/\r?\n/g, "\n");
+//MochiKit.Logging.logDebug("--- KeePassExportProcessor.deferredParse - lines: " + lines.length);
+ context = {
+ line: lines,
+ size: lines.length,
+ result: []
+ }
+//MochiKit.Logging.logDebug("--- KeePassExportProcessor.deferredParse - context: " + Clipperz.Base.serializeJSON(context).substring(0,50));
+//console.log("--- KeePassExportProcessor.deferredParse - context: ", context);
+
+ deferredResult = new MochiKit.Async.Deferred();
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("KeePassExportProcessor.deferredParse - 1 " + res); return res;});
+//deferredResult.addBoth(function(res) {console.log("KeePassExportProcessor.deferredParse - 1 ", res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(this, 'deferredParse_core'));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("KeePassExportProcessor.deferredParse - 2 " + res); return res;});
+ deferredResult.callback(context);
+//MochiKit.Logging.logDebug("<<< KeePassExportProcessor.deferredParse");
+
+ 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");
+// recordLabelRegexp = new RegExp("^\\[(.*)\\]$", "m");
+ fieldLabelRegexp = new RegExp("^(Group|Group Tree|UserName|URL|Password|Notes|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;
+
+//MochiKit.Logging.logDebug("1.0");
+ line = aContext.line;
+//MochiKit.Logging.logDebug("0 - line: " + line.replace(/\n/g, "\\n").substring(0,50));
+
+ result = {};
+ result['Title'] = line.match(recordLabelRegexp)[1];
+//MochiKit.Logging.logDebug("1 - title: " + result['Title']);
+ line = line.replace(/^.*\n/, "");
+//MochiKit.Logging.logDebug("2 - line: " + line.replace(/\n/g, "\\n").substring(0,50));
+//MochiKit.Logging.logDebug("=======================================");
+ while (fieldLabelRegexp.test(line) == true) {
+ var fieldName;
+ var fieldValue;
+
+ fieldName = RegExp.$1;
+//MochiKit.Logging.logDebug("3 - fieldName: " + fieldName);
+ line = RegExp.rightContext;
+//MochiKit.Logging.logDebug("4 - line: " + line.replace(/\n/g, "\\n").substring(0,50));
+
+ fieldValue = line.match(fieldValueRegexp)[1];
+//MochiKit.Logging.logDebug("5 - fieldValue: " + fieldValue);
+ line = RegExp.rightContext;
+//MochiKit.Logging.logDebug("6 - line: " + line.replace(/\n/g, "\\n").substring(0,50));
+
+ if (fieldName == 'Notes') {
+ var isMultiline;
+
+ isMultiline = false;
+
+//MochiKit.Logging.logDebug("7 - fieldLabelRegexp.test(line): " + fieldLabelRegexp.test(line) + " - recordLabelRegexp.test(line): " + recordLabelRegexp.test(line));
+ 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;
+//MochiKit.Logging.logDebug("8 - fieldValue: " + fieldValue);
+ line = RegExp.rightContext;
+//MochiKit.Logging.logDebug("9 - line: " + line.replace(/\n/g, "\\n").substring(0,50));
+//MochiKit.Logging.logDebug("10 - fieldLabelRegexp.test(line): " + fieldLabelRegexp.test(line) + " - recordLabelRegexp.test(line): " + recordLabelRegexp.test(line));
+ }
+
+ if (isMultiline) {
+ fieldValue = fieldValue.replace(/\n$/g, "");
+ } else {
+ fieldValue = fieldValue.replace(/\n\n$/g, "");
+ }
+
+ line = line.replace(/^\n/, '');
+ }
+//MochiKit.Logging.logDebug("5 - fieldValue: " + fieldValue);
+
+ result[fieldName] = fieldValue;
+//MochiKit.Logging.logDebug("6 - line: " + line.replace(/\n/g, "\\n").substring(0,50));
+//MochiKit.Logging.logDebug("---------------------------------------");
+ }
+ } else {
+//MochiKit.Logging.logDebug("2.0");
+ result = null;
+ }
+
+ aContext.line = line;
+//MochiKit.Logging.logDebug("#######################################");
+
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+});
+
+
diff --git a/frontend/beta/js/Clipperz/NotificationCenter.js b/frontend/beta/js/Clipperz/NotificationCenter.js
new file mode 100644
index 0000000..815d4fd
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/NotificationCenter.js
@@ -0,0 +1,325 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
+if (typeof(Clipperz.NotificationCenter) == 'undefined') { Clipperz.NotificationCenter = {}; }
+
+
+//#############################################################################
+
+Clipperz.NotificationCenterEvent = function(args) {
+ args = args || {};
+// MochiKit.Base.bindMethods(this);
+
+ this._source = args.source || null;
+ this._event = args.event || null;
+ this._parameters = args.parameters || null;
+ this._isSynchronous = args.isSynchronous || false;
+
+ return this;
+}
+
+//=============================================================================
+
+Clipperz.NotificationCenterEvent.prototype = MochiKit.Base.update(null, {
+
+ //-------------------------------------------------------------------------
+
+ 'toString': function() {
+ return "Clipperz.NotificationCenterEvent";
+ //return "Clipperz.NotificationCenterEvent {source: " + this.source() + ", event: " + this.event() + ", parameters: " + this.parameters() + "}";
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'source': function() {
+ return this._source;
+ },
+
+ 'setSource': function(aValue) {
+ this._source = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'event': function() {
+ return this._event;
+ },
+
+ 'setEvent': function(aValue) {
+ this._event = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'parameters': function() {
+ return this._parameters;
+ },
+
+ 'setParameters': function(aValue) {
+ this._parameters = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'isSynchronous': function() {
+ return this._isSynchronous;
+ },
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+});
+
+
+//#############################################################################
+//#############################################################################
+
+Clipperz.NotificationCenter = function(args) {
+ args = args || {};
+// MochiKit.Base.bindMethods(this);
+
+ this._listeners = {};
+ this._useSynchronousListenerInvocation = args.useSynchronousListenerInvocation || false;
+ this._timeoutDelay = args.timeoutDelay || 0.1;
+
+ return this;
+}
+
+//=============================================================================
+
+Clipperz.NotificationCenter.prototype = MochiKit.Base.update(null, {
+
+ //-------------------------------------------------------------------------
+
+ 'toString': function() {
+ return "Clipperz.NotificationCenter";
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'useSynchronousListenerInvocation': function() {
+ return this._useSynchronousListenerInvocation;
+ },
+
+ 'setUseSynchronousListenerInvocation': function(aValue) {
+ this._useSynchronousListenerInvocation = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'timeoutDelay': function() {
+ return this._timeoutDelay;
+ },
+
+ 'setTimeoutDelay': function(aValue) {
+ this._timeoutDelay = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'listeners': function() {
+ return this._listeners;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'register': function(aSource, anEvent, aListener, aMethod) {
+ var eventListeners;
+ var listenerInfo;
+ var eventKey;
+
+ if (anEvent != null) {
+ eventKey = anEvent;
+ } else {
+ eventKey = '_notificationCenter_matchAnyEvent_key_';
+ }
+
+ eventListeners = this.listeners()[eventKey];
+
+ if (eventListeners == null) {
+ eventListeners = [];
+ this.listeners()[eventKey] = eventListeners;
+ }
+
+ listenerInfo = {};
+ if (aSource != null) {
+ listenerInfo['source'] = aSource;
+ } else {
+ listenerInfo['source'] = 'any';
+ }
+
+ listenerInfo['listener'] = aListener;
+ listenerInfo['method'] = aMethod;
+
+ eventListeners.push(listenerInfo);
+
+ return listenerInfo;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'removeListenerInfoFromListeners': function(aListener, someListeners) {
+ var listenerIndex;
+ var i,c;
+
+ if (someListeners != null) {
+ listenerIndex = -1;
+ c = someListeners.length;
+ for (i=0; i<c; i++) {
+ var listenerInfo;
+
+ listenerInfo = someListeners[i];
+ if (listenerInfo['listener'] === aListener) {
+ listenerIndex = i;
+ }
+ }
+
+ if (listenerIndex != -1) {
+ Clipperz.Base.removeObjectAtIndexFromArray(listenerIndex, someListeners);
+ }
+ }
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'unregister': function(aListener, anEvent) {
+ if (anEvent == null) {
+ var allListenerList;
+ var i, c;
+
+// allListenerList = Clipperz.Base.values(this.listeners());
+ allListenerList = MochiKit.Base.values(this.listeners());
+ c = allListenerList.length;
+ for (i=0; i<c; i++) {
+ this.removeListenerInfoFromListeners(aListener, allListenerList[i]);
+ }
+ } else {
+ this.removeListenerInfoFromListeners(aListener, this.listeners()[anEvent]);
+ }
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'asysnchronousListenerNotification': function(anEventInfo, aMethod, aListener) {
+ MochiKit.Async.callLater(this.timeoutDelay(), MochiKit.Base.partial(MochiKit.Base.methodcaller(aMethod, anEventInfo), aListener));
+// setTimeout(MochiKit.Base.partial(MochiKit.Base.methodcaller(aMethod, anEventInfo), aListener), this.timeoutDelay());
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'processListenerInfo': function(anEventInfo, aListenerInfo) {
+ var shouldInvokeListenerMethod;
+
+ if (aListenerInfo['source'] == 'any') {
+ shouldInvokeListenerMethod = true;
+ } else {
+ if (aListenerInfo['source'] === anEventInfo.source()) {
+ shouldInvokeListenerMethod = true;
+ } else {
+ shouldInvokeListenerMethod = false;
+ }
+ }
+
+ if (shouldInvokeListenerMethod) {
+ if (this.useSynchronousListenerInvocation() || anEventInfo.isSynchronous()) {
+//MochiKit.Logging.logDebug("syncrhronous listener invocation");
+ try {
+// MochiKit.Base.map(MochiKit.Base.methodcaller(aListenerInfo['method'], anEventInfo), [aListenerInfo['listener']]);
+//console.log("notification: ", aListenerInfo['listener'], aListenerInfo['method'], anEventInfo);
+ MochiKit.Base.method(aListenerInfo['listener'], aListenerInfo['method'], anEventInfo)();
+ } catch(exception) {
+ MochiKit.Logging.logError('NotificationCenter ERROR: unable to invoke method \'' + aListenerInfo['method'] + '\' on object ' + aListenerInfo['listener']);
+ }
+ } else {
+ var asyncMethod;
+
+//MochiKit.Logging.logDebug("asyncrhronous listener invocation");
+ asyncMethod = MochiKit.Base.bind(this.asysnchronousListenerNotification, this)
+ MochiKit.Base.map(MochiKit.Base.partial(asyncMethod, anEventInfo, aListenerInfo['method']), [aListenerInfo['listener']]);
+ }
+ }
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'notify': function(aSource, anEvent, someEventParameters, isSynchronous) {
+ var eventInfo;
+ var processInfoMethod;
+
+//MochiKit.Logging.logDebug(">>> NotificationCenter.notify");
+ eventInfo = new Clipperz.NotificationCenterEvent({source:aSource, event:anEvent, parameters:someEventParameters, isSynchronous:isSynchronous});
+//MochiKit.Logging.logDebug("--- NotificationCenter.notify - 1");
+ processInfoMethod = MochiKit.Base.bind(this.processListenerInfo, this);
+//MochiKit.Logging.logDebug("--- NotificationCenter.notify - 2");
+
+ MochiKit.Base.map(MochiKit.Base.partial(processInfoMethod, eventInfo), this.listeners()[anEvent] || []);
+//MochiKit.Logging.logDebug("--- NotificationCenter.notify - 3");
+ MochiKit.Base.map(MochiKit.Base.partial(processInfoMethod, eventInfo), this.listeners()['_notificationCenter_matchAnyEvent_key_'] || []);
+//MochiKit.Logging.logDebug("<<< NotificationCenter.notify");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'deferredNotification': function(aSource, anEvent, someEventParameters, aDeferredResult) {
+
+ this.notify(aSource, anEvent, someEventParameters, true);
+
+ return aDeferredResult;
+// return MochiKit.Async.wait(1, aDeferredResult);
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'resetStatus': function() {
+ this._listeners = {};
+ },
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+
+});
+
+//#############################################################################
+
+Clipperz.NotificationCenter.defaultNotificationCenter = new Clipperz.NotificationCenter();
+
+Clipperz.NotificationCenter.notify = MochiKit.Base.method(Clipperz.NotificationCenter.defaultNotificationCenter, 'notify');
+Clipperz.NotificationCenter.register = MochiKit.Base.method(Clipperz.NotificationCenter.defaultNotificationCenter, 'register');
+Clipperz.NotificationCenter.unregister = MochiKit.Base.method(Clipperz.NotificationCenter.defaultNotificationCenter, 'unregister');
+Clipperz.NotificationCenter.deferredNotification = MochiKit.Base.method(Clipperz.NotificationCenter.defaultNotificationCenter, 'deferredNotification');
+/*
+_clipperz_notificationCenter_defaultNotificationCenter = null;
+
+Clipperz.NotificationCenter.defaultNotificationCenter = function() {
+ if (_clipperz_notificationCenter_defaultNotificationCenter == null) {
+ _clipperz_notificationCenter_defaultNotificationCenter = new Clipperz.NotificationCenter();
+ }
+
+ return _clipperz_notificationCenter_defaultNotificationCenter;
+};
+*/
diff --git a/frontend/beta/js/Clipperz/PM/BookmarkletProcessor.js b/frontend/beta/js/Clipperz/PM/BookmarkletProcessor.js
new file mode 100644
index 0000000..4dfdd8e
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/BookmarkletProcessor.js
@@ -0,0 +1,288 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
+if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
+//if (typeof(Clipperz.PM.BookmarkletProcessor) == 'undefined') { Clipperz.PM.BookmarkletProcessor = {}; }
+//if (typeof(Clipperz.PM.BookmarkletProcessor.versions) == 'undefined') { Clipperz.PM.BookmarkletProcessor.versions = {}; }
+
+/*
+Clipperz.PM.BookmarkletProcessor.versions['abstract'] = function(anUser, aConfiguration) {
+ this._user = anUser;
+ this._configuration = aConfiguration;
+
+ this._recordTitle = null;
+ this._record = null;
+ this._editableFields = null;
+
+ return this;
+}
+
+
+Clipperz.PM.BookmarkletProcessor.versions['abstract'].prototype = MochiKit.Base.update(null, {
+
+ 'toString': function() {
+ return "BookmarkletProcessor - " + this.user();
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'user': function() {
+ return this._user;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'configuration': function() {
+ return this._configuration;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'record': function() {
+ throw Clipperz.Base.exception.AbstractMethod;
+ },
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+});
+*/
+
+Clipperz.PM.BookmarkletProcessor = function(anUser, aConfiguration) {
+ this._user = anUser;
+ this._configuration = aConfiguration;
+
+ this._recordTitle = null;
+ this._record = null;
+ this._editableFields = null;
+ this._favicon = null;
+
+ return this;
+}
+
+Clipperz.PM.BookmarkletProcessor.prototype = MochiKit.Base.update(null, {
+
+ 'toString': function() {
+ return "BookmarkletProcessor - " + this.user();
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'user': function() {
+ return this._user;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'configuration': function() {
+ return this._configuration;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'recordTitle': function() {
+ if (this._recordTitle == null) {
+ this._recordTitle = this.configuration().page.title;
+ }
+
+ return this._recordTitle;
+ },
+
+ //-------------------------------------------------------------------------
+
+ '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'];
+//MochiKit.Logging.logDebug("+++ actionUrl: " + actionUrl);
+ this._hostname = actionUrl.replace(/^https?:\/\/([^\/]*)\/.*/, '$1');
+ }
+
+ return this._hostname;
+ },
+
+ 'favicon': function() {
+ if (this._favicon == null) {
+ this._favicon = "http://" + this.hostname() + "/favicon.ico";
+//MochiKit.Logging.logDebug("+++ favicon: " + this._favicon);
+ }
+
+ return this._favicon;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'record': function() {
+ if (this._record == null) {
+ var record;
+ var recordVersion;
+ var directLogin;
+ var bindings;
+ var i,c;
+
+ record = new Clipperz.PM.DataModel.Record({
+ label:this.recordTitle(),
+ notes:"",
+ user:this.user()
+ });
+ recordVersion = new Clipperz.PM.DataModel.RecordVersion(record, {})
+ record.setCurrentVersion(recordVersion);
+
+ bindings = {};
+
+ c = this.editableFields().length;
+ for (i=0; i<c; i++) {
+ var formField;
+ var recordField;
+
+//MochiKit.Logging.logDebug(">>> adding a field");
+ formField = this.editableFields()[i];
+ recordField = new Clipperz.PM.DataModel.RecordField({
+ recordVersion:recordVersion,
+ label:formField['name'],
+ value:formField['value'],
+ type:Clipperz.PM.Strings.inputTypeToRecordFieldType[formField['type']],
+ hidden:false
+ });
+ recordVersion.addField(recordField);
+
+ bindings[formField['name']] = recordField.key();
+//MochiKit.Logging.logDebug("<<< adding a field");
+ }
+
+ directLogin = new Clipperz.PM.DataModel.DirectLogin({
+ record:record,
+ label:this.recordTitle() + Clipperz.PM.Strings['newDirectLoginLabelSuffix'],
+// bookmarkletVersion:this.version(),
+ bookmarkletVersion:'0.2',
+ favicon:this.favicon(),
+ formData:this.configuration()['form'],
+ bindingData:bindings
+ });
+ record.addDirectLogin(directLogin);
+
+ this.user().addRecord(record);
+
+ this._record = record;
+ }
+
+ return this._record;
+ },
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+});
+
+//#############################################################################
+
+Clipperz.PM.BookmarkletProcessor.createRecordFromBookmarkletConfiguration = function(anUser, aConfiguration) {
+ var processor;
+
+ processor = new Clipperz.PM.BookmarkletProcessor(anUser, aConfiguration);
+
+ return processor.record();
+};
+
+//-----------------------------------------------------------------------------
+
+Clipperz.PM.BookmarkletProcessor.sanitizeBookmarkletConfiguration = function(aConfiguration) {
+ var result;
+
+// throw "XSS Bookmarklet attempt";
+
+ result = aConfiguration;
+
+ return result;
+};
+
+//-----------------------------------------------------------------------------
+
+Clipperz.PM.BookmarkletProcessor.checkBookmarkletConfiguration = function(aConfiguration, aButton, aCallback) {
+ var result;
+
+ try {
+ result = Clipperz.Base.evalJSON(aConfiguration);
+ result = Clipperz.PM.BookmarkletProcessor.sanitizeBookmarkletConfiguration(result);
+
+ if (result['version'] != '0.2.3') {
+ throw "WrongBookmarkletVersion";
+ }
+ } catch (exception) {
+ var title;
+ var message;
+
+ if (exception == "WrongBookmarkletVersion") {
+ title = Clipperz.PM.Strings['newRecordPanelWrongBookmarkletVersionExceptionTitle'];
+ message = Clipperz.PM.Strings['newRecordPanelWrongBookmarkletVersionExceptionMessage'];
+ } else {
+ title = Clipperz.PM.Strings['newRecordPanelGeneralExceptionTitle'];
+ message = Clipperz.PM.Strings['newRecordPanelGeneralExceptionMessage'];
+ }
+ Clipperz.PM.Components.MessageBox().show({
+ title:title,
+ text:message,
+ width:240,
+ fn:aCallback,
+ closable:false,
+ showProgressBar:false,
+ showCloseButton:false,
+ buttons:{'ok':Clipperz.PM.Strings['newRecordPanelExceptionPanelCloseButtonLabel']}
+ }, aButton);
+
+ throw exception;
+ }
+
+ return result;
+};
+
+//-----------------------------------------------------------------------------
diff --git a/frontend/beta/js/Clipperz/PM/Components/BaseComponent.js b/frontend/beta/js/Clipperz/PM/Components/BaseComponent.js
new file mode 100644
index 0000000..67e257b
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Components/BaseComponent.js
@@ -0,0 +1,124 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
+if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
+if (typeof(Clipperz.PM.Components) == 'undefined') { Clipperz.PM.Components = {}; }
+
+//#############################################################################
+
+var _Clipperz_PM_Components_Panels_base_id_ = 0;
+
+//#############################################################################
+
+Clipperz.PM.Components.BaseComponent = function(anElement, args) {
+ args = args || {};
+// MochiKit.Base.bindMethods(this);
+// Clipperz.PM.Components.BaseComponent.superclass.constructor.call(this, args);
+
+ this._element = anElement;
+ this._ids = {};
+
+ return this;
+}
+
+//=============================================================================
+
+//MochiKit.Base.update(Clipperz.PM.Components.BaseComponent.prototype, {
+YAHOO.extendX(Clipperz.PM.Components.BaseComponent, YAHOO.ext.util.Observable, {
+
+ 'isClipperzPMComponent': true,
+
+ //-------------------------------------------------------------------------
+
+ 'toString': function () {
+ return "Clipperz.PM.Components.BaseComponent component";
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'domHelper': function() {
+ return Clipperz.YUI.DomHelper;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'element': function() {
+//MochiKit.Logging.logDebug(">>> BaseComponent.element");
+ return this._element;
+ },
+
+ 'setElement': function(aValue) {
+ this._element = aValue;
+ },
+
+ //-----------------------------------------------------
+
+ 'remove': function() {
+//MochiKit.Logging.logDebug(">>> BaseComponent.remove");
+ Clipperz.NotificationCenter.unregister(this);
+ MochiKit.Signal.disconnectAllTo(this);
+//MochiKit.Logging.logDebug("<<< BaseComponent.remove");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'getId': function(aValue) {
+ var result;
+
+ result = this._ids[aValue];
+
+ if (typeof(result) == 'undefined') {
+ _Clipperz_PM_Components_Panels_base_id_ ++;
+
+ result = "Clipperz_PM_Components_Panels_" + aValue + "_" + _Clipperz_PM_Components_Panels_base_id_;
+ this._ids[aValue] = result;
+//MochiKit.Logging.logDebug(">>> getId(" + aValue + ") = " + result);
+ } else {
+//MochiKit.Logging.logDebug("<<< getId(" + aValue + ") = " + result);
+ }
+
+ return result;
+ },
+
+ 'getDom': function(aValue) {
+ return YAHOO.util.Dom.get(this.getId(aValue));
+ },
+
+ 'getElement': function(aValue) {
+ return YAHOO.ext.Element.get(this.getId(aValue));
+ },
+
+ 'getActor': function(aValue, anAnimator) {
+ return new YAHOO.ext.Actor(this.getDom(aValue), anAnimator);
+ },
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+
+});
diff --git a/frontend/beta/js/Clipperz/PM/Components/Compact/CompactHeader.js b/frontend/beta/js/Clipperz/PM/Components/Compact/CompactHeader.js
new file mode 100644
index 0000000..e51b56f
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Components/Compact/CompactHeader.js
@@ -0,0 +1,86 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
+if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
+if (typeof(Clipperz.PM.Components) == 'undefined') { Clipperz.PM.Components = {}; }
+if (typeof(Clipperz.PM.Components.Compact) == 'undefined') { Clipperz.PM.Components.Compact = {}; }
+
+Clipperz.PM.Components.Compact.CompactHeader = function(anElement, args) {
+
+ Clipperz.PM.Components.Compact.CompactHeader.superclass.constructor.call(this, anElement, args);
+
+ this.render();
+
+ return this;
+};
+
+YAHOO.extendX(Clipperz.PM.Components.Compact.CompactHeader, Clipperz.PM.Components.BaseComponent, {
+
+ 'toString': function() {
+ return "Clipperz.PM.Components.Compact.CompactHeader";
+ },
+
+ //-----------------------------------------------------
+
+ 'render': function() {
+ this.element().update("");
+
+ Clipperz.YUI.DomHelper.append(this.element().dom, {tag:'div', children:[
+ {tag:'img', src:'./images/logo.gif'},
+ {tag:'div', id:'lockBlock', children:[
+ {tag:'input', type:'checkbox', id:'autolock'},
+ {tag:'span', html:'auto'},
+ {tag:'a', href:'#', htmlString:Clipperz.PM.Strings['lockMenuLabel'], id:'lock'}
+ ]}
+ ]});
+
+ Clipperz.YUI.DomHelper.append(this.element().dom,
+ {tag:'div', id:'compactMiscLinks', children:[
+ {tag:'a', id:'donateHeaderIconLink', target:'_blank', href:Clipperz.PM.Strings['donateHeaderLinkUrl'], children:[
+ {tag:'img', id:'donateHeaderLinkIcon', src:'./images/smiles_small.gif'}
+ ]},
+ {tag:'ul', children:[
+ {tag:'li', children:[{tag:'a', id:'donateHeaderLink', html:'donate', target:'_blank'}]},
+ {tag:'li', children:[{tag:'a', id:'creditsHeaderLink', html:'credits', target:'_blank'}]},
+ {tag:'li', children:[{tag:'a', id:'feedbackHeaderLink', html:'feedback', target:'_blank'}]},
+ {tag:'li', children:[{tag:'a', id:'helpHeaderLink', html:'help', target:'_blank'}]},
+ {tag:'li', children:[{tag:'a', id:'forumHeaderLink', html:'forum', target:'_blank'}]}
+ ]}
+ ]}
+ );
+
+ YAHOO.ext.Element.get('lockBlock').setVisibilityMode(YAHOO.ext.Element.DISPLAY).hide();
+ Clipperz.NotificationCenter.notify(this, 'switchLanguage');
+ },
+
+ //-----------------------------------------------------
+ __syntaxFix__: '__syntaxFix__'
+});
+
+
diff --git a/frontend/beta/js/Clipperz/PM/Components/Compact/CompactInterface.js b/frontend/beta/js/Clipperz/PM/Components/Compact/CompactInterface.js
new file mode 100644
index 0000000..492f815
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Components/Compact/CompactInterface.js
@@ -0,0 +1,312 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
+if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
+if (typeof(Clipperz.PM.Components) == 'undefined') { Clipperz.PM.Components = {}; }
+if (typeof(Clipperz.PM.Components.Compact) == 'undefined') { Clipperz.PM.Components.Compact = {}; }
+
+Clipperz.PM.Components.Compact.CompactInterface = function(anElement, args) {
+
+ Clipperz.PM.Components.Compact.CompactInterface.superclass.constructor.call(this, anElement, args);
+
+ this._directLoginItemTemplate = null;
+ this._user = args.user;
+ this._autoLockTimer = null;
+
+ Clipperz.NotificationCenter.register(null, 'updatedProgressState', this, 'userNotificationHandler')
+ Clipperz.NotificationCenter.register(null, 'directLoginAdded', this, 'directLoginAddedHandler');
+
+ this.render();
+
+ return this;
+};
+
+YAHOO.extendX(Clipperz.PM.Components.Compact.CompactInterface, Clipperz.PM.Components.BaseComponent, {
+
+ 'toString': function() {
+ return "Clipperz.PM.Components.Compact.CompactInterface";
+ },
+
+ //-----------------------------------------------------
+
+ 'render': function() {
+ var result;
+ var layout;
+ var registerButton;
+
+//MochiKit.Logging.logDebug(">>> CompactInterface.render");
+ this.element().update("");
+
+ Clipperz.YUI.DomHelper.append(this.element().dom, {tag:'div', children:[
+ {tag:'div', id:this.getId('cantentPanel'), children:[
+ {tag:'h4', id:this.getId('message')},
+ {tag:'ul', id:'directLogins', children:[]}
+ ]},
+ {tag:'div', id:this.getId('lockPanel'), cls:'lockPanel', children:[
+ {tag:'div', htmlString:Clipperz.PM.Strings['lockDescription']},
+ {tag:'form', id:'lockDialogForm', children:[
+ {tag:'input', type:'password', id:this.getId('lockPassphrase')}
+ ]},
+ {tag:'div', id:this.getId('unlock')}
+ ]}
+ ]});
+
+ this.getElement('lockPanel').setVisibilityMode(YAHOO.ext.Element.DISPLAY).hide();
+
+ YAHOO.ext.Element.get('lockBlock').show();
+ MochiKit.Signal.connect(YAHOO.ext.Element.get('lock').dom, 'onclick', this, 'doLockEventHandler');
+ new YAHOO.ext.Button(this.getId('unlock'), {text:Clipperz.PM.Strings['unlockButtonLabel'], handler:this.doUnlockEventHandler, scope:this, minWidth:0});
+ this.getElement('unlock').swallowEvent('click', true);
+ new Clipperz.PM.Components.PasswordEntropyDisplay(this.getElement('lockPassphrase'));
+ MochiKit.Signal.connect('lockDialogForm', 'onsubmit', this, 'doUnlockEventHandler');
+
+ this.getElement('cantentPanel').setVisibilityMode(YAHOO.ext.Element.DISPLAY);
+//MochiKit.Logging.logDebug("<<< CompactInterface.render");
+
+ return result;
+ },
+
+ //-----------------------------------------------------
+
+ 'directLoginAddedHandler': function(anEvent) {
+ this.redrawDirectLoginItems();
+ },
+
+ //-----------------------------------------------------
+
+ 'compareDirectLogins': function(a, b) {
+ return MochiKit.Base.compare(a.label().toLowerCase(), b.label().toLowerCase());
+ },
+
+ //-----------------------------------------------------
+
+ 'redrawDirectLoginItems': function() {
+ var template;
+ var allDirectLogins;
+
+ this.getElement('message').setVisibilityMode(YAHOO.ext.Element.DISPLAY).hide();
+//MochiKit.Logging.logDebug(">>> CompactInterface.redrawDirectLoginItems");
+//MochiKit.Logging.logDebug("--- CompactInterface.redrawDirectLoginItems - 0");
+ MochiKit.Iter.forEach(YAHOO.ext.Element.get('directLogins').getChildrenByTagName('li'), function(aDirectLoginElement) {
+ MochiKit.Signal.disconnectAll(aDirectLoginElement.dom);
+//MochiKit.Logging.logDebug("disconnecting IMG " + aDirectLoginElement.getChildrenByTagName('img')[0].dom.src);
+ MochiKit.Signal.disconnectAll(aDirectLoginElement.getChildrenByTagName('img')[0].dom);
+ })
+//MochiKit.Logging.logDebug("--- CompactInterface.redrawDirectLoginItems - 1");
+ YAHOO.ext.Element.get('directLogins').update("");
+//MochiKit.Logging.logDebug("--- CompactInterface.redrawDirectLoginItems - 2");
+ allDirectLogins = MochiKit.Base.values(this.user().directLoginReferences());
+//MochiKit.Logging.logDebug("--- CompactInterface.redrawDirectLoginItems - 3");
+ allDirectLogins.sort(this.compareDirectLogins);
+
+//MochiKit.Logging.logDebug("--- CompactInterface.redrawDirectLoginItems - 4");
+ template = this.directLoginItemTemplate();
+//MochiKit.Logging.logDebug("--- CompactInterface.redrawDirectLoginItems - 5");
+ MochiKit.Iter.forEach(allDirectLogins, MochiKit.Base.bind(function(aDirectLogin) {
+ var directLoginElement;
+ var faviconImageElementID;
+
+ faviconImageElementID = aDirectLogin.reference() + "_faviconIMG";
+ directLoginElement = template.append('directLogins', {
+ elementID:faviconImageElementID,
+ faviconUrl:aDirectLogin.fixedFavicon(),
+ directLoginTitle:aDirectLogin.label(),
+ directLoginReference:aDirectLogin.reference()
+ }, true);
+//MochiKit.Logging.logDebug("--- CompactInterface.redrawDirectLoginItems - 6: " + recordElement.dom);
+ directLoginElement.addClassOnOver("hover");
+ MochiKit.Signal.connect(directLoginElement.dom, 'onclick', this, 'handleDirectLoginClick');
+
+ MochiKit.Signal.connect(faviconImageElementID, 'onload', this, 'handleLoadedFaviconImage');
+ MochiKit.Signal.connect(faviconImageElementID, 'onerror', aDirectLogin, 'handleMissingFaviconImage');
+ MochiKit.Signal.connect(faviconImageElementID, 'onabort', aDirectLogin, 'handleMissingFaviconImage');
+
+// YAHOO.ext.Element.get(faviconImageElementID).dom.src = aDirectLogin.fixedFavicon();
+ }, this));
+
+ this.resetAutoLockTimer();
+//MochiKit.Logging.logDebug("<<< CompactInterface.redrawDirectLoginItems");
+ },
+
+ //-----------------------------------------------------
+
+ 'directLoginItemTemplate': function() {
+ if (this._directLoginItemTemplate == null) {
+ this._directLoginItemTemplate = Clipperz.YUI.DomHelper.createTemplate({tag:'li', id:'{directLoginReference}', children:[
+ {tag:'table', border:'0', cellpadding:'0', cellspacing:'0', children:[
+ {tag:'tbody', children:[
+ {tag:'tr', children:[
+ {tag:'td', width:'20', align:'center', valign:'top', children:[
+ {tag:'img', id:'{elementID}', src:'{faviconUrl}'}
+ ]},
+ {tag:'td', valign:'top', children:[
+ {tag:'a', cls:'directLoginItemTitle', html:'{directLoginTitle}'}
+ ]}
+ ]}
+ ]}
+ ]}
+ ]});
+ this._directLoginItemTemplate.compile();
+ }
+
+ return this._directLoginItemTemplate;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'handleDirectLoginClick': function(anEvent) {
+ var directLoginReference;
+//MochiKit.Logging.logDebug(">>> MainPanel.handleDirectLoginClick !!!");
+
+ directLoginReference = this.user().directLoginReferences()[anEvent.src().id];
+ this.openDirectLogin(directLoginReference);
+ this.resetAutoLockTimer();
+//MochiKit.Logging.logDebug("<<< MainPanel.handleDirectLoginClick");
+ },
+
+ //-----------------------------------------------------
+
+ 'openDirectLogin': function(aDirectLoginReference) {
+ var deferredResult;
+ var newWindow;
+
+//MochiKit.Logging.logDebug(">>> MainPanel.openDirectLogin - " + aDirectLoginReference.label());
+ deferredResult = new MochiKit.Async.Deferred();
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("MainPanel.openDirectLogin - 1: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(aDirectLoginReference, 'setupJumpPageWindow'));
+ deferredResult.addCallback(MochiKit.Base.method(aDirectLoginReference, 'deferredDirectLogin'));
+ deferredResult.addCallback(function(aDirectLogin) {
+ aDirectLogin.runDirectLogin(newWindow);
+ });
+
+ newWindow = window.open(Clipperz.PM.Strings['directLoginJumpPageUrl'], "");
+// MochiKit.Signal.connect(newWindow, 'onload', MochiKit.Base.method(deferredResult, 'callback', newWindow))
+// MochiKit.Signal.connect(newWindow, 'onload', MochiKit.Base.partial(alert, "done"));
+ deferredResult.callback(newWindow);
+//MochiKit.Logging.logDebug("<<< MainPanel.openDirectLogin");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'handleLoadedFaviconImage': function(anEvent) {
+//MochiKit.Logging.logDebug(">>> MainPanel.handleLoadedFaviconImage");
+ MochiKit.Signal.disconnectAll(anEvent.src())
+//MochiKit.Logging.logDebug("<<< MainPanel.handleLoadedFaviconImage");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'doLockEventHandler': function(anEvent) {
+ anEvent.stop();
+ this.lock();
+ },
+
+ 'doUnlockEventHandler': function(anEvent) {
+ if (typeof(anEvent.stop) != 'undefined') {
+ anEvent.stop();
+ }
+ this.unlock();
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'autolock': function() {
+ var shouldAutoLock;
+
+ shouldAutoLock = YAHOO.ext.Element.get('autolock').dom.checked;
+
+ if (shouldAutoLock) {
+ this.lock();
+ } else {
+ this.resetAutoLockTimer();
+ }
+ },
+
+ 'lock': function() {
+//MochiKit.Logging.logDebug(">>> lock");
+ this.getDom('lockPassphrase').value = "";
+ this.getElement('lockPanel').show();
+ this.getElement('cantentPanel').hide();
+ YAHOO.ext.Element.get('lockBlock').hide();
+ //this.getElement('lockPassphrase').focus();
+//MochiKit.Logging.logDebug("<<< lock");
+ },
+
+ 'unlock': function(anEvent) {
+//MochiKit.Logging.logDebug(">>> unlock");
+ if (this.getDom('lockPassphrase').value == this.user().passphrase()) {
+ this.getElement('lockPanel').hide();
+ this.getElement('cantentPanel').show();
+ YAHOO.ext.Element.get('lockBlock').show();
+ this.resetAutoLockTimer();
+ } else {
+ this.getDom('lockPassphrase').value = "";
+ this.getElement('lockPassphrase').focus();
+ }
+//MochiKit.Logging.logDebug("<<< unlock");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'user': function() {
+ return this._user;
+ },
+
+ //-----------------------------------------------------
+
+ 'autoLockTimer': function() {
+ if (this._autoLockTimer == null) {
+//MochiKit.Logging.logDebug("--- timer started - 1");
+ this._autoLockTimer = MochiKit.Async.callLater(60, MochiKit.Base.method(this, 'autolock'));
+//MochiKit.Logging.logDebug("--- timer started - 2");
+ }
+
+ return this._autoLockTimer;
+ },
+
+ 'resetAutoLockTimer': function() {
+//MochiKit.Logging.logDebug(">>> timer resetted");
+ this.autoLockTimer().cancel();
+ this._autoLockTimer = null;
+//MochiKit.Logging.logDebug("--- timer resetted - 1");
+ this.autoLockTimer();
+//MochiKit.Logging.logDebug("<<< timer resetted");
+ },
+
+ //-----------------------------------------------------
+
+ 'userNotificationHandler': function(anEvent) {
+ this.getElement('message').update(anEvent.parameters().text);
+ },
+
+ //-----------------------------------------------------
+ __syntaxFix__: '__syntaxFix__'
+});
+
+
diff --git a/frontend/beta/js/Clipperz/PM/Components/Compact/LoginForm.js b/frontend/beta/js/Clipperz/PM/Components/Compact/LoginForm.js
new file mode 100644
index 0000000..d708464
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Components/Compact/LoginForm.js
@@ -0,0 +1,189 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
+if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
+if (typeof(Clipperz.PM.Components) == 'undefined') { Clipperz.PM.Components = {}; }
+if (typeof(Clipperz.PM.Components.Compact) == 'undefined') { Clipperz.PM.Components.Compact = {}; }
+
+Clipperz.PM.Components.Compact.LoginForm = function(anElement, args) {
+
+ Clipperz.PM.Components.Compact.LoginForm.superclass.constructor.call(this, anElement, args);
+
+ this.render();
+ Clipperz.NotificationCenter.register(null, 'updatedProgressState', this, 'userNotificationHandler')
+
+ return this;
+};
+
+YAHOO.extendX(Clipperz.PM.Components.Compact.LoginForm, Clipperz.PM.Components.BaseComponent, {
+
+ 'toString': function() {
+ return "Clipperz.PM.Components.Compact.LoginForm";
+ },
+
+ //-----------------------------------------------------
+
+ 'render': function() {
+ var result;
+ var layout;
+
+ MochiKit.Signal.disconnectAllTo(this);
+ this.element().update("");
+
+ Clipperz.YUI.DomHelper.append(this.element().dom, {tag:'div', id:this.getId('baseDiv'), cls:'LoginPanel', children:[
+ {tag:'div', id:'compactHeader'},
+ {tag:'div', id:'compactBody', children:[
+ {tag:'form', id:this.getId('loginForm_form'), children:[
+ {tag:'dl', children:[
+ {tag:'dt', htmlString:Clipperz.PM.Strings['loginFormUsernameLabel']},
+ {tag:'dd', children:[
+ {tag:'input', id:this.getId('login_username'), type:'text', size:'30', name:'username'}
+ ]},
+ {tag:'dt', htmlString:Clipperz.PM.Strings['loginFormPassphraseLabel']},
+ {tag:'dd', children:[
+ {tag:'input', id:this.getId('login_passphrase'), type:'password', size:'30', name:'passphrase'}
+ ]}
+ ]},
+ {tag:'div', id:this.getId('login_submit')}
+ ]},
+ {tag:'h4', id:this.getId('message')}
+ ]}
+ ]});
+
+ new Clipperz.PM.Components.Compact.CompactHeader(YAHOO.ext.Element.get('compactHeader'));
+
+ MochiKit.Signal.connect(this.getId('loginForm_form'), 'onsubmit', this, 'stopFormSubmit');
+ new YAHOO.ext.Button(this.getId('login_submit'), {text:Clipperz.PM.Strings['loginFormButtonLabel'], handler:this.doLogin, scope:this, minWidth:0});
+ this.getElement('login_submit').swallowEvent('click', true);
+
+ MochiKit.Signal.connect(this.getId('loginForm_form'), 'onkeydown', this, 'onkeydown');
+
+ new Clipperz.PM.Components.PasswordEntropyDisplay(this.getElement('login_passphrase'));
+ this.getElement('login_username').focus();
+
+ return result;
+ },
+
+ //-----------------------------------------------------
+
+ 'doLogin': function(e) {
+//MochiKit.Logging.logDebug(">>> compact.LoginForm.doLogin");
+ if (this.checkLoginForm()) {
+ this.doLoginWithUsernameAndPassphrase(this.getDom('login_username').value, this.getDom('login_passphrase').value);
+ }
+//MochiKit.Logging.logDebug("<<< compact.LoginForm.doLogin");
+ },
+
+ //.........................................................................
+
+ 'doLoginWithUsernameAndPassphrase': function(anUsername, aPassphrase) {
+ var deferredResult;
+ var user;
+
+//MochiKit.Logging.logDebug(">>> compact.LoginForm.doLoginWithUsernameAndPassphrase");
+ user = new Clipperz.PM.DataModel.User({username:anUsername, passphrase:aPassphrase});
+
+ deferredResult = new MochiKit.Async.Deferred();
+ deferredResult.addCallback(MochiKit.Base.method(user, 'connect'));
+ deferredResult.addCallback(MochiKit.Base.method(user, 'loadPreferences'));
+ deferredResult.addCallback(MochiKit.Base.method(user, 'loadRecords'));
+ deferredResult.addCallback(MochiKit.Base.method(user, 'loadDirectLogins'));
+ deferredResult.addErrback(MochiKit.Base.bind(function() {
+ this.getElement('loginForm_form').setVisibilityMode(YAHOO.ext.Element.DISPLAY).show();
+ this.getElement('message').update(Clipperz.PM.Strings['loginMessagePanelFailureText']);
+ this.getDom('login_passphrase').value = "";
+ this.getElement('login_passphrase').focus();
+ }, this))
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("compact.LoginForm.doLogin - 6: " + res); return res;});
+ deferredResult.callback("token");
+//MochiKit.Logging.logDebug("<<< compact.LoginForm.doLoginWithUsernameAndPassphrase");
+
+ return deferredResult;
+ },
+
+ //.........................................................................
+
+ 'checkLoginForm': function() {
+ var result;
+ var username
+ var passphrase;
+
+//MochiKit.Logging.logDebug(">>> checkLoginForm");
+ username = this.getDom('login_username').value;
+ passphrase = this.getDom('login_passphrase').value;
+
+ if ((username != "") && (passphrase != "")) {
+ result = true;
+ } else {
+ if (username == "") {
+ this.getElement('login_username').focus();
+ } else if (passphrase == "") {
+ this.getElement('login_passphrase').focus();
+ }
+
+ result = false;
+ }
+//MochiKit.Logging.logDebug("<<< checkLoginForm - " + result);
+
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'stopFormSubmit': function(anEvent) {
+ anEvent.stop();
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'onkeydown': function(anEvent) {
+//MochiKit.Logging.logDebug(">>> onkeydown - " + anEvent.src().id);
+ if (anEvent.key().code == 13) {
+ this.doLogin();
+ anEvent.stop();
+ }
+ },
+
+ //-----------------------------------------------------
+
+ 'userNotificationHandler': function(anEvent) {
+//MochiKit.Logging.logDebug(">>> compact.LoginForm.userNotificationHandler");
+//MochiKit.Logging.logDebug("userNotificationHandler - event: " + anEvent.event());
+ this.getElement('loginForm_form').setVisibilityMode(YAHOO.ext.Element.DISPLAY).hide();
+ if (this.getDom('message') != null) {
+ this.getElement('message').update(Clipperz.PM.Strings.messagePanelConfigurations[anEvent.parameters()]()['text']);
+ }
+//MochiKit.Logging.logDebug("<<< compact.LoginForm.userNotificationHandler");
+ },
+
+ //-----------------------------------------------------
+ __syntaxFix__: '__syntaxFix__'
+});
+
+
diff --git a/frontend/beta/js/Clipperz/PM/Components/Import/CSVImport/CSVImportColumns.js b/frontend/beta/js/Clipperz/PM/Components/Import/CSVImport/CSVImportColumns.js
new file mode 100644
index 0000000..18b36da
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Components/Import/CSVImport/CSVImportColumns.js
@@ -0,0 +1,174 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
+if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
+if (typeof(Clipperz.PM.Components) == 'undefined') { Clipperz.PM.Components = {}; }
+if (typeof(Clipperz.PM.Components.Import) == 'undefined') { Clipperz.PM.Components.Import = {}; }
+if (typeof(Clipperz.PM.Components.Import.CSVImport) == 'undefined') { Clipperz.PM.Components.Import.CSVImport = {}; }
+
+//#############################################################################
+
+Clipperz.PM.Components.Import.CSVImport.CSVImportColumns = function(anElement, args) {
+ args = args || {};
+
+ Clipperz.PM.Components.Import.CSVImport.CSVImportColumns.superclass.constructor.call(this, anElement, args);
+ this._mainComponent = args.mainComponent;
+
+ return this;
+}
+
+//=============================================================================
+
+YAHOO.extendX(Clipperz.PM.Components.Import.CSVImport.CSVImportColumns, Clipperz.PM.Components.BaseComponent, {
+
+ 'toString': function() {
+ return "Clipperz.PM.Components.Import.CSVImport.CSVImportColumns component";
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'mainComponent': function() {
+ return this._mainComponent;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'render': function() {
+ var i,c;
+ var columnSelectorCheckboxCells;
+ var checkboxes;
+ var data;
+
+//MochiKit.Logging.logDebug(">>> CSVImportColumns.render");
+ Clipperz.NotificationCenter.unregister(this);
+ MochiKit.Signal.disconnectAllTo(this);
+
+ this.element().update("");
+
+ data = this.mainComponent().parsedValues();
+ columnSelectorCheckboxCells = [];
+
+ c = data[0].length;
+ for (i=0; i<c; i++) {
+ columnSelectorCheckboxCells.push({tag:'th', valign:'top', cls:(this.mainComponent().isColumnSelected(i) ? 'selectedColumn': 'skippedColumn'), children:[
+ {tag:'input', type:'checkbox', id:this.getId('columnCheckbox_' + i), value:i}
+ ]})
+ }
+
+ this.domHelper().append(this.element(), {tag:'div', children:[
+ {tag:'div', cls:'importStepDescription', htmlString:Clipperz.PM.Strings['CSV_ImportWizard_Columns']},
+ {tag:'div', id:this.getId('dataDiv'), cls:'csvImportPreview', children:[
+ {tag:'table', id:this.getId('previewDada'), cls:'csvImportPreview columns', cellspacing:'0', children:[
+ {tag:'thead', id:this.getId('previewData_thead'), children:[
+ {tag:'tr', children:columnSelectorCheckboxCells}
+ ]},
+ {tag:'tbody', id:this.getId('previewData_tbody'), children:[]}
+ ]}
+ ]}
+ ]});
+
+ c = data[0].length;
+ for (i=0; i<c; i++) {
+ if (this.mainComponent().isColumnSelected(i)) {
+ this.getDom('columnCheckbox_' + i).checked = true;
+ }
+ }
+
+ this.renderData(this.getElement('previewData_tbody'), data);
+
+ checkboxes = MochiKit.DOM.getElementsByTagAndClassName('input', null, this.getDom('previewData_thead'));
+ c = checkboxes.length;
+ for (i=0; i<c; i++) {
+ MochiKit.Signal.connect(checkboxes[i], 'onclick', this, 'renderDataHandler');
+ }
+//MochiKit.Logging.logDebug("<<< CSVImportColumns.render");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'renderData': function(anElement, someData) {
+ var config;
+ var i,c;
+
+//MochiKit.Logging.logDebug(">>> CSVImportColumns.renderData");
+// anElement.update("");
+ MochiKit.DOM.replaceChildNodes(anElement.dom);
+
+ config = MochiKit.Base.map(MochiKit.Base.bind(function(aRowData) {
+ var result;
+ var i,c;
+
+ result = {tag:'tr', children:[]};
+ c = aRowData.length;
+ for (i=0; i<c; i++) {
+ var field;
+
+ field = aRowData[i];
+ result.children.push({tag:'td', valign:'top', cls:(this.mainComponent().isColumnSelected(i) ? 'selectedColumn': 'skippedColumn'), html:(MochiKit.Base.isNotEmpty(field) ? field.replace(/\n/g, '<br>') : '&nbsp;')});
+ }
+
+ return result;
+ }, this), someData);
+
+ MochiKit.Base.map(function(aRowConfig) {Clipperz.YUI.DomHelper.append(anElement, aRowConfig);}, config);
+
+ Clipperz.Style.applyZebraStylesToTable(this.getId('previewDada'));
+//MochiKit.Logging.logDebug("<<< CSVImportColumns.renderData");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'renderDataHandler': function(anEvent) {
+ var thElement;
+
+ thElement = YAHOO.ext.Element.get(anEvent.src().parentNode);
+
+ if (anEvent.src().checked == true) {
+ this.mainComponent().skippedColumns().remove(anEvent.src().value);
+ thElement.addClass('selectedColumn');
+ thElement.removeClass('skippedColumn');
+ } else {
+ this.mainComponent().skippedColumns().add(anEvent.src().value);
+ thElement.removeClass('selectedColumn');
+ thElement.addClass('skippedColumn');
+ }
+
+ if (this.mainComponent().skippedColumns().allItems().length == this.mainComponent().parsedValues()[0].length) {
+ this.mainComponent().nextButton().disable();
+ } else {
+ this.mainComponent().nextButton().enable();
+ }
+
+ this.renderData(this.getElement('previewData_tbody'), this.mainComponent().parsedValues());
+ },
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+});
+
diff --git a/frontend/beta/js/Clipperz/PM/Components/Import/CSVImport/CSVImportFields.js b/frontend/beta/js/Clipperz/PM/Components/Import/CSVImport/CSVImportFields.js
new file mode 100644
index 0000000..a368747
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Components/Import/CSVImport/CSVImportFields.js
@@ -0,0 +1,247 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
+if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
+if (typeof(Clipperz.PM.Components) == 'undefined') { Clipperz.PM.Components = {}; }
+if (typeof(Clipperz.PM.Components.Import) == 'undefined') { Clipperz.PM.Components.Import = {}; }
+if (typeof(Clipperz.PM.Components.Import.CSVImport) == 'undefined') { Clipperz.PM.Components.Import.CSVImport = {}; }
+
+//#############################################################################
+
+Clipperz.PM.Components.Import.CSVImport.CSVImportFields = function(anElement, args) {
+ args = args || {};
+
+ Clipperz.PM.Components.Import.CSVImport.CSVImportFields.superclass.constructor.call(this, anElement, args);
+ this._mainComponent = args.mainComponent;
+
+ return this;
+}
+
+//=============================================================================
+
+YAHOO.extendX(Clipperz.PM.Components.Import.CSVImport.CSVImportFields, Clipperz.PM.Components.BaseComponent, {
+
+ 'toString': function() {
+ return "Clipperz.PM.Components.Import.CSVImport.CSVImportFields component";
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'mainComponent': function() {
+ return this._mainComponent;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'render': function() {
+ var fieldsHeaderCells;
+ var titleColumnIndex;
+ var notesColumnIndex;
+ var i,c;
+
+ Clipperz.NotificationCenter.unregister(this);
+ MochiKit.Signal.disconnectAllTo(this);
+
+ this.element().update("");
+
+ titleColumnIndex = this.mainComponent().titleColumnIndex()
+ notesColumnIndex = this.mainComponent().notesColumnIndex()
+
+ fieldsHeaderCells = [];
+ fieldsHeaderCells.push({tag:'td', valign:'top', cls:'title', html:this.mainComponent().labelForColumn(titleColumnIndex)});
+
+ c = this.mainComponent().parsedValues()[0].length;
+ for (i=0; i<c; i++) {
+ if ((i != titleColumnIndex) && (i != notesColumnIndex) && (this.mainComponent().isColumnSelected(i))) {
+ var trimmedLabel;
+
+ trimmedLabel = Clipperz.Base.trim(this.mainComponent().labelForColumn(i));
+ fieldsHeaderCells.push({tag:'td', valign:'top', id:this.getId('fieldHeaderTD_' + i), cls:((trimmedLabel == "") ? 'missingLabelWarning' : (this.isColumnSetup(i) ? 'configuredColumn': 'unconfiguredColumn')), children:[
+ {tag:'span', html:((trimmedLabel == "") ? Clipperz.PM.Strings['CSV_ImportWizard_Fields_MissingLabelWarning'] : trimmedLabel)/*, cls:((trimmedLabel == "") ? 'missingLabelWarning' : '')*/},
+ {tag:'select', id:this.getId('select_' + i), name:i, children:[
+ {tag:'option', value:'UNDEFINED', html:"select data type", cls:'disabledOption'},
+ {tag:'option', value:'TXT', htmlString:Clipperz.PM.Strings['recordFieldTypologies']['TXT']['shortDescription']},
+ {tag:'option', value:'PWD', htmlString:Clipperz.PM.Strings['recordFieldTypologies']['PWD']['shortDescription']},
+ {tag:'option', value:'URL', htmlString:Clipperz.PM.Strings['recordFieldTypologies']['URL']['shortDescription']},
+ {tag:'option', value:'DATE', htmlString:Clipperz.PM.Strings['recordFieldTypologies']['DATE']['shortDescription']},
+ {tag:'option', value:'ADDR', htmlString:Clipperz.PM.Strings['recordFieldTypologies']['ADDR']['shortDescription']}
+ ]}
+ ]})
+ }
+ }
+
+ if (notesColumnIndex != -1) {
+ fieldsHeaderCells.push({tag:'td', valign:'top', cls:'notes', html:this.mainComponent().labelForColumn(notesColumnIndex)});
+ }
+
+ this.domHelper().append(this.element(), {tag:'div', children:[
+ {tag:'div', cls:'importStepDescription', htmlString:Clipperz.PM.Strings['CSV_ImportWizard_Fields']},
+ {tag:'div', id:this.getId('dataDiv'), children:[
+ {tag:'div', children:[
+ ]},
+ {tag:'div', cls:'csvImportPreview', children:[
+ {tag:'table', id:this.getId('previewDada'), cls:'csvImportPreview', cellspacing:'0', children:[
+ {tag:'thead', id:this.getId('previewData_thead'), children:[
+ {tag:'tr', cls:'CSV_previewData_header', children:fieldsHeaderCells}
+ ]},
+ {tag:'tbody', id:this.getId('previewData_tbody'), children:[]}
+ ]}
+ ]}
+ ]}
+ ]});
+
+ for (i=0; i<c; i++) {
+ if ((i != titleColumnIndex) && (i != notesColumnIndex) && (this.mainComponent().isColumnSelected(i))) {
+ Clipperz.DOM.selectOptionMatchingValue(this.getDom('select_' + i), this.mainComponent().typeForColumn(i));
+ MochiKit.Signal.connect(this.getDom('select_' + i), 'onchange', this, 'renderDataRowsHandler');
+ }
+ }
+
+ this.renderDataRows(this.getElement('previewData_tbody'));
+// Clipperz.NotificationCenter.register(null, 'updatedCSVImportColumnHeader', this, 'renderDataRowsHandler');
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'isColumnSetup': function(aColumnIndex) {
+ return ((Clipperz.Base.trim(this.mainComponent().labelForColumn(aColumnIndex)) != "") && (this.mainComponent().typeForColumn(aColumnIndex) != 'UNDEFINED'));
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'renderDataRowsHandler': function(anEvent) {
+ var columnIndex;
+ var tdElement;
+
+//MochiKit.Logging.logDebug(">>> renderDataRowsHandler")
+ columnIndex = anEvent.src().name;
+ this.mainComponent().setTypeForColumn(anEvent.src().value, columnIndex);
+
+ tdElement = this.getElement('fieldHeaderTD_' + columnIndex);
+
+ if (this.isColumnSetup(columnIndex)) {
+ tdElement.removeClass('unconfiguredColumn');
+ tdElement.addClass('configuredColumn');
+ } else {
+ tdElement.addClass('unconfiguredColumn');
+ tdElement.removeClass('configuredColumn');
+ }
+
+ this.renderDataRows(this.getElement('previewData_tbody'));
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'renderDataRows': function(anElement) {
+ var titleColumnIndex;
+ var notesColumnIndex;
+ var data
+ var i,c;
+
+//MochiKit.Logging.logDebug("#### >> renderDataRows");
+// anElement.update("");
+ MochiKit.DOM.replaceChildNodes(anElement.dom);
+
+ if (this.mainComponent().isFirstRowHeader()) {
+ data = this.mainComponent().parsedValues().slice(1);
+ } else {
+ data = this.mainComponent().parsedValues();
+ }
+
+
+ titleColumnIndex = this.mainComponent().titleColumnIndex();
+ notesColumnIndex = this.mainComponent().notesColumnIndex();
+
+ c = data.length;
+ for (i=0; i<c; i++) {
+ var rowData;
+ var rowConfig;
+ var ii, cc;
+
+ rowData = data[i];
+
+ rowConfig = {tag:'tr', children:[
+ {tag:'td', valign:'top', cls:'title', html:(MochiKit.Base.isNotEmpty(rowData[titleColumnIndex]) ? rowData[titleColumnIndex].replace(/\n/g, '<br>') : '&nbsp;')}
+ ]};
+
+ cc = rowData.length;
+ for (ii=0; ii<cc; ii++) {
+// if ((ii != titleColumnIndex) && (ii != notesColumnIndex)) {
+ if ((ii != titleColumnIndex) && (ii != notesColumnIndex) && (this.mainComponent().isColumnSelected(ii))) {
+ rowConfig.children.push({
+ tag:'td',
+ valign:'top',
+ cls:(this.isColumnSetup(ii) ? 'configuredColumn' : 'unconfiguredColumn'),
+ html:(MochiKit.Base.isNotEmpty(rowData[ii]) ? rowData[ii].replace(/\n/g, '<br>') : '&nbsp;')
+ });
+ }
+ }
+ if (notesColumnIndex != -1) {
+ rowConfig.children.push({tag:'td', valign:'top', cls:'notes', html:(MochiKit.Base.isNotEmpty(rowData[notesColumnIndex]) ? rowData[notesColumnIndex].replace(/\n/g, '<br>') : '&nbsp;')});
+ }
+
+ this.domHelper().append(anElement, rowConfig);
+ }
+
+ Clipperz.Style.applyZebraStylesToTable(this.getId('previewDada'));
+
+ this.checkWetherToEnableNextButton();
+//MochiKit.Logging.logDebug("#### << renderDataRows");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'checkWetherToEnableNextButton': function() {
+ var result;
+ var titleColumnIndex;
+ var notesColumnIndex;
+ var i,c;
+
+ titleColumnIndex = this.mainComponent().titleColumnIndex()
+ notesColumnIndex = this.mainComponent().notesColumnIndex()
+
+ result = true;
+ c = this.mainComponent().parsedValues()[0].length;
+ for (i=0; i<c; i++) {
+ if ((i != titleColumnIndex) && (i != notesColumnIndex) && (this.mainComponent().isColumnSelected(i))) {
+ result = result && this.isColumnSetup(i);
+ }
+ }
+
+ if (result) {
+ this.mainComponent().nextButton().enable();
+ } else {
+ this.mainComponent().nextButton().disable();
+ }
+ },
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+});
+
diff --git a/frontend/beta/js/Clipperz/PM/Components/Import/CSVImport/CSVImportHeader.js b/frontend/beta/js/Clipperz/PM/Components/Import/CSVImport/CSVImportHeader.js
new file mode 100644
index 0000000..ebd243a
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Components/Import/CSVImport/CSVImportHeader.js
@@ -0,0 +1,240 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
+if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
+if (typeof(Clipperz.PM.Components) == 'undefined') { Clipperz.PM.Components = {}; }
+if (typeof(Clipperz.PM.Components.Import) == 'undefined') { Clipperz.PM.Components.Import = {}; }
+if (typeof(Clipperz.PM.Components.Import.CSVImport) == 'undefined') { Clipperz.PM.Components.Import.CSVImport = {}; }
+
+//#############################################################################
+
+Clipperz.PM.Components.Import.CSVImport.CSVImportHeader = function(anElement, args) {
+ args = args || {};
+
+ Clipperz.PM.Components.Import.CSVImport.CSVImportHeader.superclass.constructor.call(this, anElement, args);
+ this._mainComponent = args.mainComponent;
+
+ this._pendingDeferredLabelFieldHandlerEvents = 0;
+
+ return this;
+}
+
+//=============================================================================
+
+YAHOO.extendX(Clipperz.PM.Components.Import.CSVImport.CSVImportHeader, Clipperz.PM.Components.BaseComponent, {
+
+ 'toString': function() {
+ return "Clipperz.PM.Components.Import.CSVImport.CSVImportHeader component";
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'mainComponent': function() {
+ return this._mainComponent;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'render': function() {
+ var thConfigs;
+ var i,c;
+
+//MochiKit.Logging.logDebug(">>> CSVImportHeader.render");
+ Clipperz.NotificationCenter.unregister(this);
+ MochiKit.Signal.disconnectAllTo(this);
+
+ thConfigs = [];
+ c = this.mainComponent().parsedValues()[0].length;
+ for (i=0; i<c; i++) {
+ if (this.mainComponent().isColumnSelected(i)) {
+// thConfigs.push({tag:'th', children:[{tag:'input', type:'text', id:this.getId('headerTextField_' + i), value:this.mainComponent().labelForColumn(i)}]});
+ thConfigs.push({tag:'th', children:[{tag:'input', type:'text', id:this.getId('headerTextField_' + i), value:""}]});
+ }
+ }
+
+ this.element().update("");
+ this.domHelper().append(this.element(), {tag:'div', children:[
+ {tag:'div', cls:'importStepDescription', htmlString:Clipperz.PM.Strings['CSV_ImportWizard_Header']},
+ {tag:'div', cls:'importStepParameters', children:[
+ {tag:'input', type:'checkbox', name:'isFistRowHeader', id:this.getId('isFirstRowHeader_checkbox')},
+ {tag:'span', id:this.getId('isFirstRowHeader_span'), cls:'clickableSpan', htmlString:Clipperz.PM.Strings['CSV_ImportWizard_Header_Settings_firstRowHeaderLabel']}
+ ]},
+ {tag:'div', id:this.getId('dataDiv'), children:[
+ {tag:'div', cls:'csvImportPreview', children:[
+ {tag:'table', id:this.getId('previewDada'), cls:'csvImportPreview header', cellspacing:'0', children:[
+ {tag:'thead', children:[{tag:'tr', children:thConfigs}]},
+ {tag:'tbody', id:this.getId('previewData_tbody')}
+ ]}
+ ]}
+ ]}
+ ]});
+
+ for (i=0; i<c; i++) {
+ if (this.mainComponent().isColumnSelected(i)) {
+ this.getElement('headerTextField_' + i).dom.value = this.mainComponent().labelForColumn(i);
+ }
+ }
+
+ this.renderData(this.getElement('previewData_tbody'), this.mainComponent().parsedValues());
+
+ if (this.mainComponent().isFirstRowHeader()) {
+ this.getDom('isFirstRowHeader_checkbox').click();
+ }
+
+ c = this.mainComponent().parsedValues()[0].length;
+ for (i=0; i<c; i++) {
+ if (this.mainComponent().isColumnSelected(i)) {
+ MochiKit.Signal.connect(this.getDom('headerTextField_' + i), 'onchange', MochiKit.Base.partial(MochiKit.Base.method(this, 'labelFieldHandler'), i));
+ MochiKit.Signal.connect(this.getDom('headerTextField_' + i), 'onkeypress', MochiKit.Base.partial(MochiKit.Base.method(this, 'deferredLabelFieldHandler'), i));
+ }
+ }
+
+ MochiKit.Signal.connect(this.getDom('isFirstRowHeader_checkbox'), 'onclick', this, 'toggleFirstRowHeaderCheckboxHandler');
+ if (Clipperz_IEisBroken != true) {
+ MochiKit.Signal.connect(this.getDom('isFirstRowHeader_span'), 'onclick', this.getDom('isFirstRowHeader_checkbox'), 'click');
+ }
+//MochiKit.Logging.logDebug("<<< CSVImportHeader.render");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'renderData': function(anElement, someData) {
+ var trConfigs;
+ var data;
+ var i,c;
+
+// anElement.update("");
+ MochiKit.DOM.replaceChildNodes(anElement.dom);
+
+ if (this.mainComponent().isFirstRowHeader()) {
+ data = someData.slice(1);
+ } else {
+ data = someData;
+ }
+
+ trConfigs = MochiKit.Base.map(MochiKit.Base.bind(function(aRowData) {
+ var result;
+ var i,c;
+
+ result = {tag:'tr', children:[]};
+ c = aRowData.length;
+ for (i=0; i<c; i++) {
+ if (this.mainComponent().isColumnSelected(i)) {
+ result.children.push({tag:'td', valign:'top', html:(MochiKit.Base.isNotEmpty(aRowData[i]) ? aRowData[i].replace(/\n/g, '<br>') : '&nbsp;')});
+ }
+ }
+
+ return result;
+ }, this), data);
+
+ MochiKit.Base.map(function(aRowConfig) {Clipperz.YUI.DomHelper.append(anElement, aRowConfig);}, trConfigs);
+
+ Clipperz.Style.applyZebraStylesToTable(this.getId('previewDada'));
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'toggleFirstRowHeaderCheckboxHandler': function() {
+ var firstRowData;
+ var i,c;
+
+//MochiKit.Logging.logDebug(">>> toggleFirstRowHeaderCheckboxHandler");
+ this.mainComponent().setIsFirstRowHeader(this.getDom('isFirstRowHeader_checkbox').checked);
+
+ firstRowData = this.mainComponent().parsedValues()[0];
+
+ c = firstRowData.length;
+ for (i=0; i<c; i++) {
+ if (this.mainComponent().isColumnSelected(i)) {
+ var label;
+
+ if (this.mainComponent().isFirstRowHeader()) {
+ label = firstRowData[i];
+ } else {
+ label = null;
+ }
+
+ this.mainComponent().setLabelForColumn(label, i);
+ }
+ };
+
+ this.updateInputFieldValues();
+ this.renderData(this.getElement('previewData_tbody'), this.mainComponent().parsedValues());
+//MochiKit.Logging.logDebug("<<< toggleFirstRowHeaderCheckboxHandler");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'updateInputFieldValues': function() {
+ var i,c;
+
+//MochiKit.Logging.logDebug(">>> updateInputFieldValues");
+ c = this.mainComponent().parsedValues()[0].length;
+ for (i=0; i<c; i++) {
+ if (this.mainComponent().isColumnSelected(i)) {
+ this.getDom('headerTextField_' + i).value = this.mainComponent().labelForColumn(i);
+ }
+ }
+//console.log('[1] fieldSettings', fieldSettings);
+//MochiKit.Logging.logDebug("<<< updateInputFieldValues");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'labelFieldHandler': function(aColumnIndex, anEvent) {
+ var inputField;
+
+//MochiKit.Logging.logDebug(">>> labelFieldHandler");
+ inputField = anEvent.src();
+
+ this.mainComponent().setLabelForColumn(inputField.value, aColumnIndex);
+//MochiKit.Logging.logDebug("##### [" + anEvent.src().id + "] -> label[" + aColumnIndex + "]: '" + inputField.value + "'");
+//MochiKit.Logging.logDebug("<<< labelFieldHandler");
+ },
+
+ 'deferredLabelFieldHandler': function(aColumnIndex, anEvent) {
+//MochiKit.Logging.logDebug(">>> deferredLabelFieldHandler");
+ this._pendingDeferredLabelFieldHandlerEvents ++;
+ MochiKit.Async.callLater(1, MochiKit.Base.partial(MochiKit.Base.method(this, 'deferredLabelFieldHandlerCatcher'), aColumnIndex, anEvent));
+//MochiKit.Logging.logDebug("<<< deferredLabelFieldHandler");
+ },
+
+ 'deferredLabelFieldHandlerCatcher': function(aColumnIndex, anEvent) {
+//MochiKit.Logging.logDebug(">>> deferredLabelFieldHandlerCatcher");
+ this._pendingDeferredLabelFieldHandlerEvents --;
+ if (this._pendingDeferredLabelFieldHandlerEvents == 0) {
+ this.labelFieldHandler(aColumnIndex, anEvent);
+ }
+//MochiKit.Logging.logDebug("<<< deferredLabelFieldHandlerCatcher");
+ },
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+});
+
diff --git a/frontend/beta/js/Clipperz/PM/Components/Import/CSVImport/CSVImportNotes.js b/frontend/beta/js/Clipperz/PM/Components/Import/CSVImport/CSVImportNotes.js
new file mode 100644
index 0000000..a53c531
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Components/Import/CSVImport/CSVImportNotes.js
@@ -0,0 +1,212 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
+if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
+if (typeof(Clipperz.PM.Components) == 'undefined') { Clipperz.PM.Components = {}; }
+if (typeof(Clipperz.PM.Components.Import) == 'undefined') { Clipperz.PM.Components.Import = {}; }
+if (typeof(Clipperz.PM.Components.Import.CSVImport) == 'undefined') { Clipperz.PM.Components.Import.CSVImport = {}; }
+
+//#############################################################################
+
+Clipperz.PM.Components.Import.CSVImport.CSVImportNotes = function(anElement, args) {
+ args = args || {};
+
+ Clipperz.PM.Components.Import.CSVImport.CSVImportNotes.superclass.constructor.call(this, anElement, args);
+ this._mainComponent = args.mainComponent;
+
+ return this;
+}
+
+//=============================================================================
+
+YAHOO.extendX(Clipperz.PM.Components.Import.CSVImport.CSVImportNotes, Clipperz.PM.Components.BaseComponent, {
+
+ 'toString': function() {
+ return "Clipperz.PM.Components.Import.CSVImport.CSVImportNotes component";
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'mainComponent': function() {
+ return this._mainComponent;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'render': function() {
+ var notesSelectorCheckboxCells;
+ var totalNumberOfColumns;
+ var titleColumnIndex;
+ var notesColumnIndex;
+ var i,c;
+
+ Clipperz.NotificationCenter.unregister(this);
+ MochiKit.Signal.disconnectAllTo(this);
+
+ this.element().update("");
+
+ titleColumnIndex = this.mainComponent().titleColumnIndex()
+ notesColumnIndex = this.mainComponent().notesColumnIndex()
+
+ totalNumberOfColumns = this.mainComponent().parsedValues()[0].length;
+
+ notesSelectorCheckboxCells = [{tag:'th', cls:'title', html:this.mainComponent().labelForColumn(titleColumnIndex)}];
+ c = totalNumberOfColumns;
+ for (i=0; i<c; i++) {
+ if ((i != titleColumnIndex) && (this.mainComponent().isColumnSelected(i))) {
+ notesSelectorCheckboxCells.push({tag:'th', id:this.getId('th_' + i), valign:'top', children:[
+ {tag:'input', type:'radio', id:this.getId('radio_' + i), name:'CSVImportNotesColumn', value:i},
+ {tag:'span', cls:'clickableSpan', id:this.getId('columnLabel_' + i), html:this.mainComponent().labelForColumn(i)}
+ ]})
+ }
+ }
+
+ this.domHelper().append(this.element(), {tag:'div', children:[
+ {tag:'div', cls:'importStepDescription', htmlString:Clipperz.PM.Strings['CSV_ImportWizard_Notes']},
+ {tag:'div', id:this.getId('dataDiv'), children:[
+ {tag:'div', cls:'importStepParameters', children:[
+ {tag:'input', id:this.getId('doNotSetNotes_radio'), type:'radio', name:'CSVImportNotesColumn', value:-1},
+ {tag:'span', id:this.getId('doNotSetNotes_span'), cls:'clickableSpan', htmlString:Clipperz.PM.Strings['CSV_ImportWizard_Notes_Settings_noSelectionLabel']}
+ ]},
+ {tag:'div', cls:'csvImportPreview', children:[
+ {tag:'table', id:this.getId('previewDada'), cls:'csvImportPreview', cellspacing:'0', children:[
+ {tag:'thead', id:this.getId('previewData_thead'), children:[
+ {tag:'tr', children:notesSelectorCheckboxCells}
+ ]},
+ {tag:'tbody', id:this.getId('previewData_tbody'), children:[]}
+ ]}
+ ]}
+ ]}
+ ]});
+
+ this.renderData(this.getElement('previewData_tbody'), this.mainComponent().parsedValues());
+
+ if ((notesColumnIndex >= totalNumberOfColumns) || (notesColumnIndex == titleColumnIndex) || !(this.mainComponent().isColumnSelected(notesColumnIndex))) {
+ this.mainComponent().setNotesColumnIndex(-1);
+ notesColumnIndex = -1;
+ }
+
+ c = totalNumberOfColumns;
+ for (i=0; i<c; i++) {
+ if ((i != titleColumnIndex) && (this.mainComponent().isColumnSelected(i))) {
+ MochiKit.Signal.connect(this.getDom('radio_' + i), 'onclick', this, 'renderDataHandler');
+ if (Clipperz_IEisBroken != true) {
+ MochiKit.Signal.connect(this.getDom('columnLabel_' + i), 'onclick', this.getDom('radio_' + i), 'click');
+ }
+ }
+ }
+
+ MochiKit.Signal.connect(this.getDom('doNotSetNotes_radio'), 'onclick', this, 'renderDataHandler');
+ if (Clipperz_IEisBroken != true) {
+ MochiKit.Signal.connect(this.getDom('doNotSetNotes_span'), 'onclick', this.getDom('doNotSetNotes_radio'), 'click');
+ }
+
+ if (notesColumnIndex == -1) {
+ this.getDom('doNotSetNotes_radio').click();
+ } else {
+ this.getDom('radio_' + notesColumnIndex).click();
+ }
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'renderData': function(anElement, someData) {
+ var data;
+ var config;
+ var titleColumnIndex;
+ var notesColumnIndex;
+ var i,c;
+
+// anElement.update("");
+ MochiKit.DOM.replaceChildNodes(anElement.dom);
+
+ titleColumnIndex = this.mainComponent().titleColumnIndex();
+ notesColumnIndex = this.mainComponent().notesColumnIndex();
+
+ if (this.mainComponent().isFirstRowHeader()) {
+ data = someData.slice(1);
+ } else {
+ data = someData;
+ }
+
+
+// config = [{tag:'tr', cls:'CSV_previewData_header', children:[{tag:'td', valign:'top', html:header[titleColumnIndex], cls:'title'}]}];
+// c = header.length;
+// for (i=0; i<c; i++) {
+// if (i != titleColumnIndex) {
+// config[0].children.push({tag:'td', valign:'top', html:header[i], cls:((notesColumnIndex == i) ? 'notesColumn': '')})
+// }
+// }
+
+ config = MochiKit.Base.map(MochiKit.Base.bind(function(aTitleColumnIndex, aRowData) {
+ var result;
+ var i,c;
+
+ result = {tag:'tr', children:[{tag:'td', valign:'top', cls:'title', html:(MochiKit.Base.isNotEmpty(aRowData[aTitleColumnIndex]) ? aRowData[aTitleColumnIndex].replace(/\n/g, '<br>') : '&nbsp;')}]};
+ c = aRowData.length;
+ for (i=0; i<c; i++) {
+ if ((i != titleColumnIndex) && (this.mainComponent().isColumnSelected(i))) {
+ result.children.push({tag:'td', valign:'top', cls:((notesColumnIndex == i) ? 'notesColumn': ''), html:(MochiKit.Base.isNotEmpty(aRowData[i]) ? aRowData[i].replace(/\n/g, '<br>') : '&nbsp;')});
+ }
+ }
+
+ return result;
+ }, this, titleColumnIndex), data);
+
+ MochiKit.Base.map(function(aRowConfig) {Clipperz.YUI.DomHelper.append(anElement, aRowConfig);}, config);
+
+ Clipperz.Style.applyZebraStylesToTable(this.getId('previewDada'));
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'renderDataHandler': function(anEvent) {
+ var titleColumnIndex;
+ var i,c;
+
+ this.mainComponent().setNotesColumnIndex(anEvent.src().value);
+ titleColumnIndex = this.mainComponent().titleColumnIndex();
+
+ c = this.mainComponent().parsedValues()[0].length;
+ for (i=0; i<c; i++) {
+ if ((i != titleColumnIndex) && (this.mainComponent().isColumnSelected(i))) {
+ this.getElement('th_' + i).removeClass('notesColumn');
+ }
+ }
+ if (anEvent.src().value != -1) {
+ this.getElement('th_' + anEvent.src().value).addClass('notesColumn');
+ }
+
+ this.renderData(this.getElement('previewData_tbody'), this.mainComponent().parsedValues());
+ },
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+});
+
diff --git a/frontend/beta/js/Clipperz/PM/Components/Import/CSVImport/CSVImportTitle.js b/frontend/beta/js/Clipperz/PM/Components/Import/CSVImport/CSVImportTitle.js
new file mode 100644
index 0000000..9162867
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Components/Import/CSVImport/CSVImportTitle.js
@@ -0,0 +1,189 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
+if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
+if (typeof(Clipperz.PM.Components) == 'undefined') { Clipperz.PM.Components = {}; }
+if (typeof(Clipperz.PM.Components.Import) == 'undefined') { Clipperz.PM.Components.Import = {}; }
+if (typeof(Clipperz.PM.Components.Import.CSVImport) == 'undefined') { Clipperz.PM.Components.Import.CSVImport = {}; }
+
+//#############################################################################
+
+Clipperz.PM.Components.Import.CSVImport.CSVImportTitle = function(anElement, args) {
+ args = args || {};
+
+ Clipperz.PM.Components.Import.CSVImport.CSVImportTitle.superclass.constructor.call(this, anElement, args);
+ this._mainComponent = args.mainComponent;
+
+ return this;
+}
+
+//=============================================================================
+
+YAHOO.extendX(Clipperz.PM.Components.Import.CSVImport.CSVImportTitle, Clipperz.PM.Components.BaseComponent, {
+
+ 'toString': function() {
+ return "Clipperz.PM.Components.Import.CSVImport.CSVImportTitle component";
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'mainComponent': function() {
+ return this._mainComponent;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'render': function() {
+ var titleSelectorCheckboxCells;
+ var titleColumnIndex;
+ var i,c;
+
+ Clipperz.NotificationCenter.unregister(this);
+ MochiKit.Signal.disconnectAllTo(this);
+
+ this.element().update("");
+
+ titleColumnIndex = this.mainComponent().titleColumnIndex()
+ titleSelectorCheckboxCells = [];
+ c = this.mainComponent().parsedValues()[0].length;
+ for (i=0; i<c; i++) {
+ if (this.mainComponent().isColumnSelected(i)) {
+ titleSelectorCheckboxCells.push({tag:'th', valign:'top', id:this.getId('th_' + i), children:[
+ {tag:'input', type:'radio', id:this.getId('radio_' + i), name:'CSVImportTitleColumn', value:i},
+ {tag:'span', cls:'clickableSpan', id:this.getId('columnLabel_' + i), html:this.mainComponent().labelForColumn(i)}
+ ]})
+ }
+ }
+
+ if (titleColumnIndex >= titleSelectorCheckboxCells.length) {
+ this.mainComponent().setTitleColumnIndex(-1);
+ }
+
+ this.domHelper().append(this.element(), {tag:'div', children:[
+ {tag:'div', cls:'importStepDescription', htmlString:Clipperz.PM.Strings['CSV_ImportWizard_Title']},
+ {tag:'div', id:this.getId('dataDiv'), cls:'csvImportPreview', children:[
+ {tag:'table', id:this.getId('previewDada'), cls:'csvImportPreview', cellspacing:'0', children:[
+ {tag:'thead', id:this.getId('previewData_thead'), children:[
+ {tag:'tr', children:titleSelectorCheckboxCells}
+ ]},
+ {tag:'tbody', id:this.getId('previewData_tbody'), children:[]}
+ ]}
+ ]}
+ ]});
+
+ this.renderData(this.getElement('previewData_tbody'), this.mainComponent().parsedValues());
+
+ c = this.mainComponent().parsedValues()[0].length;
+ for (i=0; i<c; i++) {
+ if (this.mainComponent().isColumnSelected(i)) {
+ MochiKit.Signal.connect(this.getDom('radio_' + i), 'onclick', this, 'renderDataHandler');
+ if (Clipperz_IEisBroken != true) {
+ MochiKit.Signal.connect(this.getDom('columnLabel_' + i), 'onclick', this.getDom('radio_' + i), 'click');
+ }
+ }
+ }
+
+ if (titleColumnIndex != -1) {
+ this.getDom('radio_' + titleColumnIndex).click();
+ } else {
+ this.mainComponent().nextButton().disable();
+ }
+
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'renderData': function(anElement, someData) {
+ var data;
+ var config;
+ var titleColumnIndex;
+ var i,c;
+
+// anElement.update("");
+ MochiKit.DOM.replaceChildNodes(anElement.dom);
+
+ titleColumnIndex = this.mainComponent().titleColumnIndex()
+
+ if (this.mainComponent().isFirstRowHeader()) {
+ data = someData.slice(1);
+ } else {
+ data = someData;
+ }
+
+ config = MochiKit.Base.map(MochiKit.Base.bind(function(aRowData) {
+ var result;
+ var i,c;
+
+ result = {tag:'tr', children:[]};
+ c = aRowData.length;
+ for (i=0; i<c; i++) {
+ if (this.mainComponent().isColumnSelected(i)) {
+ var field;
+
+ field = aRowData[i];
+ result.children.push({tag:'td', valign:'top', cls:((titleColumnIndex == i) ? 'titleColumn': ''), html:(MochiKit.Base.isNotEmpty(field) ? field.replace(/\n/g, '<br>') : '&nbsp;')});
+ }
+ }
+
+ return result;
+ }, this), data);
+
+ MochiKit.Base.map(function(aRowConfig) {Clipperz.YUI.DomHelper.append(anElement, aRowConfig);}, config);
+
+ Clipperz.Style.applyZebraStylesToTable(this.getId('previewDada'));
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'renderDataHandler': function(anEvent) {
+ var i,c;
+
+ this.mainComponent().setTitleColumnIndex(anEvent.src().value);
+
+ c = this.mainComponent().parsedValues()[0].length;
+ for (i=0; i<c; i++) {
+ if (this.mainComponent().isColumnSelected(i)) {
+ this.getElement('th_' + i).removeClass('titleColumn');
+ }
+ }
+ this.getElement('th_' + anEvent.src().value).addClass('titleColumn');
+
+ if (anEvent.src().value != -1) {
+ this.mainComponent().nextButton().enable();
+ } else {
+ this.mainComponent().nextButton().disable();
+ }
+
+ this.renderData(this.getElement('previewData_tbody'), this.mainComponent().parsedValues());
+ },
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+});
+
diff --git a/frontend/beta/js/Clipperz/PM/Components/Import/CSVImportComponent.js b/frontend/beta/js/Clipperz/PM/Components/Import/CSVImportComponent.js
new file mode 100644
index 0000000..707a3d2
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Components/Import/CSVImportComponent.js
@@ -0,0 +1,548 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
+if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
+if (typeof(Clipperz.PM.Components) == 'undefined') { Clipperz.PM.Components = {}; }
+if (typeof(Clipperz.PM.Components.Import) == 'undefined') { Clipperz.PM.Components.Import = {}; }
+
+//#############################################################################
+
+Clipperz.PM.Components.Import.CSVImportComponent = function(anElement, args) {
+ args = args || {};
+
+ this._steps = this._steps || ['CSV_EDIT', 'CSV_COLUMNS', 'CSV_HEADER', 'CSV_TITLE', 'CSV_NOTES', 'CSV_FIELDS', 'PREVIEW', 'IMPORT'];
+
+ Clipperz.PM.Components.Import.CSVImportComponent.superclass.constructor.call(this, anElement, args);
+
+ this._step1Component = null;
+ this._step2Component = null;
+ this._step3Component = null;
+ this._step4Component = null;
+ this._step5Component = null;
+
+ this._isFirstRowHeader = false;
+ this._titleColumnIndex = -1;
+ this._notesColumnIndex = -1;
+ this._fieldSettings = {};
+ this._skippedColumns = new Clipperz.Set();
+
+ this.render();
+
+ return this;
+}
+
+//=============================================================================
+
+YAHOO.extendX(Clipperz.PM.Components.Import.CSVImportComponent, Clipperz.PM.Components.Import.GenericImportComponent, {
+
+ 'toString': function() {
+ return "Clipperz.PM.Components.Import.CSVImportComponent component";
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'render': function() {
+ this.domHelper().append(this.element(), {tag:'div', cls:'csvImportWizard', children:[
+ {tag:'h3', htmlString:Clipperz.PM.Strings['CSV_ImportWizard_Title']},
+ {tag:'div', cls:'importSteps', id:this.getId('importSteps')},
+ {tag:'div', cls:'importStepBlocks', children:[
+ {tag:'div', cls:'step_0', id:this.getId('step_0'), children:[
+ {tag:'div', children:[
+ {tag:'div', cls:'importOptionsDescription', htmlString:Clipperz.PM.Strings['importOptions_csv_description']},
+ {tag:'div', cls:'importOptionsParameters', children:[
+ {tag:'div', cls:'CSVImportOptionsParameters', children:[
+ {tag:'ul', children:[
+ {tag:'li', children:[
+ {tag:'label', 'for':this.getId('CSV_inputOptions_separator'), html:"separator"},
+ {tag:'select', name:this.getId('CSV_inputOptions_separator'), id:this.getId('CSV_inputOptions_separator'), children:[
+ {tag:'option', name:'comma', value:',', html:"comma (,)", selected:true},
+ {tag:'option', name:'tab', value:'\t', html:"tab"}
+ ]}
+ ]},
+
+ {tag:'li', children:[
+ {tag:'label', 'for':this.getId('CSV_inputOptions_quote'), html:"quote"},
+ {tag:'select', name:this.getId('CSV_inputOptions_quote'), id:this.getId('CSV_inputOptions_quote'), children:[
+ {tag:'option', name:'doubleQuote', value:'\"', html:"double quote (\")", selected:true},
+ {tag:'option', name:'singleQuote', value:'\'', html:"single quote (\')"}
+ ]}
+ ]},
+
+ {tag:'li', children:[
+ {tag:'label', 'for':this.getId('CSV_inputOptions_escape'), html:"escape"},
+ {tag:'select', name:this.getId('CSV_inputOptions_escape'), id:this.getId('CSV_inputOptions_escape'), children:[
+ {tag:'option', name:'doubleQuote', value:'\"', html:"double quote (\")", selected:true},
+ {tag:'option', name:'slash', value:'\/', html:"slash (\/)"},
+ {tag:'option', name:'backslash', value:'\\', html:"backslash (\\)"}
+ ]}
+ ]}
+ ]}
+ ]}
+ ]},
+ this.textAreaConfig()
+ ]}
+ ]},
+ {tag:'div', cls:'step_1', id:this.getId('step_1'), children:[]},
+ {tag:'div', cls:'step_2', id:this.getId('step_2'), children:[]},
+ {tag:'div', cls:'step_3', id:this.getId('step_3'), children:[]},
+ {tag:'div', cls:'step_4', id:this.getId('step_4'), children:[]},
+ {tag:'div', cls:'step_5', id:this.getId('step_5'), children:[]},
+ {tag:'div', cls:'step_6', id:this.getId('step_6'), children:[
+ {tag:'div', children:[
+ {tag:'div', id:this.getId('previewDiv'), html:"preview"}
+ ]}
+ ]},
+ {tag:'div', cls:'step_7', id:this.getId('step_7'), children:[
+ {tag:'div', children:[
+ {tag:'h4', html:"done"}
+ ]}
+ ]}
+ ]},
+ {tag:'div', cls:'importOptionsButtons', children:[
+ {tag:'table', children:[
+ {tag:'tbody', children:[
+ {tag:'tr', children:[
+ {tag:'td', html:'&nbsp;'},
+ {tag:'td', children:[
+ {tag:'div', id:this.getId('backActionButton')}
+ ]},
+ {tag:'td', html:'&nbsp;'},
+ {tag:'td', children:[
+ {tag:'div', id:this.getId('nextActionButton')}
+ ]},
+ {tag:'td', html:'&nbsp;'}
+ ]}
+ ]}
+ ]}
+ ]}
+ ]});
+
+ this.setBackButton(new YAHOO.ext.Button(this.getDom('backActionButton'), {text:"back", handler:this.backAction, scope:this}));
+ this.setNextButton(new YAHOO.ext.Button(this.getDom('nextActionButton'), {text:"next", handler:this.nextAction, scope:this}));
+
+ this.updateSteps();
+
+ this.getElement('step_0').setVisibilityMode(YAHOO.ext.Element.DISPLAY).show()
+ this.getElement('step_1').setVisibilityMode(YAHOO.ext.Element.DISPLAY).hide();
+ this.getElement('step_2').setVisibilityMode(YAHOO.ext.Element.DISPLAY).hide();
+ this.getElement('step_3').setVisibilityMode(YAHOO.ext.Element.DISPLAY).hide();
+ this.getElement('step_4').setVisibilityMode(YAHOO.ext.Element.DISPLAY).hide();
+ this.getElement('step_5').setVisibilityMode(YAHOO.ext.Element.DISPLAY).hide();
+ this.getElement('step_6').setVisibilityMode(YAHOO.ext.Element.DISPLAY).hide();
+ this.getElement('step_7').setVisibilityMode(YAHOO.ext.Element.DISPLAY).hide();
+
+// this.backButton().disable();
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'nextAction': function() {
+ switch (this.currentStep()) {
+ case 0: // -> 1
+ Clipperz.PM.Components.MessageBox.showProgressPanel(
+ MochiKit.Base.method(this, 'deferredParseValues'),
+ MochiKit.Base.method(this, 'handleParseError'),
+ this.getDom('nextActionButton')
+ );
+ break;
+ case 1: // -> 2
+ this.getElement('step_1').hide();
+ this.step2Component().render();
+ this.setCurrentStep(2);
+ this.getElement('step_2').show();
+ break;
+ case 2: // -> 3
+ this.getElement('step_2').hide();
+ this.step3Component().render();
+ this.setCurrentStep(3);
+ this.getElement('step_3').show();
+ break;
+ case 3: // -> 4
+ this.getElement('step_3').hide();
+ this.step4Component().render();
+ this.setCurrentStep(4);
+ this.getElement('step_4').show();
+ break;
+ case 4: // -> 5
+ this.getElement('step_4').hide();
+ this.step5Component().render();
+ this.setCurrentStep(5);
+ this.getElement('step_5').show();
+ break;
+ case 5: // -> 6
+ this.previewValues();
+ break;
+ case 6: // -> 7
+ this.importValues();
+ break;
+ }
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'deferredParseValues': function() {
+ var deferredResult;
+
+ deferredResult = new MochiKit.Async.Deferred();
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("CSVImportComponent.deferredParseValues - 1 " + res.substring(0,50)); return res;});
+ deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', 'parseImportData');
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("CSVImportComponent.deferredParseValues - 2 " + res.substring(0,50)); return res;});
+ deferredResult.addCallback(MochiKit.Base.bind(function(res) {
+ this.startProcessing();
+
+ return res;
+ }, this));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("CSVImportComponent.deferredParseValues - 3 " + res.substring(0,50)); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(this, 'parseCSVValues'));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("CSVImportComponent.deferredParseValues - 4 " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(this, 'setParsedValues'));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("CSVImportComponent.deferredParseValues - 5 " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(this.step1Component(), 'render'));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("CSVImportComponent.deferredParseValues - 6 " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.bind(function(res) {
+ this.processingDone();
+ this.getElement('step_0').hide();
+ this.getElement('step_1').show();
+ this.backButton().enable();
+
+ return res;
+ }, this));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("CSVImportComponent.deferredParseValues - 7 " + res); return res;});
+ deferredResult.callback(this.textAreaContent());
+
+ return deferredResult;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'deferredPreviewValues': function() {
+ var deferredResult;
+
+//MochiKit.Logging.logDebug(">>> CSVImportComponent.deferredPreviewValues");
+ deferredResult = new MochiKit.Async.Deferred();
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("KeePassImportComponent.deferredPreviewValues - 1 " + res); return res;});
+ deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', 'previewImportData');
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("KeePassImportComponent.deferredPreviewValues - 2 " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.bind(function(res) {
+ this.startProcessing();
+
+ return res;
+ }, this));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("KeePassImportComponent.deferredPreviewValues - 3 " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(this, 'processCSVParsedValues'));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("KeePassImportComponent.deferredPreviewValues - 4 " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(this, 'setProcessedValues'));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("KeePassImportComponent.deferredPreviewValues - 5 " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(this, 'previewRecordValues'));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("KeePassImportComponent.deferredPreviewValues - 6 " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.bind(function(res) {
+ this.processingDone();
+ this.getElement('step_5').hide();
+ this.getElement('step_6').show();
+ this.backButton().enable();
+
+ return res;
+ }, this));
+ deferredResult.callback(this.parsedValues());
+//MochiKit.Logging.logDebug("<<< CSVImportComponent.deferredPreviewValues");
+
+ return deferredResult;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'csvProcessor': function() {
+ return new Clipperz.CSVProcessor({
+ quoteChar: this.getDom('CSV_inputOptions_quote').value,
+ escapeChar: this.getDom('CSV_inputOptions_escape').value,
+ separatorChar: this.getDom('CSV_inputOptions_separator').value,
+ binary:true
+ });
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'parseCSVValues': function(someData) {
+ var deferredResult;
+ var csvProcessor;
+
+ csvProcessor = this.csvProcessor();
+ deferredResult = new MochiKit.Async.Deferred();
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("KeePassImportComponent.parseKeePassValues - 1 " + res.substring(0,50)); return res;});
+ deferredResult.addCallback(function(res) {
+ return Clipperz.NotificationCenter.deferredNotification(this, 'updatedProgressState', {steps:(res.length)}, res);
+ })
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("KeePassImportComponent.parseKeePassValues - 2 " + res.substring(0,50)); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(csvProcessor, 'deferredParse'));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("KeePassImportComponent.parseKeePassValues - 3 " + res); return res;});
+ deferredResult.callback(someData);
+
+ return deferredResult;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'processCSVParsedValues': function (someValues) {
+ var deferredResult;
+ var records;
+ var titleColumnIndex;
+ var notesColumnIndex;
+ var i,c;
+
+ deferredResult = new MochiKit.Async.Deferred();
+ records = [];
+
+ titleColumnIndex = this.titleColumnIndex();
+ notesColumnIndex = this.notesColumnIndex();
+
+ deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', {steps:(someValues.length)});
+
+ c = someValues.length;
+ if (this.isFirstRowHeader()) {
+ i = 1;
+ } else {
+ i = 0;
+ }
+
+ for( ; i<c; i++) {
+ deferredResult.addCallback(MochiKit.Async.wait, 0.2);
+ deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', {});
+ deferredResult.addCallback(MochiKit.Base.bind(function(someRecords, someData) {
+ var record;
+ var recordVersion;
+ var ii;
+
+ record = new Clipperz.PM.DataModel.Record({user:this.user()});
+ record.setLabel(someData[titleColumnIndex]);
+ if (notesColumnIndex != -1) {
+ record.setNotes(someData[notesColumnIndex]);
+ }
+ recordVersion = record.currentVersion()
+
+ for (ii in someData) {
+// if ((ii != titleColumnIndex) && (ii != notesColumnIndex) && (typeof(this.fieldSettings()[ii]) != 'undefined')) {
+ if ((ii != titleColumnIndex) && (ii != notesColumnIndex) && (this.isColumnSelected(ii))) {
+ var recordField;
+
+ recordField = new Clipperz.PM.DataModel.RecordField({
+ recordVersion: recordVersion,
+ label: this.labelForColumn(ii),
+ value: someData[ii],
+ type: this.typeForColumn(ii)
+ });
+ recordVersion.addField(recordField);
+ }
+ }
+
+ someRecords.push(record);
+
+ return someRecords;
+ }, this), records, someValues[i]);
+ }
+ deferredResult.addCallback(MochiKit.Async.succeed, records);
+ deferredResult.callback();
+
+ return deferredResult;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'step1Component': function() {
+ if (this._step1Component == null) {
+ this._step1Component = new Clipperz.PM.Components.Import.CSVImport.CSVImportColumns(this.getElement('step_1'), {mainComponent:this});
+ }
+
+ return this._step1Component;
+ },
+
+ 'step2Component': function() {
+ if (this._step2Component == null) {
+ this._step2Component = new Clipperz.PM.Components.Import.CSVImport.CSVImportHeader(this.getElement('step_2'), {mainComponent:this});
+ }
+
+ return this._step2Component;
+ },
+
+ 'step3Component': function() {
+ if (this._step3Component == null) {
+ this._step3Component = new Clipperz.PM.Components.Import.CSVImport.CSVImportTitle(this.getElement('step_3'), {mainComponent:this});
+ }
+
+ return this._step3Component;
+ },
+
+ 'step4Component': function() {
+ if (this._step4Component == null) {
+ this._step4Component = new Clipperz.PM.Components.Import.CSVImport.CSVImportNotes(this.getElement('step_4'), {mainComponent:this});
+ }
+
+ return this._step4Component;
+ },
+
+ 'step5Component': function() {
+ if (this._step5Component == null) {
+ this._step5Component = new Clipperz.PM.Components.Import.CSVImport.CSVImportFields(this.getElement('step_5'), {mainComponent:this});
+ }
+
+ return this._step5Component;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'isFirstRowHeader': function() {
+ return this._isFirstRowHeader;
+ },
+
+ 'setIsFirstRowHeader': function(aValue) {
+ this._isFirstRowHeader = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'titleColumnIndex': function() {
+ return this._titleColumnIndex;
+ },
+
+ 'setTitleColumnIndex': function(aValue) {
+ this._titleColumnIndex = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'notesColumnIndex': function() {
+ return this._notesColumnIndex;
+ },
+
+ 'setNotesColumnIndex': function(aValue) {
+ this._notesColumnIndex = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'fieldSettings': function() {
+ return this._fieldSettings;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'skippedColumns': function() {
+ return this._skippedColumns;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'isColumnSelected': function(aColumnIndex) {
+ return !this.skippedColumns().contains("" + aColumnIndex);
+ },
+
+ //=========================================================================
+
+ 'labelForColumn': function(aColumnIndex) {
+ var result;
+
+ if ((typeof(this.fieldSettings()) != 'undefined') && (typeof(this.fieldSettings()[aColumnIndex]) != 'undefined')) {
+ if (this.isFirstRowHeader()) {
+ result = this.fieldSettings()[aColumnIndex]['_firstRowLabel'];
+//MochiKit.Logging.logDebug("--- updateInputFieldValues - [" + aColumnIndex + "] _firstRowLabel: " + label);
+ } else {
+ result = this.fieldSettings()[aColumnIndex]['_emptyLabel'];
+//MochiKit.Logging.logDebug("--- updateInputFieldValues - [" + aColumnIndex + "] _emptyLabel: " + label);
+ }
+ } else {
+ result = "";
+ }
+
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'setLabelForColumn': function(aLabel, aColumnIndex) {
+ var fieldSettings;
+
+//MochiKit.Logging.logDebug(">>> setLabelForColumn[" + aColumnIndex + "]: " + aLabel);
+ fieldSettings = this.fieldSettings();
+
+ if (typeof(fieldSettings[aColumnIndex]) == 'undefined') {
+ fieldSettings[aColumnIndex] = {}
+ }
+
+ if (this.isFirstRowHeader()) {
+//MochiKit.Logging.logDebug("--- setLabelForColumn -> _firstRowLabel");
+ fieldSettings[aColumnIndex]['_firstRowLabel'] = aLabel;
+ } else {
+ if (typeof(fieldSettings[aColumnIndex]['_emptyLabel']) == 'undefined') {
+ if (aLabel == null) {
+//MochiKit.Logging.logDebug("--- setLabelForColumn -> _emptyLabel = \"\"");
+ fieldSettings[aColumnIndex]['_emptyLabel'] = "";
+ } else {
+ fieldSettings[aColumnIndex]['_emptyLabel'] = aLabel;
+ }
+ } else {
+//MochiKit.Logging.logDebug("--- setLabelForColumn -> _emptyLabel = " + aLabel);
+ if (aLabel != null) {
+ fieldSettings[aColumnIndex]['_emptyLabel'] = aLabel;
+ }
+ }
+ }
+//MochiKit.Logging.logDebug("<<< setLabelForColumn[" + aColumnIndex + "]: " + aLabel);
+ },
+
+ //=========================================================================
+
+ 'typeForColumn': function(aColumnIndex) {
+ var result;
+
+ if ((typeof(this.fieldSettings()) != 'undefined') && (typeof(this.fieldSettings()[aColumnIndex]) != 'undefined') && (typeof(this.fieldSettings()[aColumnIndex]['type']) != 'undefined')) {
+ result = this.fieldSettings()[aColumnIndex]['type'];
+ } else {
+ result = 'UNDEFINED';
+ }
+
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'setTypeForColumn': function(aType, aColumnIndex) {
+ var fieldSettings;
+
+ fieldSettings = this.fieldSettings();
+
+ if (typeof(fieldSettings[aColumnIndex]) == 'undefined') {
+ fieldSettings[aColumnIndex] = {}
+ }
+
+ fieldSettings[aColumnIndex]['type'] = aType;
+ },
+
+ //=========================================================================
+ __syntaxFix__: "syntax fix"
+});
+
diff --git a/frontend/beta/js/Clipperz/PM/Components/Import/ClipperzImportComponent.js b/frontend/beta/js/Clipperz/PM/Components/Import/ClipperzImportComponent.js
new file mode 100644
index 0000000..50dcb93
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Components/Import/ClipperzImportComponent.js
@@ -0,0 +1,212 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
+if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
+if (typeof(Clipperz.PM.Components) == 'undefined') { Clipperz.PM.Components = {}; }
+if (typeof(Clipperz.PM.Components.Import) == 'undefined') { Clipperz.PM.Components.Import = {}; }
+
+//#############################################################################
+
+Clipperz.PM.Components.Import.ClipperzImportComponent = function(anElement, args) {
+ args = args || {};
+
+ Clipperz.PM.Components.Import.ClipperzImportComponent.superclass.constructor.call(this, anElement, args);
+
+ this.render();
+
+ return this;
+}
+
+//=============================================================================
+
+YAHOO.extendX(Clipperz.PM.Components.Import.ClipperzImportComponent, Clipperz.PM.Components.Import.GenericImportComponent, {
+
+ 'toString': function() {
+ return "Clipperz.PM.Components.Import.ClipperzImportComponent component";
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'render': function() {
+//MochiKit.Logging.logDebug(">>> Import.ClipperzImportComponent.render");
+ this.domHelper().append(this.element(), {tag:'div', cls:'clipperzImportWizard', children:[
+ {tag:'h3', htmlString:Clipperz.PM.Strings['Clipperz_ImportWizard_Title']},
+ {tag:'div', cls:'importSteps', id:this.getId('importSteps')},
+ {tag:'div', cls:'importStepBlocks', children:[
+ {tag:'div', cls:'step_0', id:this.getId('step_0'), children:[
+ {tag:'div', children:[
+ {tag:'div', cls:'importOptionsDescription', htmlString:Clipperz.PM.Strings['importOptions_clipperz_description']},
+ {tag:'div', cls:'importOptionsParameters', children:[]},
+ this.textAreaConfig()
+ ]}
+ ]},
+ {tag:'div', cls:'step_1', id:this.getId('step_1'), children:[
+ {tag:'div', children:[
+ {tag:'div', id:this.getId('previewDiv'), html:"preview"}
+ ]}
+ ]},
+ {tag:'div', cls:'step_2', id:this.getId('step_2'), children:[
+ {tag:'div', children:[
+ {tag:'h4', html:"done"}
+ ]}
+ ]}
+ ]},
+ {tag:'div', cls:'importOptionsButtons', children:[
+ {tag:'table', children:[
+ {tag:'tbody', children:[
+ {tag:'tr', children:[
+ {tag:'td', html:'&nbsp;'},
+ {tag:'td', children:[
+ {tag:'div', id:this.getId('backActionButton')}
+ ]},
+ {tag:'td', html:'&nbsp;'},
+ {tag:'td', children:[
+ {tag:'div', id:this.getId('nextActionButton')}
+ ]},
+ {tag:'td', html:'&nbsp;'}
+ ]}
+ ]}
+ ]}
+ ]}
+ ]});
+
+ this.updateSteps();
+
+ this.setBackButton(new YAHOO.ext.Button(this.getDom('backActionButton'), {text:"back", handler:this.backAction, scope:this}));
+ this.setNextButton(new YAHOO.ext.Button(this.getDom('nextActionButton'), {text:"next", handler:this.nextAction, scope:this}));
+
+ this.getElement('step_0').setVisibilityMode(YAHOO.ext.Element.DISPLAY).show()
+ this.getElement('step_1').setVisibilityMode(YAHOO.ext.Element.DISPLAY).hide();
+ this.getElement('step_2').setVisibilityMode(YAHOO.ext.Element.DISPLAY).hide();
+//MochiKit.Logging.logDebug("<<< Import.ClipperzImportComponent.render");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'nextAction': function() {
+ switch (this.currentStep()) {
+ case 0: // -> 1
+ this.previewValues();
+ break;
+ case 1: // -> 2
+ this.importValues();
+ break;
+ }
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'deferredPreviewValues': function() {
+ var deferredResult;
+
+ deferredResult = new MochiKit.Async.Deferred();
+ deferredResult.addCallback(MochiKit.Base.bind(function(res) {
+ this.startProcessing();
+
+ return res;
+ }, this));
+ deferredResult.addCallback(MochiKit.Base.method(this, 'processClipperzValues'));
+ deferredResult.addCallback(MochiKit.Base.method(this, 'setProcessedValues'));
+ deferredResult.addCallback(MochiKit.Base.method(this, 'previewRecordValues'));
+ deferredResult.addCallback(MochiKit.Base.bind(function(res) {
+ this.processingDone();
+ this.getElement('step_0').hide();
+ this.getElement('step_1').show();
+ this.backButton().enable();
+
+ return res;
+ }, this));
+// deferredResult.addErrback(MochiKit.Base.bind(function() {
+// this.processingAborted();
+// }, this))
+ deferredResult.callback(this.textAreaContent());
+
+ return deferredResult;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'processClipperzValues': function(someData) {
+ var deferredResult;
+
+ deferredResult = new MochiKit.Async.Deferred();
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Record.processClipperzValues - 1: " + res); return res;});
+ deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', 'parseImportData');
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Record.processClipperzValues - 2: " + res); return res;});
+ deferredResult.addCallback(Clipperz.Base.evalJSON);
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Record.processClipperzValues - 3: " + res); return res;});
+ deferredResult.addCallback(function(res) {
+ return Clipperz.NotificationCenter.deferredNotification(this, 'updatedProgressState', {steps:(res.length)}, res);
+ })
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Record.processClipperzValues - 4: " + res); return res;});
+ deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', 'previewImportData');
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Record.processClipperzValues - 5: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.bind(function(someClipperzValues) {
+ var innerDeferredResult;
+ var records;
+ var i,c;
+
+ innerDeferredResult = new MochiKit.Async.Deferred();
+ records = [];
+
+ c = someClipperzValues.length;
+ for(i=0; i<c; i++) {
+ innerDeferredResult.addCallback(MochiKit.Async.wait, 0.2);
+ innerDeferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', {});
+ innerDeferredResult.addCallback(MochiKit.Base.bind(function(someRecords, someData) {
+ var record;
+ var recordVersion;
+
+//MochiKit.Logging.logDebug("=== someData: " + Clipperz.Base.serializeJSON(someData));
+ record = new Clipperz.PM.DataModel.Record({user:this.user()});
+ record.setLabel(someData['label']);
+ record.setShouldProcessData(true);
+ record.processData(someData);
+
+ someRecords.push(record);
+
+ return someRecords;
+ }, this), records, someClipperzValues[i]);
+ }
+ innerDeferredResult.addCallback(MochiKit.Async.succeed, records);
+ innerDeferredResult.callback();
+
+ return innerDeferredResult;
+ }, this));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Record.processClipperzValues - 6: " + res); return res;});
+ deferredResult.callback(someData);
+
+ return deferredResult;
+ },
+
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+});
+
diff --git a/frontend/beta/js/Clipperz/PM/Components/Import/ExcelImportComponent.js b/frontend/beta/js/Clipperz/PM/Components/Import/ExcelImportComponent.js
new file mode 100644
index 0000000..ecdf509
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Components/Import/ExcelImportComponent.js
@@ -0,0 +1,134 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
+if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
+if (typeof(Clipperz.PM.Components) == 'undefined') { Clipperz.PM.Components = {}; }
+if (typeof(Clipperz.PM.Components.Import) == 'undefined') { Clipperz.PM.Components.Import = {}; }
+
+//#############################################################################
+
+Clipperz.PM.Components.Import.ExcelImportComponent = function(anElement, args) {
+ args = args || {};
+
+ this._steps = ['EXCEL_EDIT', 'CSV_COLUMNS', 'CSV_HEADER', 'CSV_TITLE', 'CSV_NOTES', 'CSV_FIELDS', 'PREVIEW', 'IMPORT'];
+
+ Clipperz.PM.Components.Import.ExcelImportComponent.superclass.constructor.call(this, anElement, args);
+
+ return this;
+}
+
+//=============================================================================
+
+YAHOO.extendX(Clipperz.PM.Components.Import.ExcelImportComponent, Clipperz.PM.Components.Import.CSVImportComponent, {
+
+ 'toString': function() {
+ return "Clipperz.PM.Components.Import.ExcelImportComponent component";
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'render': function() {
+//MochiKit.Logging.logDebug(">>> Import.ExcelImportComponent.render");
+ this.domHelper().append(this.element(), {tag:'div', cls:'excelImportWizard', children:[
+ {tag:'h3', htmlString:Clipperz.PM.Strings['Excel_ImportWizard_Title']},
+ {tag:'div', cls:'importSteps', id:this.getId('importSteps')},
+ {tag:'div', cls:'importStepBlocks', children:[
+ {tag:'div', cls:'step_0', id:this.getId('step_0'), children:[
+ {tag:'div', children:[
+ {tag:'div', cls:'importOptionsDescription', htmlString:Clipperz.PM.Strings['importOptions_excel_description']},
+ {tag:'div', cls:'importOptionsParameters', children:[]},
+ this.textAreaConfig()
+ ]}
+ ]},
+ {tag:'div', cls:'step_1', id:this.getId('step_1'), children:[]},
+ {tag:'div', cls:'step_2', id:this.getId('step_2'), children:[]},
+ {tag:'div', cls:'step_3', id:this.getId('step_3'), children:[]},
+ {tag:'div', cls:'step_4', id:this.getId('step_4'), children:[]},
+ {tag:'div', cls:'step_5', id:this.getId('step_5'), children:[]},
+ {tag:'div', cls:'step_6', id:this.getId('step_6'), children:[
+ {tag:'div', children:[
+ {tag:'div', id:this.getId('previewDiv'), html:"preview"}
+ ]}
+ ]},
+ {tag:'div', cls:'step_7', id:this.getId('step_7'), children:[
+ {tag:'div', children:[
+ {tag:'h4', html:"done"}
+ ]}
+ ]}
+ ]},
+ {tag:'div', cls:'importOptionsButtons', children:[
+ {tag:'table', children:[
+ {tag:'tbody', children:[
+ {tag:'tr', children:[
+ {tag:'td', html:'&nbsp;'},
+ {tag:'td', children:[
+ {tag:'div', id:this.getId('backActionButton')}
+ ]},
+ {tag:'td', html:'&nbsp;'},
+ {tag:'td', children:[
+ {tag:'div', id:this.getId('nextActionButton')}
+ ]},
+ {tag:'td', html:'&nbsp;'}
+ ]}
+ ]}
+ ]}
+ ]}
+ ]});
+
+ this.updateSteps();
+
+ this.setBackButton(new YAHOO.ext.Button(this.getDom('backActionButton'), {text:"back", handler:this.backAction, scope:this}));
+ this.setNextButton(new YAHOO.ext.Button(this.getDom('nextActionButton'), {text:"next", handler:this.nextAction, scope:this}));
+
+ this.getElement('step_0').setVisibilityMode(YAHOO.ext.Element.DISPLAY).show()
+ this.getElement('step_1').setVisibilityMode(YAHOO.ext.Element.DISPLAY).hide();
+ this.getElement('step_2').setVisibilityMode(YAHOO.ext.Element.DISPLAY).hide();
+ this.getElement('step_3').setVisibilityMode(YAHOO.ext.Element.DISPLAY).hide();
+ this.getElement('step_4').setVisibilityMode(YAHOO.ext.Element.DISPLAY).hide();
+ this.getElement('step_5').setVisibilityMode(YAHOO.ext.Element.DISPLAY).hide();
+ this.getElement('step_6').setVisibilityMode(YAHOO.ext.Element.DISPLAY).hide();
+ this.getElement('step_7').setVisibilityMode(YAHOO.ext.Element.DISPLAY).hide();
+//MochiKit.Logging.logDebug("<<< Import.ExcelImportComponent.render");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'csvProcessor': function() {
+ return new Clipperz.CSVProcessor({
+// quoteChar: this.getDom('CSV_inputOptions_quote').value,
+// escapeChar: this.getDom('CSV_inputOptions_escape').value,
+ separatorChar: '\t',
+ binary:true
+ });
+ },
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+});
+
diff --git a/frontend/beta/js/Clipperz/PM/Components/Import/GenericImportComponent.js b/frontend/beta/js/Clipperz/PM/Components/Import/GenericImportComponent.js
new file mode 100644
index 0000000..4f6b1e4
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Components/Import/GenericImportComponent.js
@@ -0,0 +1,523 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
+if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
+if (typeof(Clipperz.PM.Components) == 'undefined') { Clipperz.PM.Components = {}; }
+if (typeof(Clipperz.PM.Components.Import) == 'undefined') { Clipperz.PM.Components.Import = {}; }
+
+//#############################################################################
+
+Clipperz.PM.Components.Import.GenericImportComponent = function(anElement, args) {
+ args = args || {};
+
+ this._steps = this._steps || ['EDIT', 'PREVIEW', 'IMPORT'];
+
+ Clipperz.PM.Components.Import.GenericImportComponent.superclass.constructor.call(this, anElement, args);
+
+ this._user = args['user'];
+
+ this._currentStep = 0;
+ this._currentStatus = 'IDLE'; // 'PROCESSING'
+
+ this._parsedValues = null;
+ this._processedValues = null;
+
+ this._backButton = null;
+ this._nextButton = null;
+
+ Clipperz.NotificationCenter.register(null, 'importProcessorProgressUpdate', this, 'updateProgressDialogStatus');
+
+ return this;
+}
+
+//=============================================================================
+
+YAHOO.extendX(Clipperz.PM.Components.Import.GenericImportComponent, Clipperz.PM.Components.BaseComponent, {
+
+ 'toString': function() {
+ return "Clipperz.PM.Components.Import.GenericImportComponent component";
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'user': function() {
+ return this._user;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'textAreaConfig': function() {
+ return {tag:'textarea', name:this.getId('importTextArea'), cls:'importTextArea', id:this.getId('importTextArea'), cols:60, rows:15, html:""};
+ },
+
+ 'textAreaContent': function() {
+ return this.getDom('importTextArea').value
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'steps': function() {
+ return this._steps;
+ },
+
+ 'currentStep': function() {
+ return this._currentStep;
+ },
+
+ 'setCurrentStep': function(aValue) {
+ this._currentStep = aValue;
+ this.updateSteps();
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'currentStatus': function() {
+ return this._currentStatus;
+ },
+
+ 'startProcessing': function() {
+ this._currentStatus = 'PROCESSING';
+ this.updateSteps();
+ },
+
+ 'processingDone': function() {
+ this._currentStatus = 'IDLE';
+ this.setCurrentStep(this.currentStep() + 1);
+ },
+
+ 'processingAborted': function() {
+ this._currentStatus = 'IDLE';
+ this.updateSteps();
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'stepsConfig': function() {
+ var result;
+ var i,c;
+
+ result = [];
+ c = this.steps().length;
+ for (i=0; i<c; i++) {
+ var cls;
+
+ if (this.currentStep() == i) {
+ if (this.currentStatus() == 'IDLE') {
+ cls = 'current';
+ } else {
+ cls = 'currentProcessing';
+ }
+ } else {
+ cls = "";
+ }
+
+ result.push({tag:'td', cls:cls, children:[
+ {tag:'div', children:[{tag:'span', htmlString:Clipperz.PM.Strings['ImportWizard'][this.steps()[i]]}]}
+ ]})
+ if (i < (c-1)) {
+ if ((this.currentStep() == i) && (this.currentStatus() == 'PROCESSING')) {
+ cls = 'stepSeparatorProcessing';
+ } else {
+ cls = 'stepSeparator';
+ }
+
+ result.push({tag:'td', cls:cls, children:[
+ {tag:'div', children:[{tag:'span', html:">"}]}
+ ]});
+ }
+ }
+
+ result = [{tag:'div', cls:'importWizardStepsBox', children:[
+ {tag:'div', cls:'importWizardStepsInnerBox', children:[
+ {tag:'table', cls:'importWizardSteps', children:[
+ {tag:'tbody', children:[
+ {tag:'tr', children:result}
+ ]}
+ ]}
+ ]},
+ {tag:'div', cls:'importWizardStepsBoxFooter'}
+ ]}];
+
+ return result;
+ },
+
+ 'updateSteps': function() {
+ this.getElement('importSteps').update("");
+ Clipperz.YUI.DomHelper.append(this.getDom('importSteps'), {tag:'div', children:this.stepsConfig()});
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'backAction': function() {
+//MochiKit.Logging.logDebug(">>> backAction");
+ if (this.currentStep() == 0) {
+ Clipperz.NotificationCenter.notify(this, 'importCancelled');
+ } else {
+ this.getElement('step_' + this.currentStep()).hide();
+ this.setCurrentStep(this.currentStep() - 1);
+ this.getElement('step_' + this.currentStep()).show();
+
+ this.nextButton().enable();
+ }
+//MochiKit.Logging.logDebug("<<< backAction");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'backButton': function() {
+ return this._backButton;
+ },
+
+ 'setBackButton': function(aValue) {
+ this._backButton = aValue;
+ },
+
+ 'nextButton': function() {
+ return this._nextButton;
+ },
+
+ 'setNextButton': function(aValue) {
+ this._nextButton = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'render': function() {
+//MochiKit.Logging.logDebug(">>> Import.GenericImportComponent.render");
+ this.domHelper().append(this.element(), {tag:'div', children:[
+ {tag:'h2', html:this.toString()}
+ ]});
+//MochiKit.Logging.logDebug("<<< Import.GenericImportComponent.render");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'previewValues': function() {
+ Clipperz.PM.Components.MessageBox.showProgressPanel(
+ MochiKit.Base.method(this, 'deferredPreviewValues'),
+ MochiKit.Base.method(this, 'handlePreviewError'),
+ this.getDom('nextActionButton')
+ );
+ },
+
+ 'deferredPreviewValues': function() {
+ throw Clipperz.Base.exception.AbstractMethod;
+ },
+
+ 'handlePreviewError': function(anError) {
+console.log("anError", anError);
+ MochiKit.Logging.logError("An error occurred while previewing the data: " + anError);
+ alert("An error occurred while previewing the data");
+ Clipperz.PM.Components.MessageBox().hide();
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'previewRecordValues': function(someProcessedRecords) {
+//MochiKit.Logging.logDebug(">>> previewRecordValues");
+ this.getElement('previewDiv').update("");
+//MochiKit.Logging.logDebug("--- previewRecordValues - 1");
+ this.domHelper().append(this.getElement('previewDiv'), {tag:'div', cls:'importPreviewDiv', children:[{tag:'table', id:'importPreview', cellspacing:'0', children:[
+ {tag:'tbody', children:
+ MochiKit.Base.map(MochiKit.Base.bind(function(aRecord) {
+ var result;
+//MochiKit.Logging.logDebug("--- previewRecordValues - 1.1");
+//console.log("fields", aRecord.currentVersion().fields());
+ result = {tag:'tr', children:[{tag:'td', children:[
+ {tag:'table', cls:'importPreview_record', children:[
+ {tag:'tbody', children:[
+ {tag:'tr', children:[
+ {tag:'td', rowspan:'2', valign:'top', children:[
+ {tag:'input', type:'checkbox', id:this.getId(aRecord.reference()), value:"aRecord.reference()", checked:true}
+ ]},
+ {tag:'td', colspan:'2', children:[
+ {tag:'span', cls:'importPreview_title', html:aRecord.label()}
+ ]}
+ ]},
+ {tag:'tr', children:[
+ {tag:'td', valign:'top', children:[
+ {tag:'span', cls:'importPreview_notes', html:(MochiKit.Base.isNotEmpty(aRecord.notes()) ? aRecord.notes().replace(/\n/g, '<br>') : '&nbsp;')}
+ ]},
+ {tag:'td', valign:'top', cls:'importPreview_fieds', children:[
+ {tag:'table', cls:'importPreview_fields', children:[
+ {tag:'tbody', children:MochiKit.Base.map(function(aField) {
+ var result;
+//MochiKit.Logging.logDebug("--- previewRecordValues - 1.1.1");
+ result = {tag:'tr', children:[
+ {tag:'td', valign:'top', children:[
+ {tag:'span', cls:'importPreview_fields_label', html:aField.label()}
+ ]},
+ {tag:'td', valign:'top', children:[
+ {tag:'span', cls:'importPreview_fields_value', html:aField.value()}
+ ]}
+ ]};
+//MochiKit.Logging.logDebug("--- previewRecordValues - 1.1.2");
+ return result;
+ }, MochiKit.Base.values(aRecord.currentVersion().fields()))}
+ ]}
+ ]}
+ ]}
+ ]}
+ ]}
+ ]}]};
+//MochiKit.Logging.logDebug("--- previewRecordValues - 1.2");
+ return result;
+ }, this), someProcessedRecords)
+ }
+ ]}]});
+//MochiKit.Logging.logDebug("--- previewRecordValues - 2");
+
+ MochiKit.Base.map(MochiKit.Base.bind(function(aRecord) {
+ this.getElement(aRecord.reference()).dom.value = aRecord.reference();
+ }, this), someProcessedRecords);
+
+ Clipperz.Style.applyZebraStylesToTable('importPreview');
+//MochiKit.Logging.logDebug("<<< previewRecordValues");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'updateProgressDialogStatus': function(anEvent) {
+ Clipperz.PM.Components.MessageBox().update({step:anEvent.parameters().progress});
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'parsedValues': function() {
+ return this._parsedValues;
+ },
+
+ 'setParsedValues': function(aValue) {
+ this._parsedValues = aValue;
+
+ return this._parsedValues;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'processedValues': function() {
+ return this._processedValues;
+ },
+
+ 'setProcessedValues': function(aValue) {
+ this._processedValues = aValue;
+ return this._processedValues;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'importValues': function() {
+ var deferredResult;
+
+ deferredResult = new MochiKit.Async.Deferred();
+
+ deferredResult.addCallback(MochiKit.Base.bind(function() {
+ this.nextButton().disable();
+ this.startProcessing();
+ },this));
+ deferredResult.addCallback(MochiKit.Base.method(this, 'importProcessedValues'));
+ deferredResult.addCallback(MochiKit.Base.method(this, 'processingDone'));
+ deferredResult.addErrback (MochiKit.Base.method(this, 'processingAborted'));
+ deferredResult.callback();
+
+ return deferredResult;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'importProcessedValues': function() {
+ var deferredResult;
+ var processedValues;
+ var selectedRecords;
+ var i,c;
+
+//MochiKit.Logging.logDebug(">>> GenericImportComponent.importProcessedValues");
+ processedValues = this.processedValues();
+ selectedRecords = [];
+
+ c = processedValues.length;
+ for (i=0; i<c; i++) {
+ var currentRecord;
+
+ currentRecord = processedValues[i];
+ if (this.getDom(currentRecord.reference()).checked == true) {
+ selectedRecords.push(currentRecord);
+ }
+ }
+
+ deferredResult = new MochiKit.Async.Deferred();
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("GenericImportComponent - 1: " + res); return res;});
+ deferredResult.addCallback(function(someRecords) {
+ var innerDeferredResult;
+ var text;
+
+ text = Clipperz.PM.Strings['importData_importConfirmation_text'];
+ text = text.replace(/__numberOfRecords__/, someRecords.length);
+
+ innerDeferredResult = new MochiKit.Async.Deferred();
+//innerDeferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("GenericImportComponent - 1.1: " + res); return res;});
+ innerDeferredResult.addCallback(MochiKit.Async.succeed, someRecords);
+//innerDeferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("GenericImportComponent - 1.2: " + res); return res;});
+
+ Clipperz.PM.Components.MessageBox().deferredShow({
+ title:Clipperz.PM.Strings['importData_importConfirmation_title'],
+ text:text,
+ width:240,
+ showProgressBar:false,
+ showCloseButton:false,
+ buttons:{
+ 'yes':"yes", // Clipperz.PM.Strings['mainPanelDeleteRecordPanelConfirmButtonLabel'],
+ 'no':"no" // Clipperz.PM.Strings['mainPanelDeleteRecordPanelDenyButtonLabel']
+ },
+ fn:MochiKit.Base.partial(function(aDeferred, aResult) {
+ if (aResult == 'yes') {
+ aDeferred.callback(aResult);
+ } else {
+ aDeferred.errback(aResult);
+ }
+ }, innerDeferredResult)
+ }/*, this.getId('nextActionButton')*/);
+
+ return innerDeferredResult;
+ });
+
+//-------------------
+// deferredResult.addCallback(MochiKit.Base.bind(function(someRecords) {
+// Clipperz.PM.Components.MessageBox.showProgressPanel(
+// MochiKit.Base.method(this, 'importProcessedValues_core', someRecords),
+// MochiKit.Base.method(this, 'handleProcessError'),
+// this.getDom('mainDiv')
+// );
+// }, this));
+
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("GenericImportComponent - 2: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(Clipperz.PM.Components.MessageBox(), 'deferredShow'),
+ {
+// title:Clipperz.PM.Strings['accountPanelDeletingAccountPanelProgressTitle'],
+// text:Clipperz.PM.Strings['accountPanelDeletingAccountPanelProgressText'],
+ width:240,
+ showProgressBar:true,
+ showCloseButton:false
+ }
+ );
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("GenericImportComponent - 3: " + res); return res;});
+
+ deferredResult.addCallback(MochiKit.Base.bind(function(someRecords) {
+ var innerDeferredResult;
+
+//MochiKit.Logging.logDebug(">>> inner deferred");
+ innerDeferredResult = new MochiKit.Async.Deferred();
+
+//innerDeferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("GenericImportComponent - 3.1: " + res); return res;});
+ innerDeferredResult.addCallback(MochiKit.Base.method(this, 'importProcessedValues_core', someRecords));
+//innerDeferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("GenericImportComponent - 3.2: " + res); return res;});
+ innerDeferredResult.addErrback(MochiKit.Base.method(this, 'handleProcessError'));
+//innerDeferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("GenericImportComponent - 3.3: " + res); return res;});
+ innerDeferredResult.callback(someRecords);
+//MochiKit.Logging.logDebug("<<< inner deferred");
+
+ return innerDeferredResult;
+ }, this), selectedRecords);
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("GenericImportComponent - 4: " + res); return res;});
+
+ deferredResult.addCallback(MochiKit.Base.method(Clipperz.PM.Components.MessageBox(), 'hide'), 'mainDiv');
+
+ deferredResult.addErrback(MochiKit.Base.bind(function() {
+ this.nextButton().enable();
+ this.setCurrentStep(this.currentStep() -1);
+ }, this));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("GenericImportComponent - 5: " + res); return res;});
+
+ deferredResult.callback(selectedRecords);
+//MochiKit.Logging.logDebug("<<< GenericImportComponent.importProcessedValues");
+
+ return deferredResult;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'importProcessedValues_core': function(someRecords) {
+ var deferredResult;
+
+ deferredResult = new MochiKit.Async.Deferred();
+
+ deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', 'processingImportData');
+ deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', {steps:(someRecords.length + 6 + 1)});
+ deferredResult.addCallback(MochiKit.Async.wait, 0.5);
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("importProcessedValues_core - 3: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.bind(function(someRecords) {
+ var i,c;
+
+ c = someRecords.length;
+ for (i=0; i<c; i++) {
+ this.user().addRecord(someRecords[i], true);
+ }
+
+ return someRecords;
+ }, this));
+ deferredResult.addCallback(MochiKit.Async.wait, 0.5);
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("importProcessedValues_core - 4: " + res); return res;});
+ deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'recordAdded', null);
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("importProcessedValues_core - 5: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(this.user(), 'saveRecords'));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("importProcessedValues_core - 6: " + res); return res;});
+ deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'selectTab', 'mainTabPanel.recordsTab');
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("importProcessedValues_core - 7: " + res); return res;});
+
+ if (this.user().preferences().shouldShowDonationPanel()) {
+ deferredResult.addCallback(Clipperz.PM.showDonationSplashScreen, this.user(), 'mainDiv');
+ }
+
+ deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'importCompleted', null);
+
+ deferredResult.callback(someRecords);
+
+ return deferredResult;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'handleParseError': function(res) {
+ this.processingAborted();
+ MochiKit.Logging.logError("An error occurred while parsing the values: " + res);
+ alert("An error occurred while parsing the values: " + res);
+ Clipperz.PM.Components.MessageBox().hide();
+ },
+
+ 'handleProcessError': function(res) {
+ this.processingAborted();
+ MochiKit.Logging.logError("An error occurred while processing the values: " + res);
+ alert("An error occurred while processing the values: " + res);
+ Clipperz.PM.Components.MessageBox().hide();
+ },
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+});
+
diff --git a/frontend/beta/js/Clipperz/PM/Components/Import/KeePassImportComponent.js b/frontend/beta/js/Clipperz/PM/Components/Import/KeePassImportComponent.js
new file mode 100644
index 0000000..0657520
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Components/Import/KeePassImportComponent.js
@@ -0,0 +1,450 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
+if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
+if (typeof(Clipperz.PM.Components) == 'undefined') { Clipperz.PM.Components = {}; }
+if (typeof(Clipperz.PM.Components.Import) == 'undefined') { Clipperz.PM.Components.Import = {}; }
+
+//#############################################################################
+
+Clipperz.PM.Components.Import.KeePassImportComponent = function(anElement, args) {
+ args = args || {};
+
+ Clipperz.PM.Components.Import.KeePassImportComponent.superclass.constructor.call(this, anElement, args);
+
+ this._steps = ['EDIT', 'KEEPASS_SETTINGS', 'PREVIEW', 'IMPORT'];
+ this._definedFields = ['Group', 'Group Tree', 'UserName', 'URL', 'Password', 'Notes', 'UUID', 'Icon', 'Creation Time', 'Last Access', 'Last Modification', 'Expires', 'Attachment Description', 'Attachment'];
+
+ this.render();
+
+ return this;
+}
+
+//=============================================================================
+
+YAHOO.extendX(Clipperz.PM.Components.Import.KeePassImportComponent, Clipperz.PM.Components.Import.GenericImportComponent, {
+
+ 'toString': function() {
+ return "Clipperz.PM.Components.Import.KeePassImportComponent component";
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'render': function() {
+//MochiKit.Logging.logDebug(">>> Import.KeePassImportComponent.render");
+ this.domHelper().append(this.element(), {tag:'div', cls:'keePassImportWizard', children:[
+ {tag:'h3', htmlString:Clipperz.PM.Strings['KeePass_ImportWizard_Title']},
+ {tag:'div', cls:'importSteps', id:this.getId('importSteps')},
+ {tag:'div', cls:'importStepBlocks', children:[
+ {tag:'div', cls:'step_0', id:this.getId('step_0'), children:[
+ {tag:'div', children:[
+ {tag:'div', cls:'importOptionsDescription', htmlString:Clipperz.PM.Strings['importOptions_keePass_description']},
+ {tag:'div', cls:'importOptionsParameters', children:[]},
+ this.textAreaConfig()
+ ]}
+ ]},
+ {tag:'div', cls:'step_1', id:this.getId('step_1'), children:[
+ {tag:'div', children:[
+ {tag:'div', id:this.getId('settingsDiv'), children:[
+ {tag:'table', id:'KeePassSettings', children:[
+ {tag:'tbody', children:[
+ {tag:'tr', children:[
+ {tag:'td', width:'50%', valign:'top', children:[
+ {tag:'table', children:[
+ {tag:'tbody', children:[
+ {tag:'tr', children:[
+ {tag:'td', valign:'top', children:[{tag:'input', type:'checkbox', id:this.getId('Group_checkbox'), name:'Group'/*, checked:true*/}]},
+ {tag:'td', width:'150', valign:'top', children:[{tag:'span', cls:'keePassFieldLabel', id:this.getId('Group_label'), html:"Group"}]}
+ ]},
+ {tag:'tr', children:[
+ {tag:'td', valign:'top', children:[{tag:'input', type:'checkbox', id:this.getId('Group Tree_checkbox'), name:'Group Tree'/*, checked:true*/}]},
+ {tag:'td', valign:'top', children:[{tag:'span', cls:'keePassFieldLabel', id:this.getId('Group Tree_label'), html:"Group Tree"}]}
+ ]},
+ {tag:'tr', children:[
+ {tag:'td', valign:'top', children:[{tag:'input', type:'checkbox', id:this.getId('UserName_checkbox'), name:'UserName', checked:true}]},
+ {tag:'td', valign:'top', children:[{tag:'span', cls:'keePassFieldLabel', id:this.getId('UserName_label'), html:"UserName"}]}
+ ]},
+ {tag:'tr', children:[
+ {tag:'td', valign:'top', children:[{tag:'input', type:'checkbox', id:this.getId('URL_checkbox'), name:'URL', checked:true}]},
+ {tag:'td', valign:'top', children:[{tag:'span', cls:'keePassFieldLabel', id:this.getId('URL_label'), html:"URL"}]}
+ ]},
+ {tag:'tr', children:[
+ {tag:'td', valign:'top', children:[{tag:'input', type:'checkbox', id:this.getId('Password_checkbox'), name:'Password', checked:true}]},
+ {tag:'td', valign:'top', children:[{tag:'span', cls:'keePassFieldLabel', id:this.getId('Password_label'), html:"Password"}]}
+ ]},
+ {tag:'tr', children:[
+ {tag:'td', valign:'top', children:[{tag:'input', type:'checkbox', id:this.getId('Notes_checkbox'), name:'Notes', checked:true}]},
+ {tag:'td', valign:'top', children:[{tag:'span', cls:'keePassFieldLabel', id:this.getId('Notes_label'), html:"Notes"}]}
+ ]},
+ {tag:'tr', children:[
+ {tag:'td', valign:'top', children:[{tag:'input', type:'checkbox', id:this.getId('UUID_checkbox'), name:'UUID'/*, checked:true*/}]},
+ {tag:'td', valign:'top', children:[{tag:'span', cls:'keePassFieldLabel', id:this.getId('UUID_label'), html:"UUID"}]}
+ ]}
+ ]}
+ ]}
+ ]},
+ {tag:'td', width:'50%', valign:'top', children:[
+ {tag:'table', children:[
+ {tag:'tbody', children:[
+ {tag:'tr', children:[
+ {tag:'td', valign:'top', children:[{tag:'input', type:'checkbox', id:this.getId('Icon_checkbox'), name:'Icon'/*, checked:true*/}]},
+ {tag:'td', width:'150', valign:'top', children:[{tag:'span', cls:'keePassFieldLabel', id:this.getId('Icon_label'), html:"Icon"}]}
+ ]},
+ {tag:'tr', children:[
+ {tag:'td', valign:'top', children:[{tag:'input', type:'checkbox', id:this.getId('Creation Time_checkbox'), name:'Creation Time'/*, checked:true*/}]},
+ {tag:'td', valign:'top', children:[{tag:'span', cls:'keePassFieldLabel', id:this.getId('Creation Time_label'), html:"Creation Time"}]}
+ ]},
+ {tag:'tr', children:[
+ {tag:'td', valign:'top', children:[{tag:'input', type:'checkbox', id:this.getId('Last Access_checkbox'), name:'Last Access'/*, checked:true*/}]},
+ {tag:'td', valign:'top', children:[{tag:'span', cls:'keePassFieldLabel', id:this.getId('Last Access_label'), html:"Last Access"}]}
+ ]},
+ {tag:'tr', children:[
+ {tag:'td', valign:'top', children:[{tag:'input', type:'checkbox', id:this.getId('Last Modification_checkbox'), name:'Last Modification'/*, checked:true*/}]},
+ {tag:'td', valign:'top', children:[{tag:'span', cls:'keePassFieldLabel', id:this.getId('Last Modification_label'), html:"Last Modification"}]}
+ ]},
+ {tag:'tr', children:[
+ {tag:'td', valign:'top', children:[{tag:'input', type:'checkbox', id:this.getId('Expires_checkbox'), name:'Expires'/*, checked:true*/}]},
+ {tag:'td', valign:'top', children:[{tag:'span', cls:'keePassFieldLabel', id:this.getId('Expires_label'), html:"Expires"}]}
+ ]},
+ {tag:'tr', children:[
+ {tag:'td', valign:'top', children:[{tag:'input', type:'checkbox', id:this.getId('Attachment Description_checkbox'), name:'Attachment Description', checked:true}]},
+ {tag:'td', valign:'top', children:[{tag:'span', cls:'keePassFieldLabel', id:this.getId('Attachment Description_label'), html:"Attachment Description"}]}
+ ]},
+ {tag:'tr', children:[
+ {tag:'td', valign:'top', children:[{tag:'input', type:'checkbox', id:this.getId('Attachment_checkbox'), name:'Attachment', checked:true}]},
+ {tag:'td', valign:'top', children:[{tag:'span', cls:'keePassFieldLabel', id:this.getId('Attachment_label'), html:"Attachment"}]}
+ ]}
+ ]}
+ ]}
+ ]}
+ ]}
+ ]}
+ ]}
+ ]}
+ ]}
+ ]},
+ {tag:'div', cls:'step_2', id:this.getId('step_2'), children:[
+ {tag:'div', children:[
+ {tag:'div', id:this.getId('previewDiv'), html:"preview"}
+ ]}
+ ]},
+ {tag:'div', cls:'step_3', id:this.getId('step_3'), children:[
+ {tag:'div', children:[
+ {tag:'h4', html:"done"}
+ ]}
+ ]}
+ ]},
+ {tag:'div', cls:'importOptionsButtons', children:[
+ {tag:'table', children:[
+ {tag:'tbody', children:[
+ {tag:'tr', children:[
+ {tag:'td', html:'&nbsp;'},
+ {tag:'td', children:[
+ {tag:'div', id:this.getId('backActionButton')}
+ ]},
+ {tag:'td', html:'&nbsp;'},
+ {tag:'td', children:[
+ {tag:'div', id:this.getId('nextActionButton')}
+ ]},
+ {tag:'td', html:'&nbsp;'}
+ ]}
+ ]}
+ ]}
+ ]}
+ ]});
+
+ this.updateSteps();
+
+ this.setBackButton(new YAHOO.ext.Button(this.getDom('backActionButton'), {text:"back", handler:this.backAction, scope:this}));
+ this.setNextButton(new YAHOO.ext.Button(this.getDom('nextActionButton'), {text:"next", handler:this.nextAction, scope:this}));
+
+ this.getElement('step_0').setVisibilityMode(YAHOO.ext.Element.DISPLAY).show()
+ this.getElement('step_1').setVisibilityMode(YAHOO.ext.Element.DISPLAY).hide();
+ this.getElement('step_2').setVisibilityMode(YAHOO.ext.Element.DISPLAY).hide();
+ this.getElement('step_3').setVisibilityMode(YAHOO.ext.Element.DISPLAY).hide();
+//MochiKit.Logging.logDebug("<<< Import.KeePassImportComponent.render");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'nextAction': function() {
+ switch (this.currentStep()) {
+ case 0: // -> 1
+ Clipperz.PM.Components.MessageBox.showProgressPanel(
+ MochiKit.Base.method(this, 'deferredParseValues'),
+ MochiKit.Base.method(this, 'handleParseError'),
+ this.getDom('nextActionButton')
+ );
+ break;
+ case 1: // -> 2
+ this.previewValues();
+ break;
+ case 2: // -> 3
+ this.importValues();
+ break;
+ }
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'deferredParseValues': function() {
+ var deferredResult;
+
+ deferredResult = new MochiKit.Async.Deferred();
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("KeePassImportComponent.deferredParseValues - 1 " + res.substring(0,50)); return res;});
+ deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', 'parseImportData');
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("KeePassImportComponent.deferredParseValues - 2 " + res.substring(0,50)); return res;});
+ deferredResult.addCallback(MochiKit.Base.bind(function(res) {
+ this.startProcessing();
+
+ return res;
+ }, this));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("KeePassImportComponent.deferredParseValues - 3 " + res.substring(0,50)); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(this, 'parseKeePassValues')); // processPasswordPlusValues
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("KeePassImportComponent.deferredParseValues - 4 " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(this, 'setParsedValues')); // setProcessedValues
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("KeePassImportComponent.deferredParseValues - 5 " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(this, 'showSettings')); // previewRecordValues
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("KeePassImportComponent.deferredParseValues - 6 " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.bind(function(res) {
+ this.processingDone();
+ this.getElement('step_0').hide();
+ this.getElement('step_1').show();
+ this.backButton().enable();
+
+ return res;
+ }, this));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("KeePassImportComponent.deferredParseValues - 7 " + res); return res;});
+ deferredResult.callback(this.textAreaContent());
+
+ return deferredResult;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'deferredPreviewValues': function() {
+ var deferredResult;
+
+//MochiKit.Logging.logDebug(">>> KeePassImportComonent.deferredPreviewValues");
+ deferredResult = new MochiKit.Async.Deferred();
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("KeePassImportComponent.deferredPreviewValues - 1 " + res); return res;});
+ deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', 'previewImportData');
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("KeePassImportComponent.deferredPreviewValues - 2 " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.bind(function(res) {
+ this.startProcessing();
+
+ return res;
+ }, this));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("KeePassImportComponent.deferredPreviewValues - 3 " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(this, 'processKeePassParsedValues'));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("KeePassImportComponent.deferredPreviewValues - 4 " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(this, 'setProcessedValues'));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("KeePassImportComponent.deferredPreviewValues - 5 " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(this, 'previewRecordValues'));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("KeePassImportComponent.deferredPreviewValues - 6 " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.bind(function(res) {
+ this.processingDone();
+ this.getElement('step_1').hide();
+ this.getElement('step_2').show();
+ this.backButton().enable();
+
+ return res;
+ }, this));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("KeePassImportComponent.deferredPreviewValues - 7 " + res); return res;});
+// deferredResult.addErrback(MochiKit.Base.bind(function() {
+// this.processingAborted();
+// }, this))
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("KeePassImportComponent.deferredPreviewValues - 8 " + res); return res;});
+ deferredResult.callback(this.parsedValues());
+//MochiKit.Logging.logDebug("<<< KeePassImportComonent.deferredPreviewValues");
+
+ return deferredResult;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'definedFields': function() {
+ return this._definedFields;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'parseKeePassValues': function(someData) {
+ var deferredResult;
+ var keePassProcessor;
+
+ keePassProcessor = new Clipperz.KeePassExportProcessor();
+
+ deferredResult = new MochiKit.Async.Deferred();
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("KeePassImportComponent.parseKeePassValues - 1 " + res.substring(0,50)); return res;});
+ deferredResult.addCallback(function(res) {
+ return Clipperz.NotificationCenter.deferredNotification(this, 'updatedProgressState', {steps:(res.length)}, res);
+ })
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("KeePassImportComponent.parseKeePassValues - 2 " + res.substring(0,50)); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(keePassProcessor, 'deferredParse'));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("KeePassImportComponent.parseKeePassValues - 3 " + res); return res;});
+ deferredResult.callback(someData);
+
+ return deferredResult;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'showSettings': function(someValues) {
+ var availableFields;
+ var i,c;
+
+//MochiKit.Logging.logDebug(">>> KeePassImportCOmponent.showSettings");
+ availableFields = new Clipperz.Set();
+ c = this.parsedValues().length;
+ for (i=0; i<c; i++) {
+ var fieldLabel;
+
+ for (fieldLabel in this.parsedValues()[i]) {
+ availableFields.add(fieldLabel);
+ }
+ }
+
+ c = this.definedFields().length;
+ for (i=0; i<c; i++) {
+ var definedField;
+
+ definedField = this.definedFields()[i];
+ if (availableFields.contains(definedField)) {
+//MochiKit.Logging.logDebug("enabling field " + definedField);
+ this.getDom(definedField + '_checkbox').disabled = false;
+ this.getElement(definedField + '_label').removeClass('disabled');
+ } else {
+//MochiKit.Logging.logDebug("disabling field " + definedField);
+ this.getDom(definedField + '_checkbox').disabled = true;
+ this.getDom(definedField + '_checkbox').checked = false; // ????
+ this.getElement(definedField + '_label').addClass('disabled');
+ }
+ }
+//MochiKit.Logging.logDebug("<<< KeePassImportCOmponent.showSettings");
+
+ return MochiKit.Async.succeed(someValues);
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'shouldImportField': function(aFieldName) {
+ var fieldCheckbox;
+ var result;
+
+//MochiKit.Logging.logDebug(">>> shouldImportField: " + aFieldName);
+// fieldCheckbox = this.getDom(aFieldName + '_checkbox');
+ fieldCheckbox = MochiKit.DOM.getElement(this.getId(aFieldName + '_checkbox'));
+ if (fieldCheckbox != null) {
+ result = fieldCheckbox.checked;
+ } else {
+ result = false;
+ }
+//MochiKit.Logging.logDebug("<<< shouldImportField: " + result);
+
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'processKeePassParsedValues': function(someValues) {
+ var deferredResult;
+ var records;
+ var i,c;
+
+//MochiKit.Logging.logDebug(">>> processKeePassParsedValues");
+ deferredResult = new MochiKit.Async.Deferred();
+ records = [];
+
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("processKeePassParsedValues - 1: " + res); return res;});
+ c = someValues.length;
+ deferredResult.addCallback(function(res) {
+ return Clipperz.NotificationCenter.deferredNotification(this, 'updatedProgressState', {steps:c}, res);
+ })
+ for(i=0; i<c; i++) {
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("[" + i + "] processKeePassParsedValues - 1.1: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Async.wait, 0.2);
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("[" + i + "] processKeePassParsedValues - 1.2: " + res); return res;});
+ deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', {});
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("[" + i + "] processKeePassParsedValues - 1.3: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.bind(function(someRecords, someData) {
+ var record;
+ var recordVersion;
+ var ii;
+
+ record = new Clipperz.PM.DataModel.Record({user:this.user()});
+ record.setLabel(someData['Title']);
+ if (this.shouldImportField('Notes')) {
+ record.setNotes(someData['Notes']);
+ }
+ recordVersion = record.currentVersion()
+
+ for (ii in someData) {
+ if ((ii != 'Title') && (ii != 'Notes') && (typeof(someData[ii]) != "undefined") && (this.shouldImportField(ii))) {
+ var recordField;
+ var recordFieldType;
+
+ recordFieldType = 'TXT';
+ if (ii == 'Password') {
+ recordFieldType = 'PWD';
+ } else if (ii == 'URL') {
+ recordFieldType = 'URL';
+ } else if ((ii == 'Creation Time') || (ii == 'Last Access') || (ii == 'Last Modification') || (ii == 'Expires')) {
+ recordFieldType = 'Date';
+ }
+
+ recordField = new Clipperz.PM.DataModel.RecordField({
+ recordVersion: recordVersion,
+ label: ii,
+ value: someData[ii],
+ type: recordFieldType
+ });
+ recordVersion.addField(recordField);
+ }
+ }
+
+ someRecords.push(record);
+
+ return someRecords;
+ }, this), records, someValues[i]);
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("[" + i + "] processKeePassParsedValues - 1.4: " + res); return res;});
+ }
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("processKeePassParsedValues - 2: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Async.succeed, records);
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("processKeePassParsedValues - 3: " + res); return res;});
+ deferredResult.callback();
+//MochiKit.Logging.logDebug("<<< processKeePassParsedValues");
+
+ return deferredResult;
+ },
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+});
+
diff --git a/frontend/beta/js/Clipperz/PM/Components/Import/MainComponent.js b/frontend/beta/js/Clipperz/PM/Components/Import/MainComponent.js
new file mode 100644
index 0000000..54813bc
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Components/Import/MainComponent.js
@@ -0,0 +1,332 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
+if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
+if (typeof(Clipperz.PM.Components) == 'undefined') { Clipperz.PM.Components = {}; }
+if (typeof(Clipperz.PM.Components.Import) == 'undefined') { Clipperz.PM.Components.Import = {}; }
+
+//#############################################################################
+
+Clipperz.PM.Components.Import.MainComponent = function(anElement, args) {
+ args = args || {};
+
+ Clipperz.PM.Components.Import.MainComponent.superclass.constructor.call(this, anElement, args);
+
+ this._user = args.user;
+ this._wizardComponent = null;
+
+ this._backButton = null;
+ this._nextButton = null;
+
+ this._selectedComponent = null;
+
+ this.render();
+
+ return this;
+}
+
+//=============================================================================
+
+YAHOO.extendX(Clipperz.PM.Components.Import.MainComponent, Clipperz.PM.Components.BaseComponent, {
+
+ 'toString': function() {
+ return "Clipperz.PM.Components.Import.MainComponent component";
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'user': function() {
+ return this._user;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'wizardComponent': function() {
+ return this._wizardComponent;
+ },
+
+ 'setWizardComponent': function(aValue) {
+ if (this._wizardComponent != null) {
+ this._wizardComponent.remove();
+ }
+
+ if (aValue != null) {
+ this.getElement('importCover').hide();
+ this.getElement('importWizard').show();
+ }
+ this._wizardComponent = aValue;
+ },
+
+ 'resetImportComponent': function() {
+//MochiKit.Logging.logDebug(">>> resetImportComponent");
+ this.setWizardComponent(null);
+ this.getElement('wizardComponent').update("");
+
+ this.getElement('importCover').show();
+ this.getElement('importWizard').hide();
+//MochiKit.Logging.logDebug("<<< resetImportComponent");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'backButton': function() {
+ return this._backButton;
+ },
+
+ 'setBackButton': function(aValue) {
+ this._backButton = aValue;
+ },
+
+ 'nextButton': function() {
+ return this._nextButton;
+ },
+
+ 'setNextButton': function(aValue) {
+ this._nextButton = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'render': function() {
+//MochiKit.Logging.logDebug(">>> Import.MainComponent.render");
+ Clipperz.NotificationCenter.unregister(this);
+ MochiKit.Signal.disconnectAllTo(this);
+
+ this.element().update("");
+ this.domHelper().append(this.element(), {tag:'div', id:this.getId('mainDiv'), children:[
+ {tag:'div', id:this.getId('importCover'), children:[
+ {tag:'h5', htmlString:Clipperz.PM.Strings['importTabTitle']},
+ {tag:'div', cls:'panelDescription', htmlString:Clipperz.PM.Strings['importTabDescription']},
+ {tag:'div', cls:'importFormats', children:[
+ {tag:'ul', cls:'radioList', children:[
+ {tag:'li', children:[
+ {tag:'table', children:[{tag:'tbody', children:[{tag:'tr', children:[
+ {tag:'td', valign:'top', children:[
+ {tag:'input', id:this.getId('CSV_radio'), type:'radio', name:'importFormat', value:'CSV'}
+ ]},
+ {tag:'td', valign:'top', children:[
+ {tag:'h4', id:this.getId('CSV_title'), htmlString:Clipperz.PM.Strings['importFormats']['CSV']['label']},
+ {tag:'div', cls:'templateDescription', htmlString:Clipperz.PM.Strings['importFormats']['CSV']['description']}
+ ]}
+ ]}]}]}
+ ]},
+ {tag:'li', children:[
+ {tag:'table', children:[{tag:'tbody', children:[{tag:'tr', children:[
+ {tag:'td', valign:'top', children:[
+ {tag:'input', id:this.getId('Excel_radio'), type:'radio', name:'importFormat', value:'EXCEL'}
+ ]},
+ {tag:'td', valign:'top', children:[
+ {tag:'h4', id:this.getId('Excel_title'), htmlString:Clipperz.PM.Strings['importFormats']['Excel']['label']},
+ {tag:'div', cls:'templateDescription', htmlString:Clipperz.PM.Strings['importFormats']['Excel']['description']}
+ ]}
+ ]}]}]}
+ ]},
+ {tag:'li', children:[
+ {tag:'table', children:[{tag:'tbody', children:[{tag:'tr', children:[
+ {tag:'td', valign:'top', children:[
+ {tag:'input', id:this.getId('KeePass_radio'), type:'radio', name:'importFormat', value:'KEEPASS'}
+ ]},
+ {tag:'td', valign:'top', children:[
+ {tag:'h4', id:this.getId('KeePass_title'), htmlString:Clipperz.PM.Strings['importFormats']['KeePass']['label']},
+ {tag:'div', cls:'templateDescription', htmlString:Clipperz.PM.Strings['importFormats']['KeePass']['description']}
+ ]}
+ ]}]}]}
+ ]},
+ {tag:'li', children:[
+ {tag:'table', children:[{tag:'tbody', children:[{tag:'tr', children:[
+ {tag:'td', valign:'top', children:[
+ {tag:'input', id:this.getId('Roboform_radio'), type:'radio', name:'importFormat', value:'ROBOFORM'}
+ ]},
+ {tag:'td', valign:'top', children:[
+ {tag:'h4', id:this.getId('Roboform_title'), htmlString:Clipperz.PM.Strings['importFormats']['Roboform']['label']},
+ {tag:'div', cls:'templateDescription', htmlString:Clipperz.PM.Strings['importFormats']['Roboform']['description']}
+ ]}
+ ]}]}]}
+ ]},
+ {tag:'li', children:[
+ {tag:'table', children:[{tag:'tbody', children:[{tag:'tr', children:[
+ {tag:'td', valign:'top', children:[
+ {tag:'input', id:this.getId('PasswordPlus_radio'), type:'radio', name:'importFormat', value:'PASSWORD_PLUS'}
+ ]},
+ {tag:'td', valign:'top', children:[
+ {tag:'h4', id:this.getId('PasswordPlus_title'), htmlString:Clipperz.PM.Strings['importFormats']['PasswordPlus']['label']},
+ {tag:'div', cls:'templateDescription', htmlString:Clipperz.PM.Strings['importFormats']['PasswordPlus']['description']}
+ ]}
+ ]}]}]}
+ ]},
+ {tag:'li', children:[
+ {tag:'table', children:[{tag:'tbody', children:[{tag:'tr', children:[
+ {tag:'td', valign:'top', children:[
+ {tag:'input', id:this.getId('ClipperzExport_radio'), type:'radio', name:'importFormat', value:'CLIPPERZ_EXPORT'}
+ ]},
+ {tag:'td', valign:'top', children:[
+ {tag:'h4', id:this.getId('ClipperzExport_title'), htmlString:Clipperz.PM.Strings['importFormats']['ClipperzExport']['label']},
+ {tag:'div', cls:'templateDescription', htmlString:Clipperz.PM.Strings['importFormats']['ClipperzExport']['description']}
+ ]}
+ ]}]}]}
+ ]}
+ ]},
+
+ {tag:'div', cls:'importOptionsButtons', children:[
+ {tag:'table', children:[
+ {tag:'tbody', children:[
+ {tag:'tr', children:[
+ {tag:'td', html:'&nbsp;'},
+ {tag:'td', children:[
+ {tag:'div', id:this.getId('backActionButton')}
+ ]},
+ {tag:'td', html:'&nbsp;'},
+ {tag:'td', children:[
+ {tag:'div', id:this.getId('nextActionButton')}
+ ]},
+ {tag:'td', html:'&nbsp;'}
+ ]}
+ ]}
+ ]}
+ ]}
+ ]}
+ ]},
+ {tag:'div', id:this.getId('importWizard'), children:[
+ {tag:'form', id:this.getId('importWizardForm'), children:[
+ {tag:'div', cls:'wizardComponent', id:this.getId('wizardComponent'), children:[]}
+ ]}
+ ]}
+ ]});
+
+ this.setBackButton(new YAHOO.ext.Button(this.getDom('backActionButton'), {text:"back", handler:this.backAction, scope:this}));
+ this.setNextButton(new YAHOO.ext.Button(this.getDom('nextActionButton'), {text:"next", handler:this.nextAction, scope:this}));
+
+ this.backButton().disable();
+ this.nextButton().disable();
+
+ this.getElement('importCover').setVisibilityMode(YAHOO.ext.Element.DISPLAY).show();
+ this.getElement('importWizard').setVisibilityMode(YAHOO.ext.Element.DISPLAY).hide();
+
+ if (Clipperz.PM.Proxy.defaultProxy.isReadOnly()) {
+ this.getElement('mainDiv').addClass('read-only');
+
+ this.getDom('ClipperzExport_radio').disabled = true;
+ this.getDom('CSV_radio').disabled = true;
+ this.getDom('Excel_radio').disabled = true;
+ this.getDom('PasswordPlus_radio').disabled = true;
+ this.getDom('Roboform_radio').disabled = true;
+ this.getDom('KeePass_radio').disabled = true;
+ } else {
+ MochiKit.Signal.connect(this.getId('ClipperzExport_radio'), 'onclick', MochiKit.Base.method(this, 'selectComponent'));
+ MochiKit.Signal.connect(this.getId('CSV_radio'), 'onclick', MochiKit.Base.method(this, 'selectComponent'));
+ MochiKit.Signal.connect(this.getId('Excel_radio'), 'onclick', MochiKit.Base.method(this, 'selectComponent'));
+ MochiKit.Signal.connect(this.getId('PasswordPlus_radio'), 'onclick', MochiKit.Base.method(this, 'selectComponent'));
+ MochiKit.Signal.connect(this.getId('Roboform_radio'), 'onclick', MochiKit.Base.method(this, 'selectComponent'));
+ MochiKit.Signal.connect(this.getId('KeePass_radio'), 'onclick', MochiKit.Base.method(this, 'selectComponent'));
+
+ if (Clipperz_IEisBroken != true) {
+ MochiKit.Signal.connect(this.getId('ClipperzExport_title'), 'onclick', this.getDom('ClipperzExport_radio'), 'click');
+ MochiKit.Signal.connect(this.getId('CSV_title'), 'onclick', this.getDom('CSV_radio'), 'click');
+ MochiKit.Signal.connect(this.getId('Excel_title'), 'onclick', this.getDom('Excel_radio'), 'click');
+ MochiKit.Signal.connect(this.getId('PasswordPlus_title'), 'onclick', this.getDom('PasswordPlus_radio'), 'click');
+ MochiKit.Signal.connect(this.getId('Roboform_title'), 'onclick', this.getDom('Roboform_radio'), 'click');
+ MochiKit.Signal.connect(this.getId('KeePass_title'), 'onclick', this.getDom('KeePass_radio'), 'click');
+ }
+
+ Clipperz.NotificationCenter.register(null, 'importCompleted', this, 'resetImportComponent');
+ Clipperz.NotificationCenter.register(null, 'importCancelled', this, 'resetImportComponent');
+ }
+
+//MochiKit.Logging.logDebug("<<< Import.MainComponent.render");
+ },
+
+ //-------------------------------------------------------------------------
+/*
+ 'selectedFormat': function() {
+ return this.getDom('importSelectionOptions').value;
+ },
+*/
+ //-------------------------------------------------------------------------
+
+ 'updateSelectedImportWizardComponent': function(aComponent) {
+ var newWizardComponent;
+
+//MochiKit.Logging.logDebug(">>> Import.MainComponent.updateSelectedImportWizardComponent");
+ this.getElement('wizardComponent').update("");
+
+ switch(aComponent) {
+ case 'CLIPPERZ_EXPORT':
+ newWizardComponent = new Clipperz.PM.Components.Import.ClipperzImportComponent(this.getElement('wizardComponent'), {user:this.user()});
+ break;
+ case 'CSV':
+ newWizardComponent = new Clipperz.PM.Components.Import.CSVImportComponent(this.getElement('wizardComponent'), {user:this.user()});
+ break;
+ case 'EXCEL':
+ newWizardComponent = new Clipperz.PM.Components.Import.ExcelImportComponent(this.getElement('wizardComponent'), {user:this.user()});
+ break;
+ case 'PASSWORD_PLUS':
+ newWizardComponent = new Clipperz.PM.Components.Import.PasswordPlusImportComponent(this.getElement('wizardComponent'), {user:this.user()});
+ break;
+ case 'ROBOFORM':
+ newWizardComponent = new Clipperz.PM.Components.Import.RoboFormImportComponent(this.getElement('wizardComponent'), {user:this.user()});;
+ break;
+ case 'KEEPASS':
+ newWizardComponent = new Clipperz.PM.Components.Import.KeePassImportComponent(this.getElement('wizardComponent'), {user:this.user()});
+ break;
+ }
+
+ this.setWizardComponent(newWizardComponent);
+//MochiKit.Logging.logDebug("<<< Import.MainComponent.updateSelectedWizardComponent");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'selectComponent': function(anEvent) {
+ this.setSelectedComponent(anEvent.src().value);
+ this.nextButton().enable();
+ },
+
+ 'selectedComponent': function() {
+ return this._selectedComponent;
+ },
+
+ 'setSelectedComponent': function(aValue) {
+ this._selectedComponent = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'backAction': function() {
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'nextAction': function() {
+ this.updateSelectedImportWizardComponent(this.selectedComponent());
+ },
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+});
+
diff --git a/frontend/beta/js/Clipperz/PM/Components/Import/PasswordPlusImportComponent.js b/frontend/beta/js/Clipperz/PM/Components/Import/PasswordPlusImportComponent.js
new file mode 100644
index 0000000..f476ac2
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Components/Import/PasswordPlusImportComponent.js
@@ -0,0 +1,315 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
+if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
+if (typeof(Clipperz.PM.Components) == 'undefined') { Clipperz.PM.Components = {}; }
+if (typeof(Clipperz.PM.Components.Import) == 'undefined') { Clipperz.PM.Components.Import = {}; }
+
+//#############################################################################
+
+Clipperz.PM.Components.Import.PasswordPlusImportComponent = function(anElement, args) {
+ args = args || {};
+
+ Clipperz.PM.Components.Import.PasswordPlusImportComponent.superclass.constructor.call(this, anElement, args);
+
+ this.render();
+
+ return this;
+}
+
+//=============================================================================
+
+YAHOO.extendX(Clipperz.PM.Components.Import.PasswordPlusImportComponent, Clipperz.PM.Components.Import.GenericImportComponent, {
+
+ 'toString': function() {
+ return "Clipperz.PM.Components.Import.PasswordPlusImportComponent component";
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'render': function() {
+//MochiKit.Logging.logDebug(">>> Import.PasswordPlusImportComponent.render");
+ this.domHelper().append(this.element(), {tag:'div', cls:'passwordPlusImportWizard', children:[
+ {tag:'h3', htmlString:Clipperz.PM.Strings['PasswordPlus_ImportWizard_Title']},
+ {tag:'div', cls:'importSteps', id:this.getId('importSteps')},
+ {tag:'div', cls:'importStepBlocks', children:[
+ {tag:'div', cls:'step_0', id:this.getId('step_0'), children:[
+ {tag:'div', children:[
+ {tag:'div', cls:'importOptionsDescription', htmlString:Clipperz.PM.Strings['importOptions_passwordPlus_description']},
+ {tag:'div', cls:'importOptionsParameters', children:[]},
+ this.textAreaConfig()
+ ]}
+ ]},
+ {tag:'div', cls:'step_1', id:this.getId('step_1'), children:[
+ {tag:'div', children:[
+ {tag:'div', id:this.getId('previewDiv'), html:"preview"}
+ ]}
+ ]},
+ {tag:'div', cls:'step_2', id:this.getId('step_2'), children:[
+ {tag:'div', children:[
+ {tag:'h4', html:"done"}
+ ]}
+ ]}
+ ]},
+ {tag:'div', cls:'importOptionsButtons', children:[
+ {tag:'table', children:[
+ {tag:'tbody', children:[
+ {tag:'tr', children:[
+ {tag:'td', html:'&nbsp;'},
+ {tag:'td', children:[
+ {tag:'div', id:this.getId('backActionButton')}
+ ]},
+ {tag:'td', html:'&nbsp;'},
+ {tag:'td', children:[
+ {tag:'div', id:this.getId('nextActionButton')}
+ ]},
+ {tag:'td', html:'&nbsp;'}
+ ]}
+ ]}
+ ]}
+ ]}
+ ]});
+
+ this.updateSteps();
+
+ this.setBackButton(new YAHOO.ext.Button(this.getDom('backActionButton'), {text:"back", handler:this.backAction, scope:this}));
+ this.setNextButton(new YAHOO.ext.Button(this.getDom('nextActionButton'), {text:"next", handler:this.nextAction, scope:this}));
+
+ this.getElement('step_0').setVisibilityMode(YAHOO.ext.Element.DISPLAY).show()
+ this.getElement('step_1').setVisibilityMode(YAHOO.ext.Element.DISPLAY).hide();
+ this.getElement('step_2').setVisibilityMode(YAHOO.ext.Element.DISPLAY).hide();
+//MochiKit.Logging.logDebug("<<< Import.PasswordPlusImportComponent.render");
+ },
+
+ //-------------------------------------------------------------------------
+/*
+ 'backAction': function() {
+ switch (this.currentStep()) {
+ case 1: // -> 0
+ this.backButton().disable();
+ this.getElement('step_1').hide();
+ this.setCurrentStep(0);
+ this.getElement('step_0').show();
+ break;
+ }
+ },
+*/
+ //-------------------------------------------------------------------------
+
+ 'nextAction': function() {
+ switch (this.currentStep()) {
+ case 0: // -> 1
+ this.previewValues();
+ break;
+ case 1: // -> 2
+ this.importValues();
+ break;
+ }
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'deferredPreviewValues': function() {
+ var deferredResult;
+
+// this.setFormValues(MochiKit.DOM.formContents(this.getDom('dataForm')));
+
+ deferredResult = new MochiKit.Async.Deferred();
+ deferredResult.addCallback(MochiKit.Base.bind(function(res) {
+ this.startProcessing();
+
+ return res;
+ }, this));
+ deferredResult.addCallback(MochiKit.Base.method(this, 'processPasswordPlusValues'));
+ deferredResult.addCallback(MochiKit.Base.method(this, 'setProcessedValues'));
+ deferredResult.addCallback(MochiKit.Base.method(this, 'previewRecordValues'));
+ deferredResult.addCallback(MochiKit.Base.bind(function(res) {
+ this.processingDone();
+ this.getElement('step_0').hide();
+ this.getElement('step_1').show();
+ this.backButton().enable();
+
+ return res;
+ }, this));
+// deferredResult.addErrback(MochiKit.Base.bind(function() {
+// this.processingAborted();
+// }, this))
+ deferredResult.callback(this.textAreaContent());
+
+ return deferredResult;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'processPasswordPlusValues': function(someData) {
+ var deferredResult;
+ var csvProcessor;
+
+ csvProcessor = new Clipperz.CSVProcessor({binary:true});
+
+ deferredResult = new MochiKit.Async.Deferred();
+ deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', 'parseImportData');
+ deferredResult.addCallback(function(res) {
+ return Clipperz.NotificationCenter.deferredNotification(this, 'updatedProgressState', {steps:(res.length * 2)}, res);
+ })
+ deferredResult.addCallback(MochiKit.Base.method(csvProcessor, 'deferredParse'));
+ deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', 'previewImportData');
+ deferredResult.addCallback(function(res) {
+ return Clipperz.NotificationCenter.deferredNotification(this, 'updatedProgressState', {steps:(res.length * 2), step:res.length}, res);
+ })
+ deferredResult.addCallback(MochiKit.Base.bind(function(someCSVValues) {
+ var innerDeferredResult;
+ var records;
+ var i,c;
+
+ innerDeferredResult = new MochiKit.Async.Deferred();
+ records = [];
+
+ c = someCSVValues.length;
+ i=0;
+ i++; // Dataviz Passwords Plus Export, Version,1, Minimum Version To Read,1
+ i++; // Is Template,Title,Category,Field 1 Label,Field 1 Value,Field 1 Hidden,Field 2 Label,Field 2 Value,Field 2 Hidden,Field 3 Label,Field 3 Value,Field 3 Hidden,Field 4 Label,Field 4 Value,Field 4 Hidden,Field 5 Label,Field 5 Value,Field 5 Hidden,Field 6 Label,Field 6 Value,Field 6 Hidden,Field 7 Label,Field 7 Value,Field 7 Hidden,Field 8 Label,Field 8 Value,Field 8 Hidden,Field 9 Label,Field 9 Value,Field 9 Hidden,Field 10 Label,Field 10 Value,Field 10 Hidden,Note
+
+ for( ; i<c; i++) {
+ innerDeferredResult.addCallback(MochiKit.Async.wait, 0.2);
+ innerDeferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', {});
+ innerDeferredResult.addCallback(MochiKit.Base.bind(function(someRecords, someData) {
+ if (someData[0] == '0') {
+ var record;
+ var recordVersion;
+ var ii, cc;
+
+ record = new Clipperz.PM.DataModel.Record({user:this.user()});
+ if (someData[1] != "") {
+ record.setLabel(someData[1]);
+ } else {
+ record.setLabel("imported record [" + (i+1) + "]");
+ }
+ record.setNotes(someData[33]);
+ recordVersion = record.currentVersion()
+
+ cc = 10;
+ for (ii=0; ii<cc; ii++) {
+ var currentFieldValueIndex;
+ var currentType;
+
+ currentFieldValueIndex = (ii * 3) + 4;
+
+ if (someData[currentFieldValueIndex] != "") {
+ var recordField;
+ var recordFieldType;
+
+ recordFieldType = 'TXT';
+ if (someData[currentFieldValueIndex + 1] == 1) {
+ recordFieldType = 'PWD';
+ } else if (/^http/.test(someData[currentFieldValueIndex])) {
+ recordFieldType = 'URL';
+ }
+
+ recordField = new Clipperz.PM.DataModel.RecordField({
+ recordVersion: recordVersion,
+ label: someData[currentFieldValueIndex - 1],
+ value: someData[currentFieldValueIndex],
+ type: recordFieldType
+ });
+ recordVersion.addField(recordField);
+ }
+ }
+
+ // this.user().addRecord(record, true);
+
+ someRecords.push(record);
+ }
+
+ return someRecords;
+ }, this), records, someCSVValues[i]);
+ }
+ innerDeferredResult.addCallback(MochiKit.Async.succeed, records);
+ innerDeferredResult.callback();
+
+ return innerDeferredResult;
+ }, this));
+ deferredResult.callback(someData);
+
+ return deferredResult;
+
+/*
+0 Is Template
+1 Title
+2 Category
+
+3 Field 1 Label
+4 Field 1 Value
+5 Field 1 Hidden
+
+6 Field 2 Label
+7 Field 2 Value
+8 Field 2 Hidden
+
+9 Field 3 Label
+10 Field 3 Value
+11 Field 3 Hidden
+
+12 Field 4 Label
+13 Field 4 Value
+14 Field 4 Hidden
+
+15 Field 5 Label
+16 Field 5 Value
+17 Field 5 Hidden
+
+18 Field 6 Label
+19 Field 6 Value
+20 Field 6 Hidden
+
+21 Field 7 Label
+22 Field 7 Value
+23 Field 7 Hidden
+
+24 Field 8 Label
+25 Field 8 Value
+26 Field 8 Hidden
+
+27 Field 9 Label
+28 Field 9 Value
+29 Field 9 Hidden
+
+30 Field 10 Label
+31 Field 10 Value
+32 Field 10 Hidden
+
+33 Note
+*/
+ },
+
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+});
+
diff --git a/frontend/beta/js/Clipperz/PM/Components/Import/RoboFormImportComponent.js b/frontend/beta/js/Clipperz/PM/Components/Import/RoboFormImportComponent.js
new file mode 100644
index 0000000..d35bdc6
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Components/Import/RoboFormImportComponent.js
@@ -0,0 +1,392 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
+if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
+if (typeof(Clipperz.PM.Components) == 'undefined') { Clipperz.PM.Components = {}; }
+if (typeof(Clipperz.PM.Components.Import) == 'undefined') { Clipperz.PM.Components.Import = {}; }
+
+//#############################################################################
+
+Clipperz.PM.Components.Import.RoboFormImportComponent = function(anElement, args) {
+ args = args || {};
+
+ Clipperz.PM.Components.Import.RoboFormImportComponent.superclass.constructor.call(this, anElement, args);
+
+ this.render();
+
+ return this;
+}
+
+//=============================================================================
+
+YAHOO.extendX(Clipperz.PM.Components.Import.RoboFormImportComponent, Clipperz.PM.Components.Import.GenericImportComponent, {
+
+ 'toString': function() {
+ return "Clipperz.PM.Components.Import.RoboFormImportComponent component";
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'render': function() {
+//MochiKit.Logging.logDebug(">>> Import.RoboFormImportComponent.render");
+ this.domHelper().append(this.element(), {tag:'div', cls:'roboFormImportWizard', children:[
+ {tag:'h3', htmlString:Clipperz.PM.Strings['RoboForm_ImportWizard_Title']},
+ {tag:'div', cls:'importSteps', id:this.getId('importSteps')},
+ {tag:'div', cls:'importStepBlocks', children:[
+ {tag:'div', cls:'step_0', id:this.getId('step_0'), children:[
+ {tag:'div', children:[
+ {tag:'div', cls:'importOptionsDescription', htmlString:Clipperz.PM.Strings['importOptions_roboForm_description']},
+ {tag:'div', cls:'importOptionsParameters', children:[]},
+ this.textAreaConfig()
+ ]}
+ ]},
+ {tag:'div', cls:'step_1', id:this.getId('step_1'), children:[
+ {tag:'div', children:[
+ {tag:'div', id:this.getId('previewDiv'), html:"preview"}
+ ]}
+ ]},
+ {tag:'div', cls:'step_2', id:this.getId('step_2'), children:[
+ {tag:'div', children:[
+ {tag:'h4', html:"done"}
+ ]}
+ ]}
+ ]},
+ {tag:'div', cls:'importOptionsButtons', children:[
+ {tag:'table', children:[
+ {tag:'tbody', children:[
+ {tag:'tr', children:[
+ {tag:'td', html:'&nbsp;'},
+ {tag:'td', children:[
+ {tag:'div', id:this.getId('backActionButton')}
+ ]},
+ {tag:'td', html:'&nbsp;'},
+ {tag:'td', children:[
+ {tag:'div', id:this.getId('nextActionButton')}
+ ]},
+ {tag:'td', html:'&nbsp;'}
+ ]}
+ ]}
+ ]}
+ ]}
+ ]});
+
+ this.updateSteps();
+
+ this.setBackButton(new YAHOO.ext.Button(this.getDom('backActionButton'), {text:"back", handler:this.backAction, scope:this}));
+ this.setNextButton(new YAHOO.ext.Button(this.getDom('nextActionButton'), {text:"next", handler:this.nextAction, scope:this}));
+
+ this.getElement('step_0').setVisibilityMode(YAHOO.ext.Element.DISPLAY).show()
+ this.getElement('step_1').setVisibilityMode(YAHOO.ext.Element.DISPLAY).hide();
+ this.getElement('step_2').setVisibilityMode(YAHOO.ext.Element.DISPLAY).hide();
+//MochiKit.Logging.logDebug("<<< Import.RoboFormImportComponent.render");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'nextAction': function() {
+ switch (this.currentStep()) {
+ case 0: // -> 1
+ this.previewValues();
+ break;
+ case 1: // -> 2
+ this.importValues();
+ break;
+ }
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'deferredPreviewValues': function() {
+ var deferredResult;
+
+// this.setFormValues(MochiKit.DOM.formContents(this.getDom('dataForm')));
+
+ deferredResult = new MochiKit.Async.Deferred();
+ deferredResult.addCallback(MochiKit.Base.bind(function(res) {
+ this.startProcessing();
+
+ return res;
+ }, this));
+ deferredResult.addCallback(MochiKit.Base.method(this, 'processRoboFormValues'));
+ deferredResult.addCallback(MochiKit.Base.method(this, 'setProcessedValues'));
+ deferredResult.addCallback(MochiKit.Base.method(this, 'previewRecordValues'));
+ deferredResult.addCallback(MochiKit.Base.bind(function(res) {
+ this.processingDone();
+ this.getElement('step_0').hide();
+ this.getElement('step_1').show();
+ this.backButton().enable();
+
+ return res;
+ }, this));
+// deferredResult.addErrback(MochiKit.Base.bind(function() {
+// this.processingAborted();
+// }, this))
+ deferredResult.callback(this.textAreaContent());
+
+ return deferredResult;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'processRoboFormValues': function(someData) {
+ var result;
+
+ if (someData.match(/^\<HTML\>\<HEAD\>\<TITLE\>RoboForm Passcards List /g)) {
+ result = this.processRoboFormPasscardsValues(someData);
+ } else if (someData.match(/\<HTML\>\<HEAD\>\<TITLE\>RoboForm Safenotes List /g)) {
+ result = this.processRoboFormSafenotesValues(someData);
+ }
+
+ return result;
+ },
+
+ //.........................................................................
+
+ 'processRoboFormPasscardsValues': function(someData) {
+ var deferredResult;
+
+ deferredResult = new MochiKit.Async.Deferred();
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("RoboFormImportComponent.processRoboFormValues - 1: "/* + res*/); return res;});
+ deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', 'parseImportData');
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("RoboFormImportComponent.processRoboFormValues - 2: "/* + res*/); return res;});
+ deferredResult.addCallback(function(someData) {
+ var result;
+ var data;
+
+ data = someData.replace(/\r?\n/g, "");
+ result = data.match(/\<TABLE width\=\"100\%\"\>.*?\<\/TABLE\>/g);
+
+ return result;
+ });
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("RoboFormImportComponent.processRoboFormValues - 3: "/* + res*/); return res;});
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("RoboFormImportComponent.processRoboFormValues - 3.1: " + res.length); return res;});
+ deferredResult.addCallback(function(res) {
+ return Clipperz.NotificationCenter.deferredNotification(this, 'updatedProgressState', {steps:(res.length)}, res);
+ })
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("RoboFormImportComponent.processRoboFormValues - 4: "/* + res*/); return res;});
+ deferredResult.addCallback(MochiKit.Base.bind(function(someRecordValues) {
+ var innerDeferredResult;
+ var records;
+ var i,c;
+
+ innerDeferredResult = new MochiKit.Async.Deferred();
+ records = [];
+
+ c = someRecordValues.length;
+ for(i=0; i<c; i++) {
+//innerDeferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("RoboFormImportComponent.processRoboFormValues __inner loop__ - 1: " + res); return res;});
+ innerDeferredResult.addCallback(MochiKit.Async.wait, 0.2);
+//innerDeferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("RoboFormImportComponent.processRoboFormValues __inner loop__ - 2: " + res); return res;});
+ innerDeferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', {});
+//innerDeferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("RoboFormImportComponent.processRoboFormValues __inner loop__ - 3: " + res); return res;});
+ innerDeferredResult.addCallback(MochiKit.Base.bind(function(someRecords, someData) {
+ var data;
+ var record;
+ var recordVersion;
+ var fields;
+ var ii, cc;
+ var hasNotes;
+
+ var caption;
+ var subcaption;
+
+//MochiKit.Logging.logDebug("data: " + someData);
+ data = someData.replace(/\<WBR\>/g, "");
+ hasNotes = false;
+
+ /\<TD class\=caption colSpan\=3\>(.*?)\<\/TD\>/.test(data); // <TD class=caption colSpan=3>110mb</TD>
+ caption = RegExp.$1;
+//MochiKit.Logging.logDebug("caption: " + caption);
+
+ /\<TD class\=subcaption colSpan\=3\>(.*?)\<\/TD\>/.test(data); // <TD class=subcaption colSpan=3>110<WBR>mb.com</TD>
+ subcaption = RegExp.$1;
+//MochiKit.Logging.logDebug("subcaption: " + subcaption);
+
+ record = new Clipperz.PM.DataModel.Record({user:this.user()});
+ recordVersion = record.currentVersion()
+
+ record.setLabel(caption);
+// record.setNotes(subcaption);
+ if (subcaption != null) {
+ var recordField;
+
+ recordField = new Clipperz.PM.DataModel.RecordField({
+ recordVersion: recordVersion,
+ label: "url",
+ value: subcaption,
+ type: 'URL'
+ });
+ recordVersion.addField(recordField);
+ }
+
+ fields = data.match(/\<TR\>.*?\<\/TR\>/g) || [];
+ cc = fields.length;
+//MochiKit.Logging.logDebug("fields.length: " + cc);
+ for (ii=0; ii<cc; ii++) {
+ var recordField;
+ var fieldString;
+ var fieldName;
+ var fieldValue;
+
+//MochiKit.Logging.logDebug("fieldString: " + fields[ii]);
+ fieldString = fields[ii];
+//MochiKit.Logging.logDebug("fieldString (cleaned): " + fieldString);
+ /\<TD class\=field vAlign\=top align\=left width\=\"40\%\"\>(.*?)\<\/TD\>/.test(fieldString);
+ fieldName = RegExp.$1;
+
+ /\<TD class\=wordbreakfield vAlign\=top align\=left width\=\"55\%\"\>(.*?)\<\/TD\>/.test(fieldString);
+ fieldValue = RegExp.$1;
+
+ if (fieldName == "Note$") {
+ record.setNotes(fieldValue);
+ hasNotes = true;
+ } else {
+ var fieldType;
+
+ if (((ii == 1) && (hasNotes == false)) || ((ii == 2) && (hasNotes == true))) {
+ fieldType = 'PWD';
+ } else {
+ fieldType = 'TXT';
+ }
+
+ recordField = new Clipperz.PM.DataModel.RecordField({
+ recordVersion: recordVersion,
+ label: fieldName,
+ value: fieldValue,
+ type: fieldType
+ });
+ recordVersion.addField(recordField);
+ }
+ }
+
+ someRecords.push(record);
+
+ return someRecords;
+ }, this), records, someRecordValues[i]);
+ }
+//innerDeferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("RoboFormImportComponent.processRoboFormValues __inner loop__ - 4: " + res); return res;});
+ innerDeferredResult.addCallback(MochiKit.Async.succeed, records);
+//innerDeferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("RoboFormImportComponent.processRoboFormValues __inner loop__ - 5: " + res); return res;});
+ innerDeferredResult.callback();
+
+ return innerDeferredResult;
+ }, this));
+ deferredResult.callback(someData);
+
+ return deferredResult;
+ },
+
+
+ //.........................................................................
+
+ 'processRoboFormSafenotesValues': function(someData) {
+ var deferredResult;
+
+ deferredResult = new MochiKit.Async.Deferred();
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("RoboFormImportComponent.processRoboFormValues - 1: "/* + res*/); return res;});
+ deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', 'parseImportData');
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("RoboFormImportComponent.processRoboFormValues - 2: "/* + res*/); return res;});
+ deferredResult.addCallback(function(someData) {
+ var result;
+ var data;
+
+ data = someData.replace(/\r?\n/g, "");
+ result = data.match(/\<TABLE width\=\"100\%\"\>.*?\<\/TABLE\>/g);
+
+ return result;
+ });
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("RoboFormImportComponent.processRoboFormValues - 3: "/* + res*/); return res;});
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("RoboFormImportComponent.processRoboFormValues - 3.1: " + res.length); return res;});
+ deferredResult.addCallback(function(res) {
+ return Clipperz.NotificationCenter.deferredNotification(this, 'updatedProgressState', {steps:(res.length)}, res);
+ })
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("RoboFormImportComponent.processRoboFormValues - 4: "/* + res*/); return res;});
+ deferredResult.addCallback(MochiKit.Base.bind(function(someRecordValues) {
+ var innerDeferredResult;
+ var records;
+ var i,c;
+
+ innerDeferredResult = new MochiKit.Async.Deferred();
+ records = [];
+
+ c = someRecordValues.length;
+ for(i=0; i<c; i++) {
+//innerDeferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("RoboFormImportComponent.processRoboFormValues __inner loop__ - 1: " + res); return res;});
+ innerDeferredResult.addCallback(MochiKit.Async.wait, 0.2);
+//innerDeferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("RoboFormImportComponent.processRoboFormValues __inner loop__ - 2: " + res); return res;});
+ innerDeferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', {});
+//innerDeferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("RoboFormImportComponent.processRoboFormValues __inner loop__ - 3: " + res); return res;});
+ innerDeferredResult.addCallback(MochiKit.Base.bind(function(someRecords, someData) {
+ var data;
+ var record;
+ var recordVersion;
+
+ var caption;
+ var wordbreakfield;
+
+//MochiKit.Logging.logDebug("data: " + someData);
+ data = someData.replace(/\<WBR\>/g, "");
+ hasNotes = false;
+
+ /\<TD class\=caption colSpan\=3\>(.*?)\<\/TD\>/.test(data); // <TD class=caption colSpan=3>110mb</TD>
+ caption = RegExp.$1;
+//MochiKit.Logging.logDebug("caption: " + caption);
+
+ /\<TD class\=wordbreakfield vAlign=top align\=left width\=\"\1\0\0\%\"\>(.*?)\<\/TD\>/.test(data); // <TD class=wordbreakfield vAlign=top align=left width="100%">7759500</TD>
+ wordbreakfield = RegExp.$1;
+//MochiKit.Logging.logDebug("subcaption: " + subcaption);
+
+ record = new Clipperz.PM.DataModel.Record({user:this.user()});
+ recordVersion = record.currentVersion()
+
+ record.setLabel(caption);
+ record.setNotes(wordbreakfield);
+
+ someRecords.push(record);
+
+ return someRecords;
+ }, this), records, someRecordValues[i]);
+ }
+//innerDeferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("RoboFormImportComponent.processRoboFormValues __inner loop__ - 4: " + res); return res;});
+ innerDeferredResult.addCallback(MochiKit.Async.succeed, records);
+//innerDeferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("RoboFormImportComponent.processRoboFormValues __inner loop__ - 5: " + res); return res;});
+ innerDeferredResult.callback();
+
+ return innerDeferredResult;
+ }, this));
+ deferredResult.callback(someData);
+
+ return deferredResult;
+ },
+
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+});
+
diff --git a/frontend/beta/js/Clipperz/PM/Components/MessageBox.js b/frontend/beta/js/Clipperz/PM/Components/MessageBox.js
new file mode 100644
index 0000000..d2bc09a
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Components/MessageBox.js
@@ -0,0 +1,224 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
+if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
+if (typeof(Clipperz.PM.Components) == 'undefined') { Clipperz.PM.Components = {}; }
+
+
+
+Clipperz.PM.Components.MessageBoxImplementation = function() {
+ this._step = 0;
+ this._steps = 0;
+
+ return this;
+};
+
+//YAHOO.extendX(Clipperz.PM.Components.MessageBoxImplementation, Clipperz.PM.Components.BaseComponent, {
+Clipperz.PM.Components.MessageBoxImplementation.prototype = MochiKit.Base.update(null, {
+
+ 'toString': function() {
+ return "Clipperz.PM.Components.MessageBox";
+ },
+
+ //-----------------------------------------------------
+
+ 'step': function() {
+ return this._step;
+ },
+
+ 'setStep': function(aValue) {
+ if (aValue == 'next') {
+ this._step = this._step + 1;
+ } else {
+ this._step = aValue;
+ }
+
+ if (this._step > this.steps()) {
+//MochiKit.Logging.logDebug("overstepping: " + this._step + " (" + this.steps() + ")");
+ this._step = this.steps();
+ }
+ },
+
+ //-----------------------------------------------------
+
+ 'steps': function() {
+ return this._steps;
+ },
+
+ 'setSteps': function(aValue) {
+ if (aValue.constructor == String) {
+ if (aValue.charAt(0) == '+') {
+ this._steps += aValue.substring(1)*1;
+ } else if (aValue.charAt(0) == '-') {
+ this._steps -= aValue.substring(1)*1;
+ } else {
+ this._steps = aValue.substring(1)*1;
+ }
+ } else {
+ this._steps = aValue;
+ }
+ },
+
+ //-----------------------------------------------------
+
+ 'deferredShow': function(aConfiguration, anAnimationTargetElement, aValue) {
+ this.show(aConfiguration, anAnimationTargetElement);
+
+ return aValue;
+ },
+
+ 'show': function(aConfiguration, anAnimationTargetElement) {
+ var messageBoxConfiguration;
+
+ messageBoxConfiguration = MochiKit.Base.clone(aConfiguration);
+ messageBoxConfiguration.msg = messageBoxConfiguration.text;
+ messageBoxConfiguration.animEl = anAnimationTargetElement;
+ messageBoxConfiguration.progress = messageBoxConfiguration.showProgressBar;
+ messageBoxConfiguration.closable = messageBoxConfiguration.showCloseButton;
+ this.setSteps(aConfiguration.steps || 0);
+ this.setStep(aConfiguration.step || 0);
+ delete messageBoxConfiguration.buttons;
+
+ Clipperz.YUI.MessageBox.show(messageBoxConfiguration);
+ },
+
+ //-----------------------------------------------------
+
+ 'update': function(someValues) {
+//MochiKit.Logging.logDebug(">>> MessageBox.update");
+ if (someValues.title) {
+ Clipperz.YUI.MessageBox.getDialog().setTitle(someValues.title);
+ };
+
+ if (someValues.text) {
+ Clipperz.YUI.MessageBox.updateText(someValues.text);
+ };
+
+ if (typeof(someValues.showProgressBar) != 'undefined') {
+ Clipperz.YUI.MessageBox.progressElement().setDisplayed(someValues.showProgressBar);
+ Clipperz.YUI.MessageBox.updateProgress(0);
+ };
+
+ if (typeof(someValues.steps) != 'undefined') {
+ this.setSteps(someValues.steps);
+ };
+
+ if (typeof(someValues.step) != 'undefined') {
+ this.setStep(someValues.step);
+ } else {
+ this.setStep('next');
+ }
+ Clipperz.YUI.MessageBox.updateProgress(this.step() / this.steps());
+
+
+ if (typeof(someValues.fn) != 'undefined') {
+ Clipperz.YUI.MessageBox.opt().fn = someValues.fn;
+ };
+
+ if (typeof(someValues.scope) != 'undefined') {
+ Clipperz.YUI.MessageBox.opt().scope = someValues.scope;
+ };
+
+ if (someValues.buttons) {
+ Clipperz.YUI.MessageBox.updateButtons(someValues.buttons);
+ };
+
+// if (someValues.title) {
+// Clipperz.YUI.MessageBox.getDialog().setTitle(someValues.title + " [" + this.step() + " / " + this.steps() + "]");
+// };
+
+//MochiKit.Logging.logDebug("--- MessageBox.update - step: " + this.step() + " / " + this.steps() + " - " + someValues.text);
+//MochiKit.Logging.logDebug("<<< MessageBox.update");
+ },
+
+ //-----------------------------------------------------
+
+ 'hide': function(anAnimationTargetElement) {
+ if (anAnimationTargetElement) {
+ Clipperz.YUI.MessageBox.getDialog().animateTarget = anAnimationTargetElement;
+ }
+
+ Clipperz.YUI.MessageBox.hide();
+ },
+
+ //-----------------------------------------------------
+ __syntaxFix__: '__syntaxFix__'
+});
+
+
+//##########################################################
+
+_clipperz_pm_components_messageBox = null;
+
+Clipperz.PM.Components.MessageBox = function() {
+ if (_clipperz_pm_components_messageBox == null) {
+ _clipperz_pm_components_messageBox = new Clipperz.PM.Components.MessageBoxImplementation();
+ }
+
+ return _clipperz_pm_components_messageBox;
+}
+
+//---------------------------------------------------------
+
+Clipperz.PM.Components.MessageBox.showProgressPanel = function(aCallback, anErrback, anActivationItem) {
+ var deferredResult;
+
+ deferredResult = new MochiKit.Async.Deferred();
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Clipperz.PM.Components.MessageBox.showProgressPanel - 0: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(Clipperz.PM.Components.MessageBox(), 'deferredShow'),
+ {
+ title: "",
+ text: "",
+ width:240,
+ showProgressBar:true,
+ showCloseButton:false,
+ fn:MochiKit.Base.method(deferredResult, 'cancel'),
+ scope:this,
+ buttons:{
+ // 'ok':Clipperz.PM.Strings['loginMessagePanelInitialButtonLabel']
+ }
+ },
+ anActivationItem
+ );
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Clipperz.PM.Components.MessageBox.showProgressPanel - 1: " + res); return res;});
+ deferredResult.addCallback(aCallback);
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Clipperz.PM.Components.MessageBox.showProgressPanel - 2: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Async.wait, 0.5);
+ deferredResult.addCallback(function(res) {
+ Clipperz.PM.Components.MessageBox().hide(YAHOO.ext.Element.get(anActivationItem));
+ return res;
+ });
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Clipperz.PM.Components.MessageBox.showProgressPanel - 3: " + res); return res;});
+ deferredResult.addErrback(anErrback);
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Clipperz.PM.Components.MessageBox.showProgressPanel - 4: " + res); return res;});
+ deferredResult.callback();
+
+ return deferredResult;
+};
+
diff --git a/frontend/beta/js/Clipperz/PM/Components/OTP/MainComponent.js b/frontend/beta/js/Clipperz/PM/Components/OTP/MainComponent.js
new file mode 100644
index 0000000..9d191f6
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Components/OTP/MainComponent.js
@@ -0,0 +1,490 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
+if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
+if (typeof(Clipperz.PM.Components) == 'undefined') { Clipperz.PM.Components = {}; }
+if (typeof(Clipperz.PM.Components.OTP) == 'undefined') { Clipperz.PM.Components.OTP = {}; }
+
+//#############################################################################
+
+Clipperz.PM.Components.OTP.MainComponent = function(anElement, args) {
+ args = args || {};
+
+//MochiKit.Logging.logDebug("new OTP.MainComponent");
+ Clipperz.PM.Components.OTP.MainComponent.superclass.constructor.call(this, anElement, args);
+
+ this._user = args.user;
+ this._shouldRender = true;
+
+ this._deleteButton = null;
+ this._printButton = null;
+
+ Clipperz.NotificationCenter.register(null, 'tabSelected', this, 'tabSelectedHandler');
+// Clipperz.NotificationCenter.register(null, 'oneTimePasswordAdded', this, 'render');
+
+ return this;
+}
+
+//=============================================================================
+
+YAHOO.extendX(Clipperz.PM.Components.OTP.MainComponent, Clipperz.PM.Components.BaseComponent, {
+
+ 'toString': function() {
+ return "Clipperz.PM.Components.OTP.MainComponent component";
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'render': function() {
+//MochiKit.Logging.logDebug("### OTP.MainComponent.render");
+ Clipperz.NotificationCenter.unregister(this);
+ MochiKit.Signal.disconnectAllTo(this);
+
+ if (Clipperz.PM.Proxy.defaultProxy.isReadOnly()) {
+ this.element().update("");
+ this.domHelper().append(this.element(), {tag:'div', cls:'oneTimePasswordReadOnlyMessage', htmlString:Clipperz.PM.Strings['oneTimePasswordReadOnlyMessage']});
+ } else {
+ var deferredResult;
+
+ deferredResult = new MochiKit.Async.Deferred();
+
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("OTP.MainComponent.render - 1: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.bind(function() {
+ this.element().update("");
+ Clipperz.YUI.DomHelper.append(this.element(), {tag:'div', htmlString:Clipperz.PM.Strings['oneTimePasswordLoadingMessage']});
+ }, this));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("OTP.MainComponent.render - 2: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(this.user(), 'loadOneTimePasswords'));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("OTP.MainComponent.render - 3: " + res); return res;});
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("OTP.MainComponent.render - 3.1: " + Clipperz.Base.serializeJSON(res.serializedData())); return res;});
+ deferredResult.addCallback(MochiKit.Base.bind(function(aResult) {
+ var tbodyElement;
+ var oneTimePasswordReferenceKeys;
+ var imageExtension;
+ var isThereAnyActiveOneTimePassword;
+
+ isThereAnyActiveOneTimePassword = false;
+
+ this.element().update("");
+ Clipperz.YUI.DomHelper.append(this.element(), {tag:'div', id:'oneTimePasswordList', children:[
+ {tag:'div', id:'oneTimePasswords_header', children:[
+ {tag:'table', width:'100%', children:[
+ {tag:'tbody', children:[
+ {tag:'tr', children:[
+ {tag:'td', width:'10%', children:[
+ {tag:'div', id:this.getId('createNewOneTimePasswordButton')}
+ ]},
+ {tag:'td', width:'40%', children:[
+ {tag:'div', id:this.getId('deleteSelectedOneTimePasswordButton')}
+ ]},
+ {tag:'td', width:'50%', align:'right', children:[
+ {tag:'div', id:this.getId('printOneTimePasswordButton')}
+ ]}
+ ]}
+ ]}
+ ]},
+ {tag:'div', children:[
+ {tag:'ul', children:[
+ {tag:'li', children:[
+ {tag:'span', htmlString:Clipperz.PM.Strings['oneTimePasswordSelectionLink_selectLabel']}
+ ]},
+ {tag:'li', children:[
+ {tag:'a', href:'#', id:this.getId('selectAllOneTimePasswords_link'), htmlString:Clipperz.PM.Strings['oneTimePasswordSelectionLink_all']}
+ ]},
+ {tag:'li', children:[
+ {tag:'a', href:'#', id:this.getId('selectNoneOneTimePasswords_link'), htmlString:Clipperz.PM.Strings['oneTimePasswordSelectionLink_none']}
+ ]},
+ {tag:'li', children:[
+ {tag:'a', href:'#', id:this.getId('selectUsedOneTimePasswords_link'), htmlString:Clipperz.PM.Strings['oneTimePasswordSelectionLink_used']}
+ ]},
+ {tag:'li', children:[
+ {tag:'a', href:'#', id:this.getId('selectUnusedOneTimePasswords_link'), htmlString:Clipperz.PM.Strings['oneTimePasswordSelectionLink_unused']}
+ ]}
+ ]}
+ ]}
+ ]},
+ {tag:'form', id:this.getId('oneTimePasswords_form'), children:[
+ {tag:'table', cls:'oneTimePassword', cellspacing:'0', cellpadding:'2', children:[
+ {tag:'tbody', id:this.getId('oneTimePasswords_tbody'), children:[
+ ]}
+ ]}
+ ]}
+ ]});
+
+ imageExtension = (Clipperz_IEisBroken == true) ? 'gif': 'png';
+
+ tbodyElement = this.getElement('oneTimePasswords_tbody');
+ oneTimePasswordReferenceKeys = MochiKit.Base.keys(this.user().oneTimePasswordManager().oneTimePasswords()).reverse();
+ c = oneTimePasswordReferenceKeys.length;
+ if (c>0) {
+ for (i=0; i<c; i++) {
+ var otpReference;
+ var currentOTP;
+ var loginSessionInfoConfig;
+
+ imageExtension = (Clipperz_IEisBroken == true) ? 'gif': 'png';
+
+ otpReference = oneTimePasswordReferenceKeys[i];
+ currentOTP = this.user().oneTimePasswordManager().oneTimePasswords()[otpReference];
+
+ switch (currentOTP.status()) {
+ case 'USED':
+ var loginSessionInfo;
+
+ loginSessionInfo = currentOTP.connectionInfo();
+ try {
+ var ip;
+
+ ip = (currentOTP.connectionInfo()['ip'].match(/^\d{1,3}(.\d{1,3}){3}$/)) ? currentOTP.connectionInfo()['ip'] : Clipperz.PM.Strings['unknown_ip'];
+
+ loginSessionInfoConfig = [
+ {tag:'div', cls:'oneTimePassword_usageDateDescription', children:[
+ {tag:'span', cls:'value', html:Clipperz.PM.Date.getElapsedTimeDescription(currentOTP.usageDate())}
+ ]},
+ {tag:'div', cls:'oneTimePassword_usageDetails', children:[
+ {tag:'img', cls:'flag', title:Clipperz.PM.Strings['countries'][ loginSessionInfo['country']], src:Clipperz.PM.Strings['icons_baseUrl'] + "/flags/" + loginSessionInfo['country'].toLowerCase() + "." + imageExtension, width:'32', height:'32'},
+ {tag:'img', cls:'browser', title:Clipperz.PM.Strings['browsers'][ loginSessionInfo['browser']], src:Clipperz.PM.Strings['icons_baseUrl'] + "/browsers/" + loginSessionInfo['browser'].toLowerCase() + "." + imageExtension, width:'32', height:'32'},
+ {tag:'img', cls:'operatingSystem', title:Clipperz.PM.Strings['operatingSystems'][loginSessionInfo['operatingSystem']], src:Clipperz.PM.Strings['icons_baseUrl'] + "/operatingSystems/" + loginSessionInfo['operatingSystem'].toLowerCase() + "." + imageExtension, width:'32', height:'32'}
+ ]},
+ {tag:'div', cls:'oneTimePassword_usageDate', html:Clipperz.PM.Date.formatDateWithTemplate(currentOTP.usageDate(), Clipperz.PM.Strings['fullDate_format'])},
+ {tag:'div', cls:'oneTimePassword_IP', children:[
+ {tag:'span', cls:'oneTimePassword_IPLabel', htmlString:Clipperz.PM.Strings['loginHistoryIPLabel']},
+ {tag:'span', cls:'oneTimePassword_IPValue', html:ip}
+ ]}
+ ];
+ } catch(exception) {
+ MochiKit.Logging.logWarning("an error occured while showing the One Time Password session details");
+ loginSessionInfoConfig = [];
+ }
+ break;
+ case 'DISABLED':
+ loginSessionInfoConfig = [
+ {tag:'span', cls:'disabledOneTimePassword', htmlString:Clipperz.PM.Strings['disabledOneTimePassword_warning']}
+ ];
+ break;
+ case 'ACTIVE':
+ default:
+ loginSessionInfoConfig = [];
+ break;
+ }
+
+
+ if (currentOTP.isExpired() == false) {
+ isThereAnyActiveOneTimePassword = true;
+ };
+
+
+ this.domHelper().append(tbodyElement, {tag:'tr', cls:(currentOTP.isExpired() ? 'oneTimePassword_used': 'oneTimePassword_new'), children:[
+ {tag:'td', valign:'top', children:[
+ {tag:'input', type:'checkbox', cls:'otpCheckbox', name:currentOTP.reference()}
+ ]},
+ {tag:'td', valign:'top', children:[
+ {tag:'span', cls:'oneTimePassword_value', html:currentOTP.password()}
+ ]},
+ {tag:'td', valign:'top', children:[
+ {tag:'div', cls:'oneTimePassword_usageStats', children:loginSessionInfoConfig}
+ ]}
+ ]});
+ }
+ } else {
+ this.domHelper().append(tbodyElement, {tag:'tr', children:[
+ {tag:'td', children:[
+ {tag:'div', cls:'oneTimePassword_noPasswordPresent', htmlString:Clipperz.PM.Strings['oneTimePasswordNoPasswordAvailable']}
+ ]}
+ ]});
+ }
+
+ new YAHOO.ext.Button(this.getDom('createNewOneTimePasswordButton'), {text:Clipperz.PM.Strings['createNewOTPButtonLabel'], handler:this.createNewOneTimePassword, scope:this});
+ this.setDeleteButton(new YAHOO.ext.Button(this.getDom('deleteSelectedOneTimePasswordButton'), {text:Clipperz.PM.Strings['deleteOTPButtonLabel'], handler:this.deleteSelectedOneTimePasswords, scope:this}));
+ this.setPrintButton(new YAHOO.ext.Button(this.getDom('printOneTimePasswordButton'), {text:Clipperz.PM.Strings['printOTPButtonLabel'], handler:this.printOneTimePasswords, scope:this}));
+
+ MochiKit.Signal.connect(this.getId('selectAllOneTimePasswords_link'), 'onclick', this, 'selectAllOneTimePasswords');
+ MochiKit.Signal.connect(this.getId('selectNoneOneTimePasswords_link'), 'onclick', this, 'selectNoneOneTimePasswords');
+ MochiKit.Signal.connect(this.getId('selectUsedOneTimePasswords_link'), 'onclick', this, 'selectUsedOneTimePasswords');
+ MochiKit.Signal.connect(this.getId('selectUnusedOneTimePasswords_link'),'onclick', this, 'selectUnusedOneTimePasswords');
+
+ MochiKit.Base.map(MochiKit.Base.bind(function(aCheckbox) {
+ MochiKit.Signal.connect(aCheckbox, 'onclick', this, 'handleCheckboxClick');
+ }, this), this.oneTimePasswordCheckboxes());
+
+ this.updateDeleteButtonStatus();
+
+ if (isThereAnyActiveOneTimePassword == true) {
+ this.printButton().enable();
+ } else {
+ this.printButton().disable();
+ }
+
+// Clipperz.NotificationCenter.register(null, 'oneTimePasswordAdded', this, 'render');
+ Clipperz.NotificationCenter.register(null, 'oneTimePassword_saveChanges_done', this, 'render');
+
+ }, this));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("OTP.MainComponent.render - 4: " + res); return res;});
+
+ deferredResult.callback();
+ }
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'printOneTimePasswords': function() {
+ var newWindow;
+ var activeOneTimePasswords;
+
+//MochiKit.Logging.logDebug(">>> printAllData");
+ newWindow = window.open("", "");
+ newWindow.document.write(
+"<html>" +
+"<header>" +
+" <title>Clipperz One Time Password</title>" +
+"<style>" +
+"div.oneTimePassword_print h2 {" +
+" font-family: monospace;" +
+" font-weight: normal;" +
+" padding: 10px 20px;" +
+"}" +
+"</style>" +
+"" +
+"<!--[if IE]>" +
+"<style>" +
+"</style>" +
+"<![endif]-->" +
+"" +
+"</header>" +
+"<body>" +
+"</body>" +
+"</html>"
+ );
+
+ activeOneTimePasswords = MochiKit.Base.filter(function(aOneTimePassword) {return (aOneTimePassword.isExpired() == false)}, MochiKit.Base.values(this.user().oneTimePasswordManager().oneTimePasswords()).reverse());
+
+ MochiKit.Iter.forEach(activeOneTimePasswords, MochiKit.Base.partial(function(aWindow, aOneTimePassword) {
+ MochiKit.DOM.withWindow(aWindow, MochiKit.Base.partial(function(aOneTimePassword) {
+ var newBlock;
+
+ newBlock = MochiKit.DOM.DIV({'class': 'oneTimePassword_print'},
+ MochiKit.DOM.H2(null, aOneTimePassword.password())
+ );
+ MochiKit.DOM.appendChildNodes(MochiKit.DOM.currentDocument().body, newBlock);
+
+ }, aOneTimePassword));
+ }, newWindow));
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'generateRandomBase32OTPValue': function(aButton) {
+ var randomValue;
+ var result;
+
+ randomValue = Clipperz.Crypto.PRNG.defaultRandomGenerator().getRandomBytes(160/8);
+ result = randomValue.toBase32String();
+ result = result.replace(/.{4}\B/g, '$&' + ' ');
+ result = result.replace(/(.{4} ){2}/g, '$&' + '- ');
+
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'createNewOneTimePassword': function() {
+ var newOneTimePassword;
+ var password;
+
+ password = this.generateRandomBase32OTPValue();
+ newOneTimePassword = new Clipperz.PM.DataModel.OneTimePassword({
+ user:this.user(),
+ password:password
+ });
+ this.user().oneTimePasswordManager().addOneTimePassword(newOneTimePassword);
+ Clipperz.PM.Components.MessageBox.showProgressPanel(MochiKit.Base.method(newOneTimePassword, 'saveChanges'), null, this.getDom('createNewOneTimePasswordButton'));
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'oneTimePasswordCheckboxes': function() {
+ return MochiKit.DOM.getElementsByTagAndClassName('input', 'otpCheckbox', this.getId('oneTimePasswords_tbody'));
+ },
+
+ 'checkedOneTimePasswordCheckboxes': function() {
+ return MochiKit.Base.filter(function(aCheckbox) {return (aCheckbox.checked == true)}, this.oneTimePasswordCheckboxes());
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'selectAllOneTimePasswords': function(anEvent) {
+ var checkboxes;
+ var i,c;
+
+ anEvent.stop();
+ checkboxes = this.oneTimePasswordCheckboxes();
+ c = checkboxes.length;
+ for (i=0; i<c; i++) {
+ checkboxes[i].checked = true;
+ }
+
+ this.updateDeleteButtonStatus();
+ },
+
+ 'selectNoneOneTimePasswords': function(anEvent) {
+ var checkboxes;
+ var i,c;
+
+ anEvent.stop();
+ checkboxes = this.oneTimePasswordCheckboxes();
+ c = checkboxes.length;
+ for (i=0; i<c; i++) {
+ checkboxes[i].checked = false;
+ }
+
+ this.updateDeleteButtonStatus();
+ },
+
+ 'selectUsedOneTimePasswords': function(anEvent) {
+ var checkboxes;
+ var oneTimePasswordManager;
+ var i,c;
+
+ anEvent.stop();
+ oneTimePasswordManager = this.user().oneTimePasswordManager();
+ checkboxes = this.oneTimePasswordCheckboxes();
+ c = checkboxes.length;
+ for (i=0; i<c; i++) {
+ var matchingOneTimePassword;
+
+ matchingOneTimePassword = oneTimePasswordManager.oneTimePasswordWithReference(checkboxes[i].name);
+ checkboxes[i].checked = matchingOneTimePassword.isExpired();
+ }
+
+ this.updateDeleteButtonStatus();
+ },
+
+ 'selectUnusedOneTimePasswords': function(anEvent) {
+ var checkboxes;
+ var oneTimePasswordManager;
+ var i,c;
+
+ anEvent.stop();
+ oneTimePasswordManager = this.user().oneTimePasswordManager();
+ checkboxes = this.oneTimePasswordCheckboxes();
+ c = checkboxes.length;
+ for (i=0; i<c; i++) {
+ var matchingOneTimePassword;
+
+ matchingOneTimePassword = oneTimePasswordManager.oneTimePasswordWithReference(checkboxes[i].name);
+ checkboxes[i].checked = !matchingOneTimePassword.isExpired();
+ }
+
+ this.updateDeleteButtonStatus();
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'handleCheckboxClick': function(anEvent) {
+ this.updateDeleteButtonStatus();
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'deleteSelectedOneTimePasswords': function() {
+ var deferredResult;
+ var otpToDelete;
+ var i,c;
+
+ otpToDelete = this.checkedOneTimePasswordCheckboxes();
+ c = otpToDelete.length;
+ for (i=0; i<c; i++) {
+//MochiKit.Logging.logDebug("otp to delete: " + otpToDelete[i].name);
+ this.user().oneTimePasswordManager().deleteOneTimePasswordWithReference(otpToDelete[i].name);
+ };
+
+ deferredResult = new MochiKit.Async.Deferred();
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("ActiveOTPPanel.deleteSelectedOneTimePasswords - 0: " + res); return res;});
+ deferredResult.addCallback(Clipperz.PM.Components.MessageBox.showProgressPanel, MochiKit.Base.method(this.user().oneTimePasswordManager(), 'saveChanges'), null, null);
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("ActiveOTPPanel.deleteSelectedOneTimePasswords - 1: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(this, 'render'));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("ActiveOTPPanel.deleteSelectedOneTimePasswords - 2: " + res); return res;});
+ deferredResult.callback();
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'user': function() {
+ return this._user;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'shouldRender': function() {
+ return this._shouldRender;
+ },
+
+ 'setShouldRender': function(aValue) {
+ this._shouldRender = aValue;
+ },
+
+ 'tabSelectedHandler': function(anEvent) {
+ if ((this.shouldRender()) && (anEvent.source().selectedTab() == 'manageOTPTab')) {
+ this.render();
+ this.setShouldRender(false);
+ }
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'deleteButton': function() {
+ return this._deleteButton;
+ },
+
+ 'setDeleteButton': function(aValue) {
+ this._deleteButton = aValue;
+ },
+
+ 'updateDeleteButtonStatus': function() {
+ if (this.checkedOneTimePasswordCheckboxes().length > 0) {
+ this.deleteButton().enable();
+ } else {
+ this.deleteButton().disable();
+ }
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'printButton': function() {
+ return this._printButton;
+ },
+
+ 'setPrintButton': function(aValue) {
+ this._printButton = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+});
+
diff --git a/frontend/beta/js/Clipperz/PM/Components/Panels/AccountPanel.js b/frontend/beta/js/Clipperz/PM/Components/Panels/AccountPanel.js
new file mode 100644
index 0000000..6b467d0
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Components/Panels/AccountPanel.js
@@ -0,0 +1,784 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
+if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
+if (typeof(Clipperz.PM.Components) == 'undefined') { Clipperz.PM.Components = {}; }
+if (typeof(Clipperz.PM.Components.Panels) == 'undefined') { Clipperz.PM.Components.Panels = {}; }
+
+//#############################################################################
+
+Clipperz.PM.Components.Panels.AccountPanel = function(anElement, args) {
+//MochiKit.Logging.logDebug(">>> new AccountPanel");
+ args = args || {};
+
+ Clipperz.PM.Components.Panels.AccountPanel.superclass.constructor.call(this, anElement, args);
+
+ Clipperz.NotificationCenter.register(null, 'setupDone', this, 'render');
+
+ this._shouldLoadLoginHistory = true;
+
+// this.render();
+//MochiKit.Logging.logDebug("<<< new AccountPanel");
+
+ return this;
+}
+
+//=============================================================================
+
+YAHOO.extendX(Clipperz.PM.Components.Panels.AccountPanel, Clipperz.PM.Components.Panels.BasePanel, {
+
+ 'toString': function() {
+ return "Clipperz.PM.Components.AccountPanel component";
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'render': function() {
+ var errorMessageActor;
+ var changePasswordButton;
+ var deleteAccountButton;
+
+try {
+//MochiKit.Logging.logDebug(">>> AccountPanel.render");
+ Clipperz.NotificationCenter.unregister(this);
+ MochiKit.Signal.disconnectAllTo(this);
+
+ this.element().update("");
+ Clipperz.YUI.DomHelper.append(this.element().dom, {tag:'table', border:'0', cellspacing:'0', cellpadding:'0', children:[
+ {tag:'tbody', children:[
+ {tag:'tr', children:[
+ {tag:'td', valign:'top', width:'200', children:[
+ {tag:'ul', id:"accountSubMenu", cls:'subMenu', children:[
+ {tag:'li', id:'changePassphraseTab', htmlString:Clipperz.PM.Strings['changePasswordTabLabel']},
+ {tag:'li', id:'manageOTPTab', htmlString:Clipperz.PM.Strings['manageOTPTabLabel']},
+ {tag:'li', id:'accountPreferencesTab', htmlString:Clipperz.PM.Strings['accountPreferencesLabel']},
+ {tag:'li', id:'loginHistoryTab', htmlString:Clipperz.PM.Strings['accountLoginHistoryLabel']},
+ {tag:'li', id:'deleteAccountTab', htmlString:Clipperz.PM.Strings['deleteAccountTabLabel']}
+// {tag:'li', id:'paidAccountTab'), htmlString:Clipperz.PM.Strings['paidAccountTabLabel']}
+ ]}
+ ]},
+ {tag:'td', valign:'top', children:[
+ {tag:'ul', cls:'clipperzTabPanels', children:[
+ {tag:'li', id:this.getId('changePassphrasePanel'), children:[
+ {tag:'div', cls:'clipperzSubPanel', children:[
+ {tag:'h5', htmlString:Clipperz.PM.Strings['changePasswordTabTitle']},
+ {tag:'div', cls:'panelBody', id:'changePassphraseBlock', children:[
+ {tag:'form', id:this.getId('changePassphraseForm'), children:[
+ {tag:'h5', cls:'errorMessage', id:this.getId('changePassphrase_errorMessage')},
+ {tag:'table', cls:'panelBody', children:[
+ {tag:'tr', children:[
+ {tag:'td', children:[
+ {tag:'span', cls:'formLabel', htmlString:Clipperz.PM.Strings['changePasswordFormUsernameLabel']}
+ ]},
+ {tag:'td', children:[
+ {tag:'input', type:'text', name:'username', id:this.getId('changePassphrase_username')}
+ ]}
+ ]},
+ {tag:'tr', children:[
+ {tag:'td', children:[
+ {tag:'span', cls:'formLabel', htmlString:Clipperz.PM.Strings['changePasswordFormOldPassphraseLabel']}
+ ]},
+ {tag:'td', children:[
+ {tag:'input', type:'password', name:'oldPassphrase', id:this.getId('changePassphrase_oldPassphrase')}
+ ]}
+ ]},
+ {tag:'tr', children:[
+ {tag:'td', children:[
+ {tag:'span', cls:'formLabel', htmlString:Clipperz.PM.Strings['changePasswordFormNewPassphraseLabel']}
+ ]},
+ {tag:'td', children:[
+ {tag:'input', type:'password', name:'newPassphrase', id:this.getId('changePassphrase_newPassphrase')}
+ ]}
+ ]},
+ {tag:'tr', children:[
+ {tag:'td', children:[
+ {tag:'span', cls:'formLabel', htmlString:Clipperz.PM.Strings['changePasswordFormRetypePassphraseLabel']}
+ ]},
+ {tag:'td', children:[
+ {tag:'input', type:'password', name:'renewPassphrase', id:this.getId('changePassphrase_renewPassphrase')}
+ ]}
+ ]},
+ {tag:'tr', children:[
+ {tag:'td', align:'right', children:[
+ {tag:'input', type:'checkbox', id:this.getId('changePassphrase_safetyCheck')}
+ ]},
+ {tag:'td', children:[
+ {tag:'span', htmlString:Clipperz.PM.Strings['changePasswordFormSafetyCheckboxLabel']}
+ ]}
+ ]}
+ ]},
+ {tag:'div', cls:'clipperzSubPanelButtonBox', children:[
+ {tag:'div', id:this.getId('changePassphraseButton')}
+ ]}
+ ]}
+ ]}
+ ]}
+ ]},
+ {tag:'li', id:this.getId('manageOTPPanel'), children:[
+ {tag:'div', cls:'clipperzSubPanel', children:[
+ {tag:'h5', htmlString:Clipperz.PM.Strings['manageOTPTabTitle']},
+ {tag:'div', cls:'panelDescription', htmlString:Clipperz.PM.Strings['manageOTPTabDescription']},
+ {tag:'div', id:'OTPComponent'}
+ ]}
+ ]},
+ {tag:'li', id:this.getId('accountPreferencesPanel'), children:[
+ {tag:'div', cls:'clipperzSubPanel', children:[
+ {tag:'h5', htmlString:Clipperz.PM.Strings['accountPreferencesTabTitle']},
+ {tag:'div', cls:'panelBody', id:this.getId('preferencesPanelBody')}
+ ]}
+ ]},
+ {tag:'li', id:this.getId('loginHistoryAccountPanel'), children:[
+ {tag:'div', cls:'clipperzSubPanel', children:[
+ {tag:'h5', htmlString:Clipperz.PM.Strings['loginHistoryTabTitle']},
+ {tag:'div', cls:'panelBody', id:'loginHistoryAccountBlock'}
+ ]}
+ ]},
+ {tag:'li', id:this.getId('deleteAccountPanel'), children:[
+ {tag:'div', cls:'clipperzSubPanel', children:[
+ {tag:'h5', htmlString:Clipperz.PM.Strings['deleteAccountTabTitle']},
+
+ {tag:'div', cls:'panelBody', id:'deleteAccountBlock', children:[
+ {tag:'form', id:this.getId('deleteAccountForm'), children:[
+ {tag:'h5', cls:'errorMessage', id:this.getId('deleteAccount_errorMessage')},
+ {tag:'table', cls:'panelBody', children:[
+ {tag:'tr', children:[
+ {tag:'td', children:[
+ {tag:'span', cls:'formLabel', htmlString:Clipperz.PM.Strings['deleteAccountFormUsernameLabel']}
+ ]},
+ {tag:'td', children:[
+ {tag:'input', type:'text', name:'username', id:this.getId('deleteAccount_username')}
+ ]}
+ ]},
+ {tag:'tr', children:[
+ {tag:'td', children:[
+ {tag:'span', cls:'formLabel', htmlString:Clipperz.PM.Strings['deleteAccountFormPassphraseLabel']}
+ ]},
+ {tag:'td', children:[
+ {tag:'input', type:'password', name:'passphrase', id:this.getId('deleteAccount_passphrase')}
+ ]}
+ ]},
+ {tag:'tr', children:[
+ {tag:'td', align:'right', children:[
+ {tag:'input', type:'checkbox', id:this.getId('deleteAccount_safetyCheck')}
+ ]},
+ {tag:'td', children:[
+ {tag:'span', htmlString:Clipperz.PM.Strings['deleteAccountFormSafetyCheckboxLabel']}
+ ]}
+ ]}
+ ]},
+ {tag:'div', cls:'clipperzSubPanelButtonBox', children:[
+ {tag:'div', id:this.getId('deleteAccountButton')}
+ ]}
+ ]}
+ ]}
+ ]}
+ ]}
+/*
+ {tag:'li', id:this.getId('paidAccountPanel'), children:[
+ {tag:'div', cls:'clipperzSubPanel', children:[
+ {tag:'h5', htmlString:Clipperz.PM.Strings['upgradeAccountTabTitle']},
+ {tag:'div', htmlString:Clipperz.PM.Strings['comingSoon']}
+ ]}
+ ]}
+*/
+ ]}
+ ]}
+ ]}
+ ]}
+ ]});
+
+//MochiKit.Logging.logDebug("--- AccountPanel.render - 1");
+ MochiKit.Signal.connect(this.getId('changePassphraseForm'), 'onkeydown', this, 'onkeydown');
+ errorMessageActor = this.getActor('changePassphrase_errorMessage');
+ errorMessageActor.setVisibilityMode(YAHOO.ext.Element.DISPLAY);
+ errorMessageActor.update("---");
+ errorMessageActor.hide();
+ changePasswordButton = new YAHOO.ext.Button(this.getDom('changePassphraseButton'), {text:Clipperz.PM.Strings['changePasswordFormSubmitLabel'], handler:this.doChangePassphrase, scope:this});
+
+//MochiKit.Logging.logDebug("--- AccountPanel.render - 2");
+
+ MochiKit.Signal.connect(this.getId('deleteAccountForm'), 'onkeydown', this, 'onkeydown');
+ errorMessageActor = this.getActor('deleteAccount_errorMessage');
+ errorMessageActor.setVisibilityMode(YAHOO.ext.Element.DISPLAY);
+ errorMessageActor.update(Clipperz.PM.Strings['deleteAccountFormEmptyErrorMessage']);
+ errorMessageActor.hide();
+ deleteAccountButton = new YAHOO.ext.Button(this.getDom('deleteAccountButton'), {text:Clipperz.PM.Strings['deleteAccountFormSubmitLabel'], handler:this.doDeleteAccount, scope:this});
+//MochiKit.Logging.logDebug("--- AccountPanel.render - 5");
+
+ if (Clipperz.PM.Proxy.defaultProxy.isReadOnly()) {
+ this.getElement('changePassphraseForm').addClass('read-only');
+// this.getElement('accountPreferencesForm').addClass('read-only');
+ this.getElement('deleteAccountForm').addClass('read-only');
+ changePasswordButton.disable();
+ deleteAccountButton.disable();
+ }
+//MochiKit.Logging.logDebug("--- AccountPanel.render - 6");
+
+ new Clipperz.PM.Components.PasswordEntropyDisplay(this.getElement('changePassphrase_oldPassphrase'));
+ new Clipperz.PM.Components.PasswordEntropyDisplay(this.getElement('changePassphrase_newPassphrase'));
+
+ new Clipperz.PM.Components.OTP.MainComponent(YAHOO.ext.Element.get('OTPComponent'), {user:this.user()});
+
+ this.tabPanelController().setUp();
+ Clipperz.NotificationCenter.register(null, 'tabSelected', this, 'tabSelectedHandler');
+ Clipperz.NotificationCenter.register(null, 'updatedPreferences', this, 'renderPreferences');
+ Clipperz.NotificationCenter.register(null, 'switchLanguage', this, 'switchLanguageHandler');
+//MochiKit.Logging.logDebug("<<< AccountPanel.render");
+
+} catch(exception) {
+ MochiKit.Logging.logError("### " + exception);
+ throw exception;
+}
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'tabPanelController': function() {
+ if (this._tabPanelController == null) {
+ var tabPanelControllerConfig;
+
+ tabPanelControllerConfig = {}
+ tabPanelControllerConfig['changePassphraseTab'] = this.getId('changePassphrasePanel');
+ tabPanelControllerConfig['manageOTPTab'] = this.getId('manageOTPPanel');
+ tabPanelControllerConfig['accountPreferencesTab'] = this.getId('accountPreferencesPanel');
+ tabPanelControllerConfig['loginHistoryTab'] = this.getId('loginHistoryAccountPanel');
+ tabPanelControllerConfig['deleteAccountTab'] = this.getId('deleteAccountPanel');
+// tabPanelControllerConfig['paidAccountTab'] = this.getId('paidAccountPanel');
+
+ this._tabPanelController = new Clipperz.PM.Components.TabPanel.TabPanelController({
+ name:'accountTabPanel',
+ config:tabPanelControllerConfig,
+ selectedTab:'changePassphraseTab'
+ });
+ }
+
+ return this._tabPanelController;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'doChangePassphrase': function() {
+ if (Clipperz.PM.Proxy.defaultProxy.isReadOnly() == false) {
+ var username;
+ var oldPassphrase;
+ var newPassphrase;
+ var renewPassphrase;
+ var safetyCheck;
+ var areThereAnyErrors;
+ var errorMessageActor;
+
+ errorMessageActor = this.getActor('changePassphrase_errorMessage');
+
+ areThereAnyErrors = false;
+ username = this.getDom('changePassphrase_username').value;
+ oldPassphrase= this.getDom('changePassphrase_oldPassphrase').value;
+ newPassphrase= this.getDom('changePassphrase_newPassphrase').value;
+ renewPassphrase= this.getDom('changePassphrase_renewPassphrase').value;
+ safetyCheck = this.getDom('changePassphrase_safetyCheck').checked;
+
+ if (this.user().username() != username) {
+ this.showFormErrorMessageAnimation(errorMessageActor, Clipperz.PM.Strings['changePasswordFormWrongUsernameWarning']);
+ this.getElement('changePassphrase_username').focus().dom.select();
+ areThereAnyErrors = true;
+ } else if (this.user().passphrase() != oldPassphrase) {
+ this.showFormErrorMessageAnimation(errorMessageActor, Clipperz.PM.Strings['changePasswordFormWrongPassphraseWarning']);
+ this.getElement('changePassphrase_oldPassphrase').focus().dom.select();
+ areThereAnyErrors = true;
+ } else if (newPassphrase != renewPassphrase) {
+ this.showFormErrorMessageAnimation(errorMessageActor, Clipperz.PM.Strings['changePasswordFormWrongRetypePassphraseWarning']);
+ this.getElement('changePassphrase_renewPassphrase').focus().dom.select();
+ areThereAnyErrors = true;
+ } else if (safetyCheck != true) {
+ this.showFormErrorMessageAnimation(errorMessageActor, Clipperz.PM.Strings['changePasswordFormSafetyCheckWarning']);
+ this.getElement('changePassphrase_safetyCheck').focus();
+ areThereAnyErrors = true;
+ }
+
+ if (areThereAnyErrors == false) {
+ errorMessageActor.hide();
+ this.doChangePassphraseWithUsernameAndPassphrase(username, newPassphrase);
+ }
+ }
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'doChangePassphraseWithUsernameAndPassphrase': function(anUsername, aPassphrase) {
+ var deferredResult;
+
+//MochiKit.Logging.logDebug(">>> AccountPanel.doChangePassphraseWithUsernameAndPassphrase - this.user: " + this.user());
+ deferredResult = new MochiKit.Async.Deferred();
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug(" AccountPanel.doChangePassphraseWithUsernameAndPassphrase 1: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(Clipperz.PM.Components.MessageBox(), 'deferredShow'),
+ {
+ title:Clipperz.PM.Strings['changePasswordFormProgressDialogTitle'],
+ text:Clipperz.PM.Strings['changePasswordFormProgressDialogEmptyText'],
+ width:240,
+ showProgressBar:true,
+ showCloseButton:false,
+ steps:4
+ },
+ this.getDom('changePassphraseButton')
+ );
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug(" AccountPanel.doChangePassphraseWithUsernameAndPassphrase 2: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(this.user(), 'changeCredentials'), anUsername, aPassphrase);
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug(" AccountPanel.doChangePassphraseWithUsernameAndPassphrase 3: " + res); return res;});
+ deferredResult.addCallback(function() {
+ Clipperz.PM.Components.MessageBox().update({
+ title:Clipperz.PM.Strings['changePasswordFormProgressDialogConnectedMessageTitle'],
+ text:Clipperz.PM.Strings['changePasswordFormProgressDialogConnectedMessageText'],
+ /*showProgressBar:false,*/
+ step:'next'
+ });
+ });
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug(" AccountPanel.doChangePassphraseWithUsernameAndPassphrase 4: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Async.wait, 1);
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug(" AccountPanel.doChangePassphraseWithUsernameAndPassphrase 5: " + res); return res;});
+ deferredResult.addCallback(function(anAccountPanel, res) {
+ Clipperz.PM.Components.MessageBox().hide(YAHOO.ext.Element.get('main'));
+
+ anAccountPanel.getDom('changePassphrase_username').value = "";
+ anAccountPanel.getDom('changePassphrase_oldPassphrase').value = "";
+ anAccountPanel.getElement('changePassphrase_oldPassphrase').focus();
+ anAccountPanel.getDom('changePassphrase_newPassphrase').value = "";
+ anAccountPanel.getElement('changePassphrase_newPassphrase').focus();
+ anAccountPanel.getDom('changePassphrase_renewPassphrase').value = "";
+ anAccountPanel.getDom('changePassphrase_safetyCheck').checked = false;
+
+ anAccountPanel.getElement('changePassphrase_username').focus();
+ return res;
+ }, this);
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug(" AccountPanel.doChangePassphraseWithUsernameAndPassphrase 6: " + res); return res;});
+ deferredResult.addErrback(function() {
+ Clipperz.PM.Components.MessageBox().update({
+ title:Clipperz.PM.Strings['changePasswordFormProgressDialogErrorMessageTitle'],
+ text:Clipperz.PM.Strings['changePasswordFormProgressDialogErrorMessageText'],
+ buttons:{'ok':"close"}
+ });
+ });
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug(" AccountPanel.doChangePassphraseWithUsernameAndPassphrase 7: " + res); return res;});
+ deferredResult.callback();
+
+//MochiKit.Logging.logDebug("<<< AccountPanel.doChangePassphraseWithUsernameAndPassphrase");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'doDeleteAccount': function() {
+ if (Clipperz.PM.Proxy.defaultProxy.isReadOnly() == false) {
+ var username;
+ var passphrase;
+ var safetyCheck;
+ var areThereAnyErrors;
+ var errorMessageActor;
+
+ errorMessageActor = this.getActor('deleteAccount_errorMessage');
+
+ areThereAnyErrors = false;
+ username = this.getDom('deleteAccount_username').value;
+ passphrase= this.getDom('deleteAccount_passphrase').value;
+ safetyCheck = this.getDom('deleteAccount_safetyCheck').checked;
+
+ if (this.user().username() != username) {
+ this.showFormErrorMessageAnimation(errorMessageActor, Clipperz.PM.Strings['deleteAccountFormWrongUsernameWarning']);
+ this.getElement('deleteAccount_username').focus().dom.select();
+ areThereAnyErrors = true;
+ } else if (this.user().passphrase() != passphrase) {
+ this.showFormErrorMessageAnimation(errorMessageActor, Clipperz.PM.Strings['deleteAccountFormWrongPassphraseWarning']);
+ this.getElement('deleteAccount_passphrase').focus().dom.select();
+ areThereAnyErrors = true;
+ } else if (safetyCheck != true) {
+ this.showFormErrorMessageAnimation(errorMessageActor, Clipperz.PM.Strings['deleteAccountFormSafetyCheckWarning']);
+ this.getElement('deleteAccount_safetyCheck').focus();
+ areThereAnyErrors = true;
+ }
+
+ if (areThereAnyErrors == false) {
+ var deferred;
+
+ deferred = new MochiKit.Async.Deferred();
+ errorMessageActor.hide();
+
+ deferred.addCallback(function() {
+ var deferredResult;
+
+ // TODO: if the form is submitted with the return key, the confirmation dialog is skipped!?
+ deferredResult = new MochiKit.Async.Deferred();
+ Clipperz.PM.Components.MessageBox().deferredShow({
+ title:Clipperz.PM.Strings['accountPanelDeletingAccountPanelConfirmationTitle'],
+ text:Clipperz.PM.Strings['accountPanelDeleteAccountPanelConfirmationText'],
+ width:240,
+ showProgressBar:false,
+ showCloseButton:false,
+ buttons:{
+ 'yes':Clipperz.PM.Strings['accountPanelDeleteAccountPanelConfirmButtonLabel'],
+ 'no':Clipperz.PM.Strings['accountPanelDeleteAccountPanelDenyButtonLabel']
+ },
+ fn:MochiKit.Base.partial(function(aDeferred, aResult) {
+ if (aResult == 'yes') {
+ aDeferred.callback(aResult);
+ } else {
+ aDeferred.errback(aResult);
+ }
+ }, deferredResult)
+ });
+
+ return deferredResult;
+ });
+ deferred.addCallback(MochiKit.Base.method(Clipperz.PM.Components.MessageBox(), 'deferredShow'),
+ {
+ title:Clipperz.PM.Strings['accountPanelDeletingAccountPanelProgressTitle'],
+ text:Clipperz.PM.Strings['accountPanelDeletingAccountPanelProgressText'],
+ width:240,
+ showProgressBar:true,
+ showCloseButton:false
+ }
+ );
+ deferred.addCallback(MochiKit.Base.method(this.user(), 'deleteAccountAction'));
+ deferred.addCallback(Clipperz.PM.exit, 'accountDeleted.html');
+ deferred.addErrback(function(res) {
+ alert(res);
+ })
+ deferred.callback();
+ }
+ }
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'showFormErrorMessageAnimation': function(anActor, anErrorMessage, aCallback) {
+ anActor.update(anErrorMessage);
+ anActor.show(true);
+ anActor.play(aCallback);
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'onkeydown': function(anEvent) {
+//MochiKit.Logging.logDebug(">>> onkeydown - " + anEvent.src().id);
+ if (anEvent.key().code == 13) {
+ anEvent.stop();
+
+ if (anEvent.src() == this.getDom('changePassphraseForm')) {
+ this.doChangePassphrase();
+ } else if (anEvent.src() == this.getDom('deleteAccountForm')) {
+ this.doDeleteAccount();
+ } else {
+ }
+
+ }
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'selectSelectedLanguageOption': function() {
+ var userSelectedLanguage;
+
+ userSelectedLanguage = this.user().preferences().preferredLanguage() || "default";
+ MochiKit.Base.filter(function(anOption) {return (anOption.value == userSelectedLanguage)}, this.getDom('languageSelector').childNodes)[0].selected = true;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'doSaveUserPreferences': function() {
+ var selectedLanguage;
+ var showDonationReminderDialog;
+// var disableUnsecureFaviconLoadingForIE;
+
+//MochiKit.Logging.logDebug(">>> AccountPanel.doSaveUserPreferences");
+ selectedLanguage = this.getDom('languageSelector').value;
+ if (selectedLanguage == "default") {
+ selectedLanguage = null;
+ }
+ this.user().preferences().setPreferredLanguage(selectedLanguage);
+
+ showDonationReminderDialog = this.getDom('showDonationReminderCheckbox').checked;
+ this.user().preferences().setShouldShowDonationPanel(showDonationReminderDialog);
+
+// disableUnsecureFaviconLoadingForIE = this.getDom('disableFaviconForIECheckbox').checked;
+// this.user().preferences().setDisableUnsecureFaviconLoadingForIE(disableUnsecureFaviconLoadingForIE);
+
+ this.user().preferences().saveChanges(this.getDom('saveUserPreferences'));
+ },
+
+ 'doCancelUserPreferences': function() {
+ this.renderPreferences();
+ },
+
+// 'switchLanguage': function(anEvent) {
+// Clipperz.PM.Strings.Languages.setSelectedLanguage(anEvent.src().value);
+// },
+
+ //-------------------------------------------------------------------------
+
+ 'renderLoginHistory': function() {
+ var element;
+
+//MochiKit.Logging.logDebug(">>> AccountPanel.renderLoginHistory");
+ element = YAHOO.ext.Element.get('loginHistoryAccountBlock');
+
+ if (Clipperz.PM.Proxy.defaultProxy.isReadOnly()) {
+ element.update("");
+ this.domHelper().append(element, {tag:'div', cls:'loginHistoryReadOnlyMessage', htmlString:Clipperz.PM.Strings['loginHistoryReadOnlyMessage']});
+ } else {
+ var deferredResult;
+
+ deferredResult = new MochiKit.Async.Deferred();
+ deferredResult.addCallback(MochiKit.Base.bind(function(anElement) {
+ anElement.update("");
+ Clipperz.YUI.DomHelper.append(anElement, {tag:'div', cls:'loadingMessage', htmlString:Clipperz.PM.Strings['loginHistoryLoadingMessage']});
+ }, this), element);
+ deferredResult.addCallback(MochiKit.Base.method(this.user(), 'loadLoginHistory'));
+ deferredResult.addCallback(MochiKit.Base.bind(function(anElement, aResult) {
+ var loginListItems;
+ var tBodyElement;
+ var imageExtension;
+ var now;
+ var i, c;
+
+ loginListItems = aResult;
+//MochiKit.Logging.logDebug("=== loginListItems: " + Clipperz.Base.serializeJSON(loginListItems));
+ imageExtension = (Clipperz_IEisBroken == true) ? 'gif': 'png';
+
+ now = new Date();
+ anElement.update("");
+ Clipperz.YUI.DomHelper.append(anElement, {tag:'div', cls:'panelDescription', htmlString:Clipperz.PM.Strings['loginHistoryLoadedMessage']});
+ Clipperz.YUI.DomHelper.append(anElement, {tag:'table', id:'loginHistoryTable', cellspacing:'0', cellpadding:'2', border:'0', children:[
+ {tag:'tbody', id:this.getId('loginHistoryTBody'), children:[]}
+ ]});
+//# Clipperz.YUI.DomHelper.append(anElement, {tag:'div', id:'loginHistoryFooter', children:[
+ Clipperz.YUI.DomHelper.append(anElement, {tag:'div', cls:'clipperzSubPanelButtonBox', children:[
+ {tag:'div', id:this.getId('reloadHistoryButton')}
+ ]});
+
+ new YAHOO.ext.Button(this.getDom('reloadHistoryButton'), {text:Clipperz.PM.Strings['loginHistoryReloadButtonLabel'], handler:this.reloadHistory, scope:this});
+
+ tBodyElement = this.getElement('loginHistoryTBody');
+ c = loginListItems.length;
+ for (i=0; i<c; i++) {
+ var ip;
+ var date;
+ var mainText;
+
+ date = Clipperz.PM.Date.parseDateWithUTCFormat(loginListItems[i]['date']);
+
+ if (loginListItems[i]['isCurrent'] === true) {
+ mainText ={tag:'div', cls:'currentSession', htmlString:Clipperz.PM.Strings['loginHistoryCurrentSessionText']}
+ } else {
+ mainText = {tag:'div', cls:'elapsedTime', html:Clipperz.PM.Date.getElapsedTimeDescription(date)}
+ }
+
+ if (loginListItems[i]['connectionType'] == "ONE_TIME_PASSPHRASE") {
+ optionalInfo = [
+ {tag:'span', html:"OTP"}
+ ];
+ } else {
+ optionalInfo = [];
+ }
+
+ ip = (loginListItems[i]['ip'].match(/^\d{1,3}(.\d{1,3}){3}$/)) ? loginListItems[i]['ip'] : Clipperz.PM.Strings['unknown_ip'];
+ Clipperz.YUI.DomHelper.append(tBodyElement, {tag:'tr', children:[
+ {tag:'td', cls:'loginHistoryValues', valign:'top', children:[
+ mainText,
+ {tag:'div', cls:'fullDate', html:Clipperz.PM.Date.formatDateWithTemplate(date, Clipperz.PM.Strings['fullDate_format'])},
+ {tag:'div', cls:'loginHistoryIP', children:[
+ {tag:'span', cls:'loginHistoryIPLabel', htmlString:Clipperz.PM.Strings['loginHistoryIPLabel']},
+ {tag:'span', cls:'loginHistoryIPValue', html:ip}
+ ]}
+ ]},
+ {tag:'td', cls:'loginHistoryCountry', valign:'top', children:optionalInfo},
+ {tag:'td', cls:'loginHistoryCountry', valign:'top', align:'center', children:[
+ {tag:'img', title:Clipperz.PM.Strings['countries'][loginListItems[i]['country']], cls:'flag', src:Clipperz.PM.Strings['icons_baseUrl'] + "/flags/" + loginListItems[i]['country'].toLowerCase() + "." + imageExtension, width:'32', height:'32'}
+// {tag:'span', cls:'label', htmlString:Clipperz.PM.Strings['countries'][loginListItems[i]['country']]}
+ ]},
+ {tag:'td', cls:'loginHistoryBrowser', valign:'top', align:'center', children:[
+ {tag:'img', title:Clipperz.PM.Strings['browsers'][loginListItems[i]['browser']], cls:'browser', src:Clipperz.PM.Strings['icons_baseUrl'] + "/browsers/" + loginListItems[i]['browser'].toLowerCase() + "." + imageExtension, width:'32', height:'32'}
+// {tag:'span', cls:'label', htmlString:Clipperz.PM.Strings['browsers'][loginListItems[i]['browser']]}
+ ]},
+ {tag:'td', cls:'loginHistoryOperatingSystem', valign:'top', align:'center', children:[
+ {tag:'img', title:Clipperz.PM.Strings['operatingSystems'][loginListItems[i]['operatingSystem']], cls:'operatingSystem', src:Clipperz.PM.Strings['icons_baseUrl'] + "/operatingSystems/" + loginListItems[i]['operatingSystem'].toLowerCase() + "." + imageExtension, width:'32', height:'32'}
+// {tag:'span', cls:'label', htmlString:Clipperz.PM.Strings['operatingSystems'][loginListItems[i]['operatingSystem']]}
+ ]}
+ ]});
+ }
+
+ Clipperz.Style.applyZebraStylesToTable('loginHistoryTable');
+ }, this), element);
+
+ deferredResult.callback();
+ }
+//MochiKit.Logging.logDebug("<<< AccountPanel.renderLoginHistory");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'renderPreferences': function() {
+ var saveUserPreferencesButton;
+ var cancelUserPreferencesButton;
+ var preferencedPanelBodyElement;
+
+ preferencedPanelBodyElement = this.getElement('preferencesPanelBody');
+
+ preferencedPanelBodyElement.update("");
+ Clipperz.YUI.DomHelper.append(preferencedPanelBodyElement,
+ {tag:'form', id:this.getId('accountPreferencesForm'), children:[
+ {tag:'table', cls:'panelBody', children:[
+ {tag:'tr', cls:'openPreferenceBlock', children:[
+ {tag:'td', children:[
+ {tag:'div', cls:'preferenceBlockTitle', htmlString:Clipperz.PM.Strings['accountPreferencesLanguageTitle']},
+ {tag:'div', cls:'panelDescription', htmlString:Clipperz.PM.Strings['accountPreferencesLanguageDescription']},
+ {tag:'div', cls:'panelDescription', children:[
+ {tag:'select',
+ id:this.getId('languageSelector'),
+ children:MochiKit.Base.concat([{tag:'option', value:"default", html:"---"}], Clipperz.PM.Strings['loginPanelSwitchLanguageSelectOptions'])
+ }
+ ]}
+ ]}
+ ]},
+ {tag:'tr', cls:'openPreferenceBlock', children:[
+ {tag:'td', children:[
+ {tag:'div', cls:'preferenceBlockTitle', htmlString:Clipperz.PM.Strings['showDonationReminderPanelTitle']},
+ {tag:'table', cellpadding:'0', cellspacing:'0', children:[
+ {tag:'tbody', children:[
+ {tag:'tr', children:[
+ {tag:'td', valign:'top', children:[
+ {tag:'div', cls:'panelDescription', children:[
+ {tag:'input', type:'checkbox', id:this.getId('showDonationReminderCheckbox')}
+ ]}
+ ]},
+ {tag:'td', valign:'top', children:[
+ {tag:'div', cls:'panelDescription', htmlString:Clipperz.PM.Strings['showDonationReminderPanelDescription']}
+ ]}
+ ]}
+ ]}
+ ]}
+ ]}
+ ]} //,
+/*
+ {tag:'tr', cls:'openPreferenceBlock', children:[
+ {tag:'td', children:[
+ {tag:'div', cls:'preferenceBlockTitle', htmlString:Clipperz.PM.Strings['disableFaviconForIETitle']},
+ {tag:'table', cellpadding:'0', cellspacing:'0', children:[
+ {tag:'tbody', children:[
+ {tag:'tr', children:[
+ {tag:'td', valign:'top', children:[
+ {tag:'div', cls:'panelDescription', children:[
+ {tag:'input', type:'checkbox', id:this.getId('disableFaviconForIECheckbox')}
+ ]}
+ ]},
+ {tag:'td', valign:'top', children:[
+ {tag:'div', cls:'panelDescription', children:Clipperz.PM.Strings['disableFaviconForIEDescriptionConfig']}
+ ]}
+ ]}
+ ]}
+ ]}
+ ]}
+ ]},
+*/
+ // {tag:'tr', cls:'openPreferenceBlock', children:[
+ // {tag:'td', children:[
+ // {tag:'div', cls:'preferenceBlockTitle', htmlString:Clipperz.PM.Strings['accountPreferencesInterfaceTitle']},
+ // {tag:'div', cls:'panelDescription', children:Clipperz.PM.Strings['accountPreferencesInterfaceDescriptionConfig']}
+ // ]}
+ // ]}
+ ]},
+ {tag:'div', cls:'clipperzSubPanelButtonBox', children:[
+ {tag:'table', border:'0', cellspacing:'0', cellpadding:'0', children:[
+ {tag:'tbody', children:[
+ {tag:'tr', children:[
+ {tag:'td', width:'100', align:'right', cls:'newRecordPanelButtonTD', children:[
+ {tag:'div', id:this.getId('saveUserPreferences')}
+ ]},
+ {tag:'td', width:'10', html:"&nbsp;"},
+ {tag:'td', cls:'newRecordPanelButtonTD', children:[
+ {tag:'div', id:this.getId('cancelUserPreferences')}
+ ]}
+ ]}
+ ]}
+ ]}
+ ]}
+ ]}
+ );
+
+ this.selectSelectedLanguageOption();
+ if (this.user().preferences().shouldShowDonationPanel()) {
+ this.getDom('showDonationReminderCheckbox').checked = true;
+ }
+// if (this.user().preferences().disableUnsecureFaviconLoadingForIE()) {
+// this.getDom('disableFaviconForIECheckbox').checked = true;
+// }
+
+//MochiKit.Logging.logDebug("--- AccountPanel.render - 3");
+//# saveUserPreferencesButton = new YAHOO.ext.Button(this.getDom('saveUserPreferences'), {text:Clipperz.PM.Strings['saveUserPreferencesFormSubmitLabel'], handler:this.doSaveUserPreferences, scope:this});
+ saveUserPreferencesButton = new YAHOO.ext.Button(this.getDom('saveUserPreferences'), {text:'-----------------', handler:this.doSaveUserPreferences, scope:this});
+ saveUserPreferencesButton.setText(Clipperz.PM.Strings['saveUserPreferencesFormSubmitLabel']);
+//# cancelUserPreferencesButton = new YAHOO.ext.Button(this.getDom('cancelUserPreferences'), {text:Clipperz.PM.Strings['cancelUserPreferencesFormSubmitLabel'], handler:this.doCancelUserPreferences, scope:this});
+ cancelUserPreferencesButton = new YAHOO.ext.Button(this.getDom('cancelUserPreferences'), {text:'-----------------', handler:this.doCancelUserPreferences, scope:this});
+ cancelUserPreferencesButton.setText(Clipperz.PM.Strings['cancelUserPreferencesFormSubmitLabel']);
+//MochiKit.Logging.logDebug("--- AccountPanel.render - 4");
+
+ if (Clipperz.PM.Proxy.defaultProxy.isReadOnly()) {
+ this.getElement('accountPreferencesForm').addClass('read-only');
+ saveUserPreferencesButton.disable();
+ cancelUserPreferencesButton.disable();
+ }
+
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'reloadHistory': function() {
+ this.setShouldLoadLoginHistory(true);
+ this.renderLoginHistory();
+ },
+
+ 'shouldLoadLoginHistory': function() {
+ return this._shouldLoadLoginHistory;
+ },
+
+ 'setShouldLoadLoginHistory': function(aValue) {
+ this._shouldLoadLoginHistory = aValue;
+ },
+
+ 'tabSelectedHandler': function(anEvent) {
+ if (anEvent.parameters() == 'accountPreferencesTab') {
+ this.renderPreferences();
+ }
+
+ if ((this.shouldLoadLoginHistory()) && (anEvent.parameters() == 'loginHistoryTab')) {
+ this.renderLoginHistory();
+ this.setShouldLoadLoginHistory(false);
+ }
+ },
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+
+});
+
diff --git a/frontend/beta/js/Clipperz/PM/Components/Panels/BasePanel.js b/frontend/beta/js/Clipperz/PM/Components/Panels/BasePanel.js
new file mode 100644
index 0000000..bf60f45
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Components/Panels/BasePanel.js
@@ -0,0 +1,96 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
+if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
+if (typeof(Clipperz.PM.Components) == 'undefined') { Clipperz.PM.Components = {}; }
+if (typeof(Clipperz.PM.Components.Panels) == 'undefined') { Clipperz.PM.Components.Panels = {}; }
+
+//var _Clipperz_PM_Components_Panels_base_id_ = 0;
+
+//#############################################################################
+
+Clipperz.PM.Components.Panels.BasePanel = function(anElement, args) {
+ args = args || {};
+
+ Clipperz.PM.Components.Panels.BasePanel.superclass.constructor.call(this, anElement, args);
+
+ this._user = args.user || null;
+ this._delegate = args.delegate || null;
+ this._tabPanelController = null;
+// Clipperz.NotificationCenter.register(null, 'switchLanguage', this, 'switchLanguageHandler');
+
+// this._ids = {};
+
+ return this;
+}
+
+//=============================================================================
+
+YAHOO.extendX(Clipperz.PM.Components.Panels.BasePanel, Clipperz.PM.Components.BaseComponent, {
+
+ 'toString': function() {
+ return "Clipperz.PM.Components.Panels.BasePanel component";
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'user': function() {
+ return this._user;
+ },
+
+ 'setUser': function(aValue) {
+ this._user = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'delegate': function() {
+ return this._delegate;
+ },
+
+ 'setDelegate': function(aValue) {
+ this._delegate = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'tabPanelController': function() {
+ return this._tabPanelController;
+ },
+
+ 'switchLanguageHandler': function() {
+//MochiKit.Logging.logDebug(">>> BasePanel.switchLanguageHandler [" + this.toString() + "]");
+ this.render();
+//MochiKit.Logging.logDebug("<<< BasePanel.switchLanguageHandler [" + this.toString() + "]");
+ },
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+
+});
diff --git a/frontend/beta/js/Clipperz/PM/Components/Panels/ContactsPanel.js b/frontend/beta/js/Clipperz/PM/Components/Panels/ContactsPanel.js
new file mode 100644
index 0000000..f0eb9c8
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Components/Panels/ContactsPanel.js
@@ -0,0 +1,105 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
+if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
+if (typeof(Clipperz.PM.Components) == 'undefined') { Clipperz.PM.Components = {}; }
+if (typeof(Clipperz.PM.Components.Panels) == 'undefined') { Clipperz.PM.Components.Panels = {}; }
+
+//#############################################################################
+
+Clipperz.PM.Components.Panels.ContactsPanel = function(anElement, args) {
+ args = args || {};
+
+ Clipperz.PM.Components.Panels.ContactsPanel.superclass.constructor.call(this, anElement, args);
+
+ this.render();
+
+ return this;
+}
+
+//=============================================================================
+
+YAHOO.extendX(Clipperz.PM.Components.Panels.ContactsPanel, Clipperz.PM.Components.Panels.BasePanel, {
+
+ 'toString': function() {
+ return "Clipperz.PM.Components.ContactsPanel component";
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'render': function() {
+// var tabPanelControllerConfig;
+
+ Clipperz.YUI.DomHelper.append(this.element().dom, {tag:'table', border:'0', cellspacing:'0', cellpadding:'0', children:[
+ {tag:'tbody', children:[
+ {tag:'tr', children:[
+ {tag:'td', valign:'top', width:'200', children:[
+ {tag:'ul', id:"dataSubMenu", cls:'subMenu', children:[
+ {tag:'li', id:this.getId('contacts'), htmlString:Clipperz.PM.Strings['contactsTabLabel']},
+ ]}
+ ]},
+ {tag:'td', valign:'top', children:[
+ {tag:'ul', cls:'clipperzTabPanels', children:[
+ {tag:'li', id:this.getId('contactsPanel'), children:[
+ {tag:'div', cls:'clipperzSubPanel', children:[
+ {tag:'h5', htmlString:Clipperz.PM.Strings['contactsTabTitle']},
+ {tag:'div', htmlString:Clipperz.PM.Strings['comingSoon']}
+ ]}
+ ]}
+ ]}
+ ]}
+ ]}
+ ]}
+ ]});
+
+// tabPanelControllerConfig = {}
+// tabPanelControllerConfig[this.getId('contacts')] = this.getId('contactsPanel');
+// new Clipperz.PM.Components.TabPanel.TabPanelController({ config:tabPanelControllerConfig, selectedTab:this.getId('contacts') });
+ this.tabPanelController().setUp();
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'tabPanelController': function() {
+ if (this._tabPanelController == null) {
+ var tabPanelControllerConfig;
+
+ tabPanelControllerConfig = {}
+ tabPanelControllerConfig[this.getId('contacts')] = this.getId('contactsPanel');
+ this._tabPanelController = new Clipperz.PM.Components.TabPanel.TabPanelController({ config:tabPanelControllerConfig, selectedTab:this.getId('contacts') });
+ }
+
+ return this._tabPanelController;
+ },
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+
+});
+
diff --git a/frontend/beta/js/Clipperz/PM/Components/Panels/DataPanel.js b/frontend/beta/js/Clipperz/PM/Components/Panels/DataPanel.js
new file mode 100644
index 0000000..759903f
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Components/Panels/DataPanel.js
@@ -0,0 +1,486 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
+if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
+if (typeof(Clipperz.PM.Components) == 'undefined') { Clipperz.PM.Components = {}; }
+if (typeof(Clipperz.PM.Components.Panels) == 'undefined') { Clipperz.PM.Components.Panels = {}; }
+
+//#############################################################################
+
+Clipperz.PM.Components.Panels.DataPanel = function(anElement, args) {
+ args = args || {};
+
+ Clipperz.PM.Components.Panels.DataPanel.superclass.constructor.call(this, anElement, args);
+
+ this._progressWidth = 400;
+
+
+ this.render();
+
+ return this;
+}
+
+//=============================================================================
+
+YAHOO.extendX(Clipperz.PM.Components.Panels.DataPanel, Clipperz.PM.Components.Panels.BasePanel, {
+
+ 'toString': function() {
+ return "Clipperz.PM.Components.DataPanel component";
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'render': function() {
+ MochiKit.Signal.disconnectAllTo(this);
+ Clipperz.NotificationCenter.unregister(this);
+ this.element().update("");
+
+ Clipperz.YUI.DomHelper.append(this.element().dom, {tag:'table', border:'0', cellspacing:'0', cellpadding:'0', children:[
+ {tag:'tbody', children:[
+ {tag:'tr', children:[
+ {tag:'td', valign:'top', width:'200', children:[
+ {tag:'ul', id:"dataSubMenu", cls:'subMenu', children:[
+ {tag:'li', id:'offlineCopyTab', htmlString:Clipperz.PM.Strings['offlineCopyTabLabel']},
+ {tag:'li', id:'sharingTab', htmlString:Clipperz.PM.Strings['sharingTabLabel']},
+ {tag:'li', id:'importTab', htmlString:Clipperz.PM.Strings['importTabLabel']},
+ {tag:'li', id:'printingTab', htmlString:Clipperz.PM.Strings['printingTabLabel']}
+ ]}
+ ]},
+ {tag:'td', valign:'top', children:[
+ {tag:'ul', cls:'clipperzTabPanels', children:[
+ {tag:'li', id:this.getId('offlineCopyPanel'), children:[
+ {tag:'div', cls:'clipperzSubPanel', children:[
+ {tag:'h5', htmlString:Clipperz.PM.Strings['offlineCopyTabTitle']},
+ {tag:'div', cls:'panelDescription', htmlString:Clipperz.PM.Strings['offlineCopyTabDescription']},
+ {tag:'div', id:this.getId('offlineCopyLinkBox'), children:[
+ {tag:'a', id:'offlineCopyLink', href:'#', htmlString:Clipperz.PM.Strings['offlineCopyDownloadLinkLabel']}
+ ]},
+ {tag:'div', id:this.getId('offlineCopyLinkBox_read-only'), children:[
+ {tag:'span', cls:'read-only', htmlString:Clipperz.PM.Strings['offlineCopyDownloadLinkLabel']}
+ ]}
+ ]}
+ ]},
+ {tag:'li', id:this.getId('sharingPanel'), children:[
+ {tag:'div', cls:'clipperzSubPanel', children:[
+ {tag:'h5', htmlString:Clipperz.PM.Strings['sharingTabTitle']},
+ {tag:'div', cls:'panelDescription', htmlString:Clipperz.PM.Strings['sharingTabDescription']}
+ ]}
+ ]},
+ {tag:'li', id:this.getId('importPanel'), children:[
+ {tag:'div', cls:'clipperzSubPanel', children:[
+ {tag:'div', id:this.getId('importPanelMainComponent')}
+ ]}
+ ]},
+ {tag:'li', id:this.getId('printingPanel'), children:[
+ {tag:'div', cls:'clipperzSubPanel', children:[
+ {tag:'h5', htmlString:Clipperz.PM.Strings['printingTabTitle']},
+
+ {tag:'div', cls:'panelDescription', htmlString:Clipperz.PM.Strings['printingTabDescription']},
+ {tag:'div', id:this.getId('printingLinkBox'), children:[
+ {tag:'a', id:'printingLink', href:'#', htmlString:Clipperz.PM.Strings['printingLinkLabel']}
+ ]},
+
+ {tag:'hr'},
+
+ {tag:'div', cls:'panelDescription', htmlString:Clipperz.PM.Strings['exportTabDescription']},
+ {tag:'div', id:this.getId('exportLinkBox'), children:[
+ {tag:'a', id:'exportLink', href:'#', htmlString:Clipperz.PM.Strings['exportLinkLabel']}
+ ]}
+ ]}
+ ]}
+ ]}
+ ]}
+ ]}
+ ]}
+ ]});
+
+ this.tabPanelController().setUp();
+
+ if (Clipperz.PM.Proxy.defaultProxy.isReadOnly()) {
+ this.getElement('offlineCopyLinkBox').setVisibilityMode(YAHOO.ext.Element.DISPLAY).hide();
+ } else {
+ this.getElement('offlineCopyLinkBox_read-only').setVisibilityMode(YAHOO.ext.Element.DISPLAY).hide();
+ MochiKit.Signal.connect('offlineCopyLink', 'onclick', this, 'downloadOfflineCopy');
+ }
+
+ new Clipperz.PM.Components.Import.MainComponent(this.getElement('importPanelMainComponent'), {user:this.user()});
+
+ MochiKit.Signal.connect('printingLink', 'onclick', this, 'printAllData');
+ MochiKit.Signal.connect('exportLink', 'onclick', this, 'exportAllData');
+
+ Clipperz.NotificationCenter.register(null, 'switchLanguage', this, 'switchLanguageHandler');
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'tabPanelController': function() {
+ if (this._tabPanelController == null) {
+ var tabPanelControllerConfig;
+
+ tabPanelControllerConfig = {}
+ tabPanelControllerConfig['offlineCopyTab'] = this.getId('offlineCopyPanel');
+ tabPanelControllerConfig['sharingTab'] = this.getId('sharingPanel');
+ tabPanelControllerConfig['importTab'] = this.getId('importPanel');
+ tabPanelControllerConfig['printingTab'] = this.getId('printingPanel');
+ this._tabPanelController = new Clipperz.PM.Components.TabPanel.TabPanelController({
+ name: 'dataTabPanel',
+ config:tabPanelControllerConfig,
+ selectedTab:'offlineCopyTab'
+ });
+ }
+
+ return this._tabPanelController;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'downloadOfflineCopy': function(anEvent) {
+ var downloadHref;
+
+ downloadHref = window.location.href.replace(/\/[^\/]*$/,'') + Clipperz_dumpUrl;
+
+ if (Clipperz_IEisBroken == true) {
+ window.open(downloadHref, "");
+ } else {
+ var deferredResult;
+ var newWindow;
+
+ newWindow = window.open("", "");
+
+ anEvent.preventDefault();
+
+ deferredResult = new MochiKit.Async.Deferred();
+ deferredResult.addCallback(MochiKit.Base.method(this.user().connection(), 'message'), 'echo', {'echo':"echo"});
+ deferredResult.addCallback(function(aWindow) {
+ aWindow.location.href = downloadHref;
+ }, newWindow);
+ deferredResult.callback();
+ }
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'compareRecords': function(a, b) {
+ return MochiKit.Base.compare(a.label().toLowerCase(), b.label().toLowerCase());
+ },
+
+ 'logo': function() {
+ var result;
+
+ if (Clipperz_IEisBroken == true) {
+ if (Clipperz.PM.Proxy.defaultProxy.isReadOnly()) {
+ result = "<span><span class=\"clipperzLogoSpan\">clipper</span><span class=\"clipperzLoggoZSpan\">z</span></span>";
+ } else {
+ result = "<img src=\"./images/exportLogo.png\" />";
+ }
+ } else {
+ result = "<img src=\"data:image/png;charset=utf-8;base64,iVBORw0KGgoAAAANSUhEUgAAANYAAABOCAIAAADTtH9XAAANIWlDQ1BJQ0MgUHJvZmlsZQAAeJyV13k0lG8bB/BrFsYyZhhjDyO77LKHLJFItmwp2bdhJiZRypIUIkso2iiSFC0kEtWPLCHJkq2oyJI9kmXeP6R6f+f9ve95rz+ecz3385xz389zzud7nxsAr+FKpZKRABAQSAuyNjEgOTg6kTBdgAJewAEzaLi6B1P1LS3N4R9roRMQAADtcq5UKvmf3/uPhQtycHQCQMgCANF7vd8OAES39d4WAIhHaFQaAMIHAIjuPq4eAIhwAJANsrU2BEAUAADOe70vBwCc23pfDwC4EHdvGgCiG4CREOjhGwiAmQBg1PXwDHYHwMkCgIdHsHsAAC4ZACwCAigeALgPACDlTg2iAeCZAEDOwdGJtL7kffEAW/kAmMx+jx1JByjNAZDa/XtM9BEAtytAbuLvsTlrQAAAgrs12EtFGQAAEFgDAIYBOn1OAgCTCrCaQqcv59Lpq9cBUH0ANWT3w0EhP/8XAtEM8L/u17/5Z6EQAEgAhBgiH3kUFY4OZzjBGImJZjrJbMRcy3Ka9Qw2ju0srozdhyOFkMKZSjzPlc6dzpPJW8tPEcjelC14WaiedFgkd/N10VbxYxL5km3SJ2Rub+mUi5a/o9CjdFr5vsp71bNqZeqDmklaFdrDOmm6T/XG9DMMnhtO7sgyrjOZNb26q9FsYXeuRcue15avrdqsV2wL93bYddp3OXQ7offdc+7b339gwOX9wQ9uWPfHHp88P3sNe4/4fPEd9eciPwv4GjhJmaJOH5oJmg2ep80f/haycGQx9HvY0tEfx1bCV46vRkhHdkQjTiJjUKfQsQynGc9g4pjimRNYzrImYpPYzuGS8SnsqRxphPOc6cQMrkzuCzwXebP4svkvCVzedEXwqtA14RxSrsj1zTdE88TyxW9KFkjekiqUvi1ze7yIfEf2rlyxQoniPaX7Sg+UH24tVS1TK1t4FFKu/lijQqtS+8m2qm1PdZ6uVUfU6D3b/lz/hcFfhrXo2pi6HS+N600aTBtNm1iaEl6ZNZu3WLTiWs+9tmyzemPdTmhPfWvTYdu5t4u7K7Pb/p1Dj1Mvf292n3O/88D+90Lvr35wGTw4JDKU+9Htk/tnj2Hx4fwRry/eoz5j0mOF434T/l/Jk3KTd6cCpykz1Fml2ftzQfPB32gLqgtliyHfQ5fCfoQtay1XrhxbDV/TWXtKpwMgRJE45DSqCX2bIY0xHOPNZMtsyLKVVRIrycaL48HzsvNycBEkOKWIGlzm3Ad4gnmT+Ir5mwRGBTmF1IS9SRdEXooixHTED0nck5ySlpIhb6mUQ8nrK6QoDipLq8Ru7VKTUadq1GrxaIdue6XLrUfZ/txAzPCYUZuxkEnozirTJTMlc8/d6RZtljgrE+tQmzzbt3Ys9tsdDjledqrbN7Vf+MAel6MHc11r3UY9uDz1vBy8T/hc863x6/dfCuAM3EIxovocCg9KDs6llR6uD+k9Mha6cBR1jCOcdFz2hGrE9kizqD3R+04ejPE8RY6lnQ46ExkXGX8yIe5samJCUta5i8mZKSmpl9JSz2ekX8goyLx54e7Fgqzb2cWXnlx+cqX26qtrbTntue3X22/05n3KH7k5VPD51lThzO2posk7s3enisdLJu6N3B98MPSwp7StrOFRTfmjx8UVlypTn0RWBTzdV21Ws+2ZzHPC86UXH/5qrH1Yl/YyqN6mQa1RoJHe1PPqYXN8i1OraOvw6wdtx9/saMe197+91uHXqdK52tXcnfZuf490z1xvRV90v9kAcWDg/a0PwYPaQ+ihxo/nPx34LPl5YrhiJOrLrlGu0f6xG+PkCdWJta8Nk6lT+6bFpidmHsyGz5nME+a7v+UtUBY1v6O+v1xK+bFvWXT560rZauSaKZ2bTgeAk4hQ5FGUNqoCfZxBj6GaMQpzismYqZY5luU0azx2F7aJLRGXiE9i38PeypFMSOVMI6Zx2XK95c7gyeC9wJfFny2QvemSoLNgv9BV4WukHJGczTmi18VuiOdJ5EvelCqQviXjKzO2pVC2SO6O/F2FYsUSpXvK91UebH2oWqZWpl6mEarxXbNCq0K7ctsTnSrdE7pretXba/SfGTw3fGEUswO9o9a4zuTlznrThl2NZgnmWPNXu5stWva0WiZbsVu1Wb+xabd9u7fTLsOe277LodvxnVPPvmxnAee+/f0H3rt8OPjBNcdNxG3I/aPHJ8/PXvneEusJ4jfmf5ssS574txSZ+5Ui5WEaYUtHfxxbDl85vnpiLYIeBdHIX0mCOYOJY4priN+VwHoWm4hNYjuHT2ZP4fiVJdyZPBd4f2bJpj+zJHfouvsN0TyxfImbEhtpUiR7R+6u/B9ZolK6tUz1kXq5+mONCs1K7SfaVdue6lbr/pEjO+qMXxrXmzTsbDRtMnsV0rK51eK1ZZvlG6v24x0ynXZd9t3RPQq9Tn2xAyrv4wZVh85+8hjWHkkZ9R33+0qeoszEzzstnFtKWLWm0wHW9z4AAEY1gIwtAHZZADa5ALFbACRdALgLACzZAGw1AckgBEgdKiB26WzsH4AAdhAEeTAARwiGZCiB7wgSwgwRiihAtCBGkHikCTIKWYVcQemgolB1qBW0CNoRnY/+xmDMcIqhmGGK0YQxh3EYw4VxxlQxYZg0mWKYxpm1mCnMNSxyLJEs5aw41ijWd1giNhD7hW0H20m2QZwr7jkehffCT7BbsWewr3LEccwStAh5nOqceZxTRBfiIpcvVxn3Fu6XPF68GN5CPnG+I3zz/JcFTATmNl0TFBMMF0IIlQr7kURIPSLnN2/eHCmKF20VSxHfK8EvMSR5W8pQ6pa0gQyHzOCWB7Kn5ZzlVRSwCiOKfynlKkereGw1UZVV41RbUR/WyNTEadZolWjnbDuvc0Y3Qu/I9kP6ZANfQx8jnx3+xoEmtJ3HTGN2nTPLNr+1u9yiYU+f5Yw1xkbIVmOvjR3VPsnhruNrpzln3v26B7xckg9Wun5x5/Ew8QzzKvLl9bP0jyfXBiIp+tSoQy+CGWlmh1NDxcIoR5+Esxx3OlEUQY+yjUGeco59dIYz7lB8W2J60lKyS0pdmsL5rMzgCx+zbLJrr9y9Jp5z+TpPPvvNpFu4wnN3MosFS27clys1Kmsrd308U8XztKjG4AWtFl9XVL+rKb5ZrqXtdUh7XQe1S6C7vk+iv/t9/KDep6Jhjy/Coz1f7aa4p7tms+ZdFieWSpcj6Lx0OgAggQV4QBr0wAEOQzqUwwACg1BEuCCSENWIOaQM0gWZhXyLwqN2o86imtFs6D3odHQvA4nBl6GE4TujIeM5xncYccxhzAsmApMHUzkzK7Mz810WNMsBloesLKzurNVYLiwV28wmw5bINoEzxxXj2fAUfCf7dvYbHDiOEI5egjHhHieJM5VzjRhM/MrlxzXGTeae5aHxLPAe5UPwneXn5y8U0BSo22S3aVQwUohPqEzYSniMFCsiIVK/OVCUR/SpmLs4VvyZRKCksOQbqThpA+lVmcot4bI6soty1fJnFGwVRRSnlKqVU1T8thqpCqkuq3WoP9a4rBml5a1tv01HR0FXRI+wHa2P0p81mDGcMhrfMWw8ZzK+89supBnRnGe3koXunj2W1lb+1mE22bb3976y67VfcSQ6KeyzcD60/+KBWpcRV2Y3RXcfjyzPaq9pH2lfT79M/44AgcC9lGzqlyCp4BBaQ4jgkeDQxqOix5LCx044RtRHqUXnxRBOJZ0mnMmI503ITlRNakn2TPmRlpiunvH5wpUsv0t7r0hfY8iZuP48r/TmxVuxt93vOBcb39N4sLVU/pHcY6lK8SqpasVnei921lq9JDccakppvtb6pG2gnd4p3K3T49GXMFDxYeIj32eDkcjRgvFPk/zTXrNX5ocXpZYCl8vWEHQ6ADACOwiCAThCMpTAmw37G+7X1aPxaEf0NwZjhqyf3tcwzkzCTDFM48y2zDUsciyXWHGsUayL2EDsFzYPnCvuI94LP8EezL7KEUfgJuRxqnM2El2Ii1zJv0xb8M3/9GwphBAq/WnZal3yT8ch0gZ/Gv4t+KffN5o1WiW/7f6W+89u/5ta70FfXj/Lv6sN6fm72+jCP+WeVf4tN4Nxw+5lzQ29N9I2/BYRNgQ/KN8wXHlyXfGzng3HDaNN8a/+as5oaXsd8kawva6D2lnSFdtd3xPSJ9HvP2D0Pn5Qb+j0R7dPRZ8Xhtu/CI/6j5mOS01gvtpN5k/FTnvP7JyVmWOdm5x//e3BQsai7eLE95glgx+SP4aXI1Z4V66scqzGrC6u3aAn0OkA6+clAABgMaSQKUEkc0Oj//Ow978qgHx4Yw4kAGA9A/faAAABAKR8aaa2AEAEAC0wBAqQgQJBQAJzMASjn1cSuP964guwfpYDAGBkB7hkDwBQ/f1Y5N/npXmG0gAADCnUsCBfbx8aSZ9KJXuSDCkB1MM0zyBZkmmgu7wsSVlRURUA4F93RgACxGzQPQAAAAlwSFlzAAALEwAACxMBAJqcGAAAC25JREFUeJztnHlUE9cex38JYY2JGhQ14Hae1BSXKoK4C0UtbtRqRUWlomi1NK5Y6tKKQpG2qK0pWo8oPp+ix+rRFlCPyxEVV9TXpx7klOdxKQFERQ1CWMLM+wMfDZk7k5nJMsHez8k/+d3f/d1fJt+5d+6SiEiSBAxGOMRCJ4D5u4MliBEYLEGMwGAJYgQGSxAjMFiCGIHBEsQIDJYgRmCwBDECgyWIERgsQYzAYAliBAZLECMwWIIYgcESxAgMliBGYLAEMQKDJYgRGCxBjMBgCWIEBksQIzASoRN4w+93X25YpWkl8zCyifr37bDsy5mcfDAtDkeRYFFRmVZbbmKsrixeBjM5+WBaHI4yEJNg/ufMbHwwLQ5HkSDmb0uLl6BM1kroFDAW0ZIkqNfXU43FJU/snwnGijjKdIQNUTP6hoelmhjdXEWCJIOxFi1JgiIRtFW4Cp0Fxsq0pIEY81ZitV5QV0nmZOUfz877o/CBkZlQqbpMmDB0TJh/a4UHbWV2NBBQ/PiFi4uzkU3k7ka2UTSbkehr4GnZC2cjt/q6ui7d2gKIAOB5heHg/tyjR85W6l43JRkYqPpkTlhAUA+RmHZYt1FYJNoS/bEjl86culqi/etJVy53DwsLipg+onO39szVmVMFgCfl9ds0x07kXGh8HxTos3VHPAmkqP4uiC0YZ5ze4VFJZPn/CxaX1EVFrqv669LTYUhPX9HHvwey7NDRe5sSt5kYO3s7H87a3PT2n5m3t6XuNPGRy+tO5+4wtiDdzp5Z79FW8WF4crm2lCHFz2PHzZ43Fllko7AmXLqiXRqbYm5sMqSlqQMG+9EVI1PNyV7bTtmhpg6mTjHNtvE6G8iHkp+6s0mSFnUDj3HV0oE4OeXklAkrWOgPACQxMT9GRyYBSfBry93dmWr0UXZg4/bgYfWAAWpmoQDAT2nHRwerkRnaKGwTBgImTkxebl5/ACCJjd2++FPTmRlzqq1kHroqGDGINlsnEaKWHbBIgtMjt/56KIdTlYLCJ0EDFvBWIZXKSjbqh5iYb13YBdTpYHTIEpatWytsTR0MCjAvZWOu5T/6eOIXrN2JoiJd8HC1Ay4f8Jfg0hUHHxQW8arqHj3za97t2gGdDhZ/utFuYQkShg5SO3EP+KdWv3rFD+x8xTExKcL0cubgKcF7RdVXzl2iKw0J6bciLnLs+BF0DgWFr67k3uDXtOXI5a5zosctip3aybsTnc+1/JJnHBe9eYddHneQblYYGKj6LHby8rjZdDHPnrtfdPc+pzzpaCARK/92gOeMeMa0eOTEKXx8/zUb5v5/4gXrEqfuz7ylSc2gen6dsOt0bgC/1i3AkJX9jZdS0fhmzrwRryrh/ZFq5FVYGafJyEyyddjyCkDezEGBXX9IWyaWvOkcp0UOLC6p/2jCcmqfMSsq8dqtPezybIa3dzsSxFptuUzmAQASUTdQmx5EMkICUA0aH8aQfHo0PhJ8XNKA1F9oiO+axLnGFhHArEj/1/r6jLR9Js46HQkkASJ7LkwaLl3eLHFzNza1lsG1G5qgAIRcCgpfNNTVObmYfdizKOyqVbuoEUNDfJM3LTYx+iidcy9rQoZQn+dkL8sr2ngpzOX5hs7erXfsivf0kqEKmZZ7nh+f5MlQrK5imYAJfBSwadMvKHNt8iY10j9qdhBq4cf55dOXPFrnzfa0hSZCaUQihqPZW1A1xKdy8mwattYAd/J/pzjUJ6d+jmxL6gbhEROo9j27s8zm2Uj4+D6Hs5Jo9MeELi/S8/4F2mJ1OQDPdV8+EryIGjji46Y0rXya4OECfQPfk8ulMqMXAOHqbs/dtlr/wX3pyrooJa5yxImbQ7/k2jTsvUId9ZLFRAczDA6fxX5ANR44dAlYHKaUyw1rEheYdaNSdS9B/u8DtMULbzN3n8xwHoiratB1RocFMdRK3xHDtSHrEhriR3eHNKJe8klqYpqdw2ZlX6Ea0zMudvTp+bxCh6pB3ClATpKcSEODSGLm20zfGc/sgISoyJKeWU9bPPM3cO7DI2wTnCX4SkeiLnm9rK3ckjxszfBhtH1VIyNHqlITTY0FhcUAJIPILAx75dJNVCVxUuJu5rAUJM/Kn7enrNI3R9/VtyvHsAD1d8T7w2lLx34HiomcYzaH80AskSC/DwOIHHDV0xh+8x4XMLOBaVFYpRnRcMBZYmbVz0/VkbnDpkKCFn6mv8f6z4AeKzkFRML5Crq7Ih46eHw8O+PX27LdT9uElbZCzGNsRGVlNSd/EqprGZZglO/BsExLcwIAHhKsrEIMxAWF5WwehwXkZn6BA4YtK31mrUwMBjMLy5EzRrOPRgDxTCN1oyt2bwNTqBN5nljrsJYYSNLhx2ImDAa02cIPxSNsUKDyx+2rDAYOtzRBgCutXvhQlu6pZCiOeW7FtjhLsJUUee2cn5U+bUf/ZLNFc/FgxiETY0rytJCwYVwT4EfmgbOTI5mOS2VlXaca/VRK5gcMC8OGhAZlUPbZgwa+KxKDs4tg9/OTI/2UevolW3WVdU86c44llwKyx9+39yRDrb0U/QFAn76+XFvnzZ9aPVFXx+Dwc9q/UGYzJ3osDDsqtB+1bGvaMeZGCQJqa0jjV4PBaiePKvIiO5T8h7ZYXcx7CZoOPnL+YHwo1Xjg0HVDjR7pX1IOqE0ug6dXGx6t80WckriHruzClTLkNtyCBZNsGrZbF1eUdmSPih4xNBkQoB4xZLHxK2zUInN5sqL6v98rGJag5+cDeFulIWP4SHDZMuQXIx46ZBF1UlJvgAlhiI27zt5SkcSuv0X6NefOiaPnqfbScmJl7DeoGobBIxC9lBXDSsQQirqfI6al6GkmsEtXZFJXXzYkzDebp1mIiiyPE/QHEOdeBDebHCvhMx3xUkA3le9DxGFBWZD/or171/Ts1RlEQBCQe+HhquWbkAtW69cLsF+SkHj4+MmbSRsXNv6QpaYG9u2/vDMNfd+HhviCmNX1sSTsV2smncs5S/GSBI+Mnxs9Jnr+OBc3JwAgCLh6rXhJ7LeoPqN28Eh/NnkyQAJZtT+caef48RmoRD5UNGfgDvM+zeE5I965c/Ho4chDCc5RUd+ZrS6XG3r5q/g1bSHX8x+MGcVqn2rdhoV2CCt1g+nRHx/MOEz13J1xanfGKWMLcsxKSZ5jlQNH6Ll7Ewx7dMYM3M51aOWZulwKSZt5r4wTJ05uNu8lKAlfTXGVWvm5my7sMvVI5GkGNvip2oaEDbE4LyHhf/eMDu6SmraaR8Xs7ATk6SYbw2HOOCNi4NiPgu0Z9nzuxvb0Z63pkMshI5Nd5+TAWNSBDx/cKfvM1gbW/n6qDpevbm6vRB7sYbMMxn+pLCV5RvYZDRvPL+I+XPrlbDuHFQFkZ62eH8vhjxInju9/OldjxX1Rof5Yw9JniPYK0Y1bmm3pazt6M+24v6vq9Fv2+ozMtU4u6N30jh0RCzQmu/hsfOh4UVHZXgF51zWTI8LofAID/3Hu/PdTIkexCWiLsDHzBuVe1syKnsS8MTItYnje5S1rmx9QN8YddRATaTTGzLMgWzjfElb4KXsTBAFlZdVFf2hfvdC5uruVasu9vT1VKh+fLgp7ns9H/io+Pm5c0zYGSUJpafWd2w9q9TXV+jpPhZRNkjYKS0dVFfnwwVNt8dMafTUJkhq9vnt3r3d6erdRuDn4iRCuWLP3FYtBqfRQKpv2PHpZMbgVEYka87RyetYNK5WKevX26tXbyyrRHBn8t0YYgcESxAgMliBGYLAEMQKDJYgRmLdQgno90wE+RwuLaUn/Nc2S4UN8n0a8LzXain1dVeMf2Nsxw2KsuTSNwfDgLRyIMS0LLEGMwGAJYgQGSxAjMFiCGIHBEsQIDJYgRmCwBDECgyWIERgsQYzAYAliBOZ/jys2NWyvP3gAAAAASUVORK5CYIIK\" />";
+ }
+
+ return result;
+ },
+
+ 'progressWidth': function() {
+ return this._progressWidth;
+ },
+
+ 'updateProgress': function(aProgressComponent, aPercentage) {
+
+
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'printAllData': function(anEvent) {
+ var newWindow;
+ var allRecords;
+
+//MochiKit.Logging.logDebug(">>> printAllData");
+ newWindow = window.open("", "");
+ newWindow.document.write(
+"<html>" +
+"<header>" +
+" <title>Clipperz export data</title>" +
+"<style>" +
+"#exportedData {" +
+" width: 600px;" +
+"}" +
+".ext-mb-progress-wrap {" +
+" border:1px solid #6593cf;" +
+" margin-bottom: 10px;" +
+" width: " + this.progressWidth() + "px;" +
+"}" +
+".ext-mb-progress {" +
+" height:18px;" +
+" background:transparent url(./images/default/basic-dialog/progress2.gif) repeat-x 1px 1px;" +
+"}" +
+".ext-mb-progress-bar {" +
+" height:18px;" +
+" overflow:hidden;" +
+" width:0;" +
+" background:#8bb8f3;" +
+"}" +
+"body {" +
+" font-family: sans-serif;" +
+"}" +
+"div#logo {" +
+" border-bottom: 1px dotted #aaaaaa;" +
+" margin-bottom: 15px;" +
+"}" +
+"div.recordBlock h2 {" +
+" font-size: 14pt;" +
+" margin: 0px;" +
+" padding: 0px;" +
+" border: 0px;" +
+" color: #666666;" +
+"}" +
+"div.recordBlock div.recordNotes p {" +
+" margin: 0px;" +
+" padding: 0px;" +
+" border: 0px;" +
+" color: #aaaaaa;" +
+" font-size: 10pt;" +
+" line-height: 18pt;" +
+" border-left: 1px solid #aaaaaa;" +
+" padding-left: 10px;" +
+"}" +
+"div.recordBlock dl {" +
+" margin: 0px;" +
+" padding: 0px;" +
+" border: 0px;" +
+" color: #999999;" +
+" padding-bottom: 10px;" +
+" border-bottom: 1px dotted #aaaaaa;" +
+" margin-top: 10px;" +
+" margin-bottom: 15px;" +
+"}" +
+"div.recordBlock dl dt {" +
+" display: block;" +
+" float: left;" +
+" min-width: 100px;" +
+" white-space: nowrap;" +
+" overflow: hidden;" +
+" margin-right: 10px;" +
+" font-size: 10pt;" +
+" line-height: 18pt;" +
+"}" +
+"div.recordBlock dl dd {" +
+" color: #666666;" +
+" font-size: 10pt;" +
+" line-height: 18pt;" +
+"}" +
+"" +
+"</style>" +
+"" +
+"<!--[if IE]>" +
+"<style>" +
+"div.recordBlock dl dt {" +
+" width: 100px;" +
+"}" +
+"</style>" +
+"<![endif]-->" +
+"" +
+"</header>" +
+"<body>" +
+" <div id=\"logo\">" + this.logo() +
+" <div id=\"progressWrapper\"><div class=\"ext-mb-progress-wrap\"><div class=\"ext-mb-progress\"><div id=\"progress\" class=\"ext-mb-progress-bar\">&#160;</div></div></div></div>" +
+" </div>" +
+"</body>" +
+"</html>"
+ );
+
+ anEvent.preventDefault();
+
+ allRecords = MochiKit.Base.values(this.user().records());
+ allRecords.sort(this.compareRecords);
+
+/*
+ deferredResult = new MochiKit.Async.Deferred();
+ MochiKit.Iter.forEach(allRecords, MochiKit.Base.partial(function(aDeferredResult, aWindow, aRecord) {
+ var printerRecord;
+
+ printerRecord = new Clipperz.PM.Components.Printing.Record({record:aRecord});
+ aDeferredResult.addCallback(MochiKit.Base.method(printerRecord, 'deferredDrawToWindow', aWindow));
+ }, deferredResult, newWindow));
+ deferredResult.callback();
+
+ return deferredResult;
+*/
+
+ MochiKit.DOM.withWindow(newWindow, MochiKit.Base.bind(function(someRecords) {
+ var currentWindow;
+ var deferredResult;
+ var progressBar;
+ var progressWrapper;
+ var i, c;
+
+ currentWindow = MochiKit.DOM.currentWindow();
+ progressBar = MochiKit.DOM.getElement('progress');
+ progressWrapper = MochiKit.DOM.getElement('progressWrapper');
+
+ deferredResult = new MochiKit.Async.Deferred();
+ c = someRecords.length;
+ for (i=0; i<c; i++) {
+ deferredResult.addCallback(function(aWindow, aRecord) {
+ var printerRecord;
+
+ printerRecord = new Clipperz.PM.Components.Printing.Record({record:aRecord});
+ return printerRecord.deferredDrawToWindow(aWindow);
+ }, currentWindow, someRecords[i])
+ deferredResult.addCallback(MochiKit.Base.bind(function(aProgressBar, aProgress) {
+ MochiKit.Style.setElementDimensions(aProgressBar, {w:aProgress * this.progressWidth()});
+ }, this, progressBar, ((i+1)/c)));
+ deferredResult.addCallback(MochiKit.Async.wait, 0.2);
+ }
+
+ deferredResult.addCallback(function(aWindow, aProgressWrapper) {
+ MochiKit.DOM.replaceChildNodes(aProgressWrapper);
+ MochiKit.Style.hideElement(aProgressWrapper);
+ aWindow.stop();
+ }, currentWindow, progressWrapper);
+
+
+ deferredResult.callback();
+ }, this, allRecords));
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'exportAllData': function(anEvent) {
+// var deferredResult;
+ var newWindow;
+ var allRecords;
+
+//MochiKit.Logging.logDebug(">>> printAllData");
+ newWindow = window.open("", "");
+ newWindow.document.write(
+"<html>" +
+"<header>" +
+" <title>Clipperz export data</title>" +
+"<style>" +
+"#exportedData {" +
+" width: 600px;" +
+"}" +
+".ext-mb-progress-wrap {" +
+" margin-top:4px;" +
+" margin-bottom: 10px;" +
+" border:1px solid #6593cf;" +
+" width: " + this.progressWidth() + "px;" +
+"}" +
+".ext-mb-progress {" +
+" height:18px;" +
+" background:transparent url(./images/default/basic-dialog/progress2.gif) repeat-x 1px 1px;" +
+"}" +
+".ext-mb-progress-bar {" +
+" height:18px;" +
+" overflow:hidden;" +
+" width:0;" +
+" background:#8bb8f3;" +
+"}" +
+"</style>" +
+"" +
+"<!--[if IE]>" +
+"<style>" +
+"</style>" +
+"<![endif]-->" +
+"" +
+"</header>" +
+"<body>" +
+" <div id=\"logo\">" + this.logo() + "</div>" +
+" <div id=\"progressWrapper\">" +
+" <div class=\"description\">" + Clipperz.PM.Strings['exportDataInProgressDescription'] + "</div>" +
+" <div class=\"ext-mb-progress-wrap\"><div class=\"ext-mb-progress\"><div id=\"progress\" class=\"ext-mb-progress-bar\">&#160;</div></div></div>" +
+" </div>" +
+" <div id=\"textareaWrapper\">" +
+" <div class=\"description\">" + Clipperz.PM.Strings['exportDataDescription'] + "</div>" +
+" <textarea id=\"exportedData\" cols=\"80\" rows=\"20\">[</textarea>" +
+" </div>" +
+"</body>" +
+"</html>"
+ );
+
+ anEvent.preventDefault();
+
+ allRecords = MochiKit.Base.values(this.user().records());
+ allRecords.sort(this.compareRecords);
+
+ MochiKit.DOM.withWindow(newWindow, MochiKit.Base.bind(function(someRecords) {
+ var currentWindow;
+ var deferredResult;
+ var textareaWrapper;
+ var textarea;
+ var progressBar;
+ var progressWrapper;
+ var i, c;
+
+ currentWindow = MochiKit.DOM.currentWindow();
+ textarea = MochiKit.DOM.getElement('exportedData');
+ textareaWrapper = MochiKit.DOM.getElement('textareaWrapper');
+ MochiKit.Style.hideElement(textareaWrapper);
+ progressBar = MochiKit.DOM.getElement('progress');
+ progressWrapper = MochiKit.DOM.getElement('progressWrapper');
+
+ deferredResult = new MochiKit.Async.Deferred();
+
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("exportAllData - 1: " + res); return res;});
+ c = someRecords.length;
+ for (i=0; i<c; i++) {
+ deferredResult.addCallback(MochiKit.Base.method(someRecords[i], 'deferredData'));
+ deferredResult.addCallback(MochiKit.Base.method(someRecords[i], 'exportedData'));
+ deferredResult.addCallback(MochiKit.Base.bind(function(aTextarea, aProgressBar, aProgress, someRecordExportedData) {
+ aTextarea.value = aTextarea.value + "\n" + someRecordExportedData + ",";
+ MochiKit.Style.setElementDimensions(aProgressBar, {w:aProgress * this.progressWidth()});
+ }, this, textarea, progressBar, ((i+1)/c)));
+ deferredResult.addCallback(MochiKit.Async.wait, 0.2);
+ }
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("exportAllData - 2: " + res); return res;});
+ deferredResult.addCallback(function(aTextareaWrapper, aTextarea, aProgressWrapper) {
+ aTextarea.value = aTextarea.value.slice(0, -1) + "\n]";
+// MochiKit.DOM.replaceChildNodes(aProgressWrapper);
+ MochiKit.Style.hideElement(aProgressWrapper);
+ MochiKit.Style.showElement(aTextareaWrapper);
+ aTextarea.focus();
+ aTextarea.select();
+ }, textareaWrapper, textarea, progressWrapper);
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("exportAllData - 3: " + res); return res;});
+ deferredResult.addBoth(function(aWindow) {
+ aWindow.stop();
+ }, currentWindow);
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("exportAllData - 4: " + res); return res;});
+
+ deferredResult.callback();
+ }, this, allRecords));
+ },
+
+ //-------------------------------------------------------------------------
+
+ __syntaxFix__: "syntax fix"
+
+});
+
diff --git a/frontend/beta/js/Clipperz/PM/Components/Panels/LoginPanel.js b/frontend/beta/js/Clipperz/PM/Components/Panels/LoginPanel.js
new file mode 100644
index 0000000..84b2475
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Components/Panels/LoginPanel.js
@@ -0,0 +1,1114 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
+if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
+if (typeof(Clipperz.PM.Components) == 'undefined') { Clipperz.PM.Components = {}; }
+if (typeof(Clipperz.PM.Components.Panels) == 'undefined') { Clipperz.PM.Components.Panels = {}; }
+
+
+Clipperz.PM.Components.Panels.LoginPanel = function(anElement, args) {
+ args = args || {};
+
+ Clipperz.PM.Components.Panels.LoginPanel.superclass.constructor.call(this, anElement, args);
+
+ this._showLoginFormAnimator = null;
+ this._showRegistrationFormAnimator = null;
+ this._shouldShowRegistrationAlert = true;
+
+ this._visibleForm = null;
+// this._isPassphraseVisible = true;
+
+ Clipperz.NotificationCenter.register(null, 'switchLanguage', this, 'switchLanguageHandler');
+
+ this.render();
+
+ return this;
+}
+
+//=============================================================================
+
+//MochiKit.Base.update(Clipperz.PM.Components.Panels.LoginPanel.prototype, {
+YAHOO.extendX(Clipperz.PM.Components.Panels.LoginPanel, Clipperz.PM.Components.Panels.BasePanel, {
+
+ 'toString': function() {
+ return "Clipperz.PM.Components.LoginPanel component";
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'render': function() {
+ var result;
+ var layout;
+ var registerButton;
+
+ MochiKit.Signal.disconnectAllTo(this);
+ this.element().update("");
+
+//MochiKit.Logging.logDebug(">>> LoginPanel.initPanel");
+ Clipperz.YUI.DomHelper.append(this.element().dom, {tag:'div', id:this.getId('baseDiv'), cls:'LoginPanel', children:[
+ {tag:'table', children:[
+ {tag:'thead'},
+ {tag:'tbody', children:[
+ {tag:'tr', children:[
+ {tag:'td', valign:'top', children:[
+ {tag:'div', cls:'clipperzServiceDescription', htmlString:Clipperz.PM.Strings['clipperzServiceDescription']}
+ ]},
+ {tag:'td', valign:'top', align:'right', children:[
+{tag:'div', id:this.getId('forms'), cls:'clipperzLoginForm', children:[
+ {tag:'div', id:this.getId('loginForm'), cls:'loginForm', children:[
+ {tag:'div', cls:'loginFormHeaderBox', children:[{tag:'h3', htmlString:Clipperz.PM.Strings['loginFormTitle']}]},
+ {tag:'form', id:this.getId('loginForm_form'), autocomplete:'off', children:[
+
+ {tag:'table', cls:'formLayout', children:[
+ {tag:'thead'},
+ {tag:'tbody', children:[
+ {tag:'tr', cls:'formFieldTR', children:[
+ {tag:'td', width:'90', htmlString:Clipperz.PM.Strings['loginFormUsernameLabel']},
+ {tag:'td', children:[
+ {tag:'input', id:this.getId('login_username'), cls:'loginFormField', type:'text', name:'username'}
+ ]}
+ ]},
+ {tag:'tr', cls:'formFieldTR', children:[
+ {tag:'td', htmlString:Clipperz.PM.Strings['loginFormPassphraseLabel']},
+ {tag:'td', children:[
+ {tag:'div', id:this.getId('passphraseDIV'), children:[
+ {tag:'input', id:this.getId('login_passphrase'), cls:'loginFormField', type:'password', name:'passphrase'}
+ ]},
+ {tag:'div', cls:'oneTimePassword', id:this.getId('oneTimePasswordDIV'), children:[
+ {tag:'input', type:'text', id:this.getId('oneTimePassword_1'), name:'passphrase'},
+ {tag:'span', html:'-'},
+ {tag:'input', type:'text', id:this.getId('oneTimePassword_2'), name:'passphrase'},
+ {tag:'span', html:'-'},
+ {tag:'input', type:'text', id:this.getId('oneTimePassword_3'), name:'passphrase'},
+ {tag:'span', html:'-'},
+ {tag:'input', type:'text', id:this.getId('oneTimePassword_4'), name:'passphrase'}
+ ]}
+ ]}
+ ]},
+ {tag:'tr', cls:'formFieldTR', id:this.getId('passwordTypeChooserTR'), children:[
+ {tag:'td', valign:'top', align:'right', children:[
+ {tag:'input', type:'checkbox', cls:'passwordTypeCheckbox', id:this.getId('useOneTimePasswordCheckbox')}
+ ]},
+ {tag:'td', children:[
+ {tag:'div', cls:'passwordTypeChooser', children:[
+ {tag:'h4', htmlString:Clipperz.PM.Strings['loginFormOneTimePasswordCheckboxLabel']},
+ {tag:'span', htmlString:Clipperz.PM.Strings['loginFormOneTimePasswordCheckboxDescription']}
+ ]}
+ ]}
+ ]},
+ {tag:'tr', children:[
+ {tag:'td'},
+ {tag:'td', children:[
+ {tag:'div', id:this.getId('login_submit')}
+ ]}
+ ]}
+ ]},
+ {tag:'tfoot'}
+ ]}
+ ]},
+
+ {tag:'div', cls:'loginFormFooterBox', children:[
+ {tag:'ul', children:[
+ {tag:'li', id:this.getId('showRegistrationLI'), children:[
+ {tag:'span', htmlString:Clipperz.PM.Strings['loginFormDontHaveAnAccountLabel']},
+ {tag:'a', href:'.', id:this.getId('showRegistration'), cls:'clipperzActionLink', htmlString:Clipperz.PM.Strings['loginFormCreateOneLabel']}
+ ]},
+ {tag:'li', children:[
+ {tag:'span', htmlString:Clipperz.PM.Strings['loginFormForgotYourCredentialsLabel']},
+ {tag:'a', href:Clipperz.PM.Strings['loginFormAarghThatsBadUrl'], target:'Clipperz_Help', htmlString:Clipperz.PM.Strings['loginFormAarghThatsBadLabel']}
+ ]},
+ {tag:'li', children:[
+ {tag:'span', htmlString:Clipperz.PM.Strings['loginFormAfraidOfMaliciousScriptsLabel']},
+ {tag:'a', href:Clipperz.PM.Strings['loginFormVerifyTheCodeUrl'], target:'Clipperz_Help', htmlString:Clipperz.PM.Strings['loginFormVerifyTheCodeLabel']}
+ ]}
+ ]}
+ ]}
+ ]},
+
+
+
+ {tag:'div', id:this.getId('registrationForm'), cls:'registrationForm', children:[
+ {tag:'div', cls:'loginFormHeaderBox', children:[{tag:'h3', htmlString:Clipperz.PM.Strings['registrationFormTitle']}]},
+ {tag:'form', id:this.getId('registrationForm_form'), children:[
+ {tag:'h5', cls:'errorMessage', id:this.getId('registration_errorMessage')},
+ {tag:'table', cls:'formLayout', children:[
+ {tag:'thead'},
+ {tag:'tbody', children:[
+ {tag:'tr', cls:'formFieldTR', children:[
+ {tag:'td', width:'90', htmlString:Clipperz.PM.Strings['registrationFormUsernameLabel']},
+ {tag:'td', children:[
+ {tag:'input', id:this.getId('registration_username'), cls:'loginFormField', type:'text', name:'username'}
+ ]}
+ ]},
+ {tag:'tr', cls:'formFieldTR', children:[
+ {tag:'td', htmlString:Clipperz.PM.Strings['registrationFormPassphraseLabel']},
+ {tag:'td', children:[
+ {tag:'input', id:this.getId('registration_passphrase'), cls:'loginFormField', type:'password', name:'passphrase'}
+ ]}
+ ]},
+ {tag:'tr', cls:'formFieldTR', children:[
+ {tag:'td', htmlString:Clipperz.PM.Strings['registrationFormRetypePassphraseLabel']},
+ {tag:'td', children:[
+ {tag:'input', id:this.getId('registration_repassphrase'), cls:'loginFormField', type:'password', name:'repeat-passphrase'}
+ ]}
+ ]},
+ {tag:'tr', cls:'formFieldTR', children:[
+ {tag:'td', align:'right', valign:'top', children:[
+ {tag:'input', id:this.getId('registration_check'), type:'checkbox', name:'safetyCheck'}
+ ]},
+ {tag:'td', children:[
+ {tag:'span', htmlString:Clipperz.PM.Strings['registrationFormSafetyCheckLabel']}
+ ]}
+ ]},
+ {tag:'tr', cls:'formFieldTR', children:[
+ {tag:'td', align:'right', valign:'top', children:[
+ {tag:'input', id:this.getId('registration_termsOfServiceCheck'), type:'checkbox', name:'termsOfServiceCheck'}
+ ]},
+ {tag:'td', children:[
+ {tag:'span', htmlString:Clipperz.PM.Strings['registrationFormTermsOfServiceCheckLabel']}
+ ]}
+ ]},
+// {tag:'tr', cls:'formFieldTR', children:[
+// {tag:'td', htmlString:Clipperz.PM.Strings['registrationFormInvitationCodeLabel']},
+// {tag:'td', children:[
+// {tag:'input', id:this.getId('registration_invitationCode'), type:'text', size:'30', name:'invitationCode'}
+// ]}
+// ]},
+ {tag:'tr', children:[
+ {tag:'td'},
+ {tag:'td', children:[
+ {tag:'div', id:this.getId('registration_submit')}
+ ]}
+ ]}
+ ]},
+ {tag:'tfoot'}
+ ]}
+ ]},
+ {tag:'div', cls:'loginFormFooterBox', children:[
+ {tag:'ul', children:[
+ {tag:'li', children:[
+ {tag:'span', htmlString:Clipperz.PM.Strings['registrationFormDoYouAlreadyHaveAnAccountLabel']},
+ {tag:'a', href:'.', id:this.getId('showLogin'), cls:'clipperzActionLink', htmlString:Clipperz.PM.Strings['registrationFormSimplyLoginLabel']}
+ ]}
+ ]}
+ ]}
+ ]}
+]},
+ {tag:'div', cls:'loginPanelSwitchLanguageBox', children:[
+ {tag:'div', cls:'loginPanelSwitchLanguageDescription', htmlString:Clipperz.PM.Strings['loginPanelSwithLanguageDescription']},
+ {tag:'div', cls:'loginPanelSwitchLanguageSelect', children:[
+ {tag:'select', id:this.getId('languageSelector'), children:Clipperz.PM.Strings['loginPanelSwitchLanguageSelectOptions']}
+ ]}
+ ]},
+ {tag:'div', cls:'browserCompatibilityBox', htmlString:Clipperz.PM.Strings['browserCompatibilityDescription']}
+ ]}
+ ]}
+ ]}
+ ]}
+ ]});
+
+ MochiKit.Signal.connect(this.getId('loginForm_form'), 'onsubmit', function(e){e.stop();});
+ MochiKit.Signal.connect(this.getId('registrationForm_form'), 'onsubmit', function(e){e.stop();});
+
+ MochiKit.Signal.connect(this.getId('showRegistration'), 'onclick', this, 'showRegistrationFormEventHandler');
+ MochiKit.Signal.connect(this.getId('showLogin'), 'onclick', this, 'showLoginFormEventHandler');
+
+ new YAHOO.ext.Button(this.getId('login_submit'), {text:Clipperz.PM.Strings['loginFormButtonLabel'], handler:this.doLogin, scope:this, minWidth:0});
+ registerButton = new YAHOO.ext.Button(this.getId('registration_submit'), {text:Clipperz.PM.Strings['registrationFormButtonLabel'], handler:this.doRegister, scope:this, minWidth:0})
+
+ if (Clipperz.PM.Proxy.defaultProxy.isReadOnly()) {
+// this.getElement('showRegistrationLI').setVisibilityMode(YAHOO.ext.Element.DISPLAY).hide();
+ this.getElement('registrationForm_form').addClass('read-only');
+ registerButton.disable();
+ this.getElement('passwordTypeChooserTR').addClass('read-only');
+ this.getDom('useOneTimePasswordCheckbox').disabled = true;
+ }
+
+ MochiKit.Signal.connect(this.getId('loginForm'), 'onkeydown', this, 'onkeydown');
+ MochiKit.Signal.connect(this.getId('registrationForm'), 'onkeydown', this, 'onkeydown');
+// MochiKit.Signal.connect(this.getId('useOneTimePasswordCheckbox'), 'onchange', this, 'renderPasswordField');
+ MochiKit.Signal.connect(this.getId('useOneTimePasswordCheckbox'), 'onclick', this, 'renderPasswordField');
+ this.renderPasswordField();
+
+ this.selectSelectedLanguageOption();
+ MochiKit.Signal.connect(this.getId('languageSelector'), 'onchange', this, 'switchLanguage');
+
+ MochiKit.Signal.connect(this.getId('oneTimePassword_1'), 'onkeypress', this, 'handleOneTimePasswordFieldKeyPress');
+ MochiKit.Signal.connect(this.getId('oneTimePassword_2'), 'onkeypress', this, 'handleOneTimePasswordFieldKeyPress');
+ MochiKit.Signal.connect(this.getId('oneTimePassword_3'), 'onkeypress', this, 'handleOneTimePasswordFieldKeyPress');
+ MochiKit.Signal.connect(this.getId('oneTimePassword_4'), 'onkeypress', this, 'handleOneTimePasswordFieldKeyPress');
+
+ MochiKit.Signal.connect(this.getId('oneTimePassword_1'), 'onkeyup', this, 'handleOneTimePasswordFieldKeyUp');
+ MochiKit.Signal.connect(this.getId('oneTimePassword_2'), 'onkeyup', this, 'handleOneTimePasswordFieldKeyUp');
+ MochiKit.Signal.connect(this.getId('oneTimePassword_3'), 'onkeyup', this, 'handleOneTimePasswordFieldKeyUp');
+ MochiKit.Signal.connect(this.getId('oneTimePassword_4'), 'onkeyup', this, 'handleOneTimePasswordFieldKeyUp');
+
+ new Clipperz.PM.Components.PasswordEntropyDisplay(this.getElement('login_passphrase'));
+ new Clipperz.PM.Components.PasswordEntropyDisplay(this.getElement('registration_passphrase'));
+//MochiKit.Logging.logDebug("<<< LoginPanel.initPanel");
+
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'renderPasswordField': function() {
+ if (this.getDom('useOneTimePasswordCheckbox').checked == false) {
+ this.getElement('oneTimePasswordDIV').setVisibilityMode(YAHOO.ext.Element.DISPLAY).hide(false);
+ this.getElement('passphraseDIV').setVisibilityMode(YAHOO.ext.Element.DISPLAY).show(false);
+ this.getElement('login_passphrase').focus();
+ } else {
+ this.getElement('passphraseDIV').setVisibilityMode(YAHOO.ext.Element.DISPLAY).hide();
+ this.getElement('oneTimePasswordDIV').setVisibilityMode(YAHOO.ext.Element.DISPLAY).show();
+ this.getElement('oneTimePassword_1').focus();
+ }
+
+ },
+
+ //.........................................................................
+
+ 'handleOneTimePasswordFieldKeyPress': function(anEvent) {
+ if (anEvent.key().string == '-') {
+ switch (anEvent.src().id) {
+ case this.getId('oneTimePassword_1'):
+ this.getElement('oneTimePassword_2').focus();
+ break;
+ case this.getId('oneTimePassword_2'):
+ this.getElement('oneTimePassword_3').focus();
+ break;
+ case this.getId('oneTimePassword_3'):
+ this.getElement('oneTimePassword_4').focus();
+ break;
+ }
+
+ anEvent.stop();
+ }
+ },
+
+/*
+ var ctrl = document.getElementById("txtTargetText");
+ var saveText = ctrl.value;
+ ctrl.focus();
+
+ var range = document.selection.createRange();
+ var specialchar = String.fromCharCode(1);
+ range.text = specialchar;
+ var pos = ctrl.value.indexOf(specialchar);
+ ctrl.value = saveText;
+ range = ctrl.createTextRange();
+ range.move('character', pos);
+ range.select();
+ range.text =
+ document.getElementById("txtSourceText").value;
+ document.getElementById("txtTargetText").focus();
+ window.event.returnValue = false;
+*/
+
+ 'handleOneTimePasswordFieldKeyUp': function(anEvent) {
+ var field;
+ var fieldValue;
+ var key;
+
+//console.log("keyUp", anEvent);
+ field = anEvent.src();
+ fieldValue = field.value;
+ key = anEvent.key();
+
+// && (key.string != 'KEY_TAB')
+// && (key.string != 'KEY_SHIFT')
+// && (key.string != 'KEY_BACKSPACE')
+// && (key.string != 'KEY_DELETE')
+// && (key.string.indexOf('KEY_ARROW') != 0)
+
+
+ if ((fieldValue.replace(/\s/g, '').length == 8) && (key.string == 'KEY_SPACEBAR')) {
+// field.value = Clipperz.Base.trim(fieldValue).replace(/.{4}/g, '$&' + ' ');
+
+ switch (field.id) {
+ case this.getId('oneTimePassword_1'):
+ this.getElement('oneTimePassword_2').focus();
+ break;
+ case this.getId('oneTimePassword_2'):
+ this.getElement('oneTimePassword_3').focus();
+ break;
+ case this.getId('oneTimePassword_3'):
+ this.getElement('oneTimePassword_4').focus();
+ break;
+ }
+// } else if (fieldValue.replace(/\s/g, '').length > 8) {
+ }
+
+//MochiKit.Logging.logDebug("-- fieldValue: " + fieldValue);
+ },
+
+ //.........................................................................
+
+ 'doLogin': function() {
+//MochiKit.Logging.logDebug(">>> LoginPanel.doLogin");
+ if (this.checkLoginForm()) {
+ if (this.getDom('useOneTimePasswordCheckbox').checked == false) {
+ this.doLoginWithUsernameAndPassphrase(this.getDom('login_username').value, this.getDom('login_passphrase').value);
+ } else {
+ var oneTimePasswordValue;
+
+ oneTimePasswordValue = this.getDom('oneTimePassword_1').value + this.getDom('oneTimePassword_2').value + this.getDom('oneTimePassword_3').value + this.getDom('oneTimePassword_4').value;
+ this.doLoginWithUsernameAndOneTimePassword(this.getDom('login_username').value, oneTimePasswordValue);
+ }
+ }
+//MochiKit.Logging.logDebug("<<< LoginPanel.doLogin");
+ },
+
+ //.........................................................................
+
+ 'doLoginWithUsernameAndPassphrase': function(anUsername, aPassphrase) {
+ var deferredResult;
+ var user;
+ var loginPanel;
+
+//MochiKit.Logging.logDebug(">>> LoginPanel.doLoginWithUsernameAndPassphrase");
+ user = new Clipperz.PM.DataModel.User({username:anUsername, passphrase:aPassphrase});
+ loginPanel = this;
+
+ deferredResult = new MochiKit.Async.Deferred();
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("0 - LoginPanel.doLogin - 0: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(Clipperz.PM.Components.MessageBox(), 'deferredShow'),
+ {
+ title: "",
+ text: "",
+ width:240,
+ showProgressBar:true,
+ showCloseButton:false,
+ fn:MochiKit.Base.method(deferredResult, 'cancel'),
+ scope:this
+ },
+ this.getDom('login_submit')
+ );
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("1 - LoginPanel.doLogin - 1: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+ deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', 'login_start');
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("2 - LoginPanel.doLogin - 2: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(user, 'connect'));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("3 - LoginPanel.doLogin - 3: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+ deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', 'connection_done');
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("4 - LoginPanel.doLogin - 4: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+ deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', 'connection_loadingUserData');
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("5 - LoginPanel.doLogin - 5: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(user, 'loadPreferences'));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("6 - LoginPanel.doLogin - 6: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(user, 'loadRecords'));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("7 - LoginPanel.doLogin - 7: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(user, 'loadDirectLogins'));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("8 - LoginPanel.doLogin - 8: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+ deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', 'login_connected');
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("9 - LoginPanel.doLogin - 9: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+ deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, user, 'setupDone', null);
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("10 - LoginPanel.doLogin - 10: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+
+ deferredResult.addCallback(MochiKit.Async.wait, 0.5);
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("11 - LoginPanel.doLogin - 11: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+
+ deferredResult.addCallback(function(res) {
+ Clipperz.PM.Components.MessageBox().hide(YAHOO.ext.Element.get('main'));
+ return res;
+ });
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("12 - LoginPanel.doLogin - 12: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+
+ deferredResult.addErrback(MochiKit.Base.bind(function() {
+ Clipperz.PM.Components.MessageBox().update({
+ title:Clipperz.PM.Strings['loginMessagePanelFailureTitle'],
+ text:Clipperz.PM.Strings['loginMessagePanelFailureText'],
+ showProgressBar:false,
+ buttons:{'ok':Clipperz.PM.Strings['loginMessagePanelFailureButtonLabel']},
+ fn:MochiKit.Base.bind(function() {
+ this.getElement('login_passphrase').focus();
+ this.getElement('login_passphrase').dom.select();
+ }, this),
+ scope:this
+ });
+ }, this));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("13 - LoginPanel.doLogin - 13: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+
+ deferredResult.callback("token");
+//MochiKit.Logging.logDebug("<<< LoginPanel.doLoginWithUsernameAndPassphrase");
+
+ return deferredResult;
+ },
+
+ //.........................................................................
+
+ 'doLoginWithUsernameAndOneTimePassword': function(anUsername, aOneTimePassword) {
+ var deferredResult;
+ var loginPanel;
+ var oneTimePassword;
+
+ oneTimePassword = Clipperz.PM.DataModel.OneTimePassword.normalizedOneTimePassword(aOneTimePassword);
+
+//MochiKit.Logging.logDebug(">>> LoginPanel.doLoginWithUsernameAndPassphrase");
+ deferredResult = new MochiKit.Async.Deferred();
+ deferredResult.addCallback(MochiKit.Base.method(Clipperz.PM.Components.MessageBox(), 'deferredShow'),
+ {
+ title: "",
+ text: "",
+ width:240,
+ showProgressBar:true,
+ showCloseButton:false,
+ fn:MochiKit.Base.method(deferredResult, 'cancel'),
+ scope:this,
+ steps:7,
+ buttons:{
+ // 'ok':Clipperz.PM.Strings['loginMessagePanelInitialButtonLabel']
+ }
+ },
+ this.getDom('login_submit')
+ );
+ deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', 'OTP_login_start');
+ 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.addBoth(function(res) {MochiKit.Logging.logDebug("LoginPanel.otpLogin - 4: " + res); return res;});
+ deferredResult.addCallback(function(aResult) {
+//MochiKit.Logging.logDebug("aResult")
+ return (new Clipperz.ByteArray().appendBase64String(aResult['passphrase'])).asString();
+ });
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("LoginPanel.otpLogin - 5: " + res); return res;});
+ deferredResult.addCallbacks(
+ MochiKit.Base.method(this, 'doLoginWithUsernameAndPassphrase', anUsername),
+ MochiKit.Base.bind(function(aLoginPanel) {
+ Clipperz.PM.Components.MessageBox().update({
+ title:Clipperz.PM.Strings['loginMessagePanelFailureTitle'],
+ text:Clipperz.PM.Strings['loginMessagePanelFailureText'],
+ showProgressBar:false,
+ buttons:{'ok':Clipperz.PM.Strings['loginMessagePanelFailureButtonLabel']},
+ fn:MochiKit.Base.bind(function() {
+ this.getElement('oneTimePassword_1').focus();
+ }, this),
+ scope:aLoginPanel
+ });
+ }, this)
+ );
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("LoginPanel.otpLogin - 6: " + res); return res;});
+ deferredResult.callback("token");
+//MochiKit.Logging.logDebug("<<< LoginPanel.doLoginWithUsernameAndPassphrase");
+
+ return deferredResult;
+ },
+
+ //.........................................................................
+
+ 'checkLoginForm': function() {
+ var result;
+ var username
+
+ result = true;
+
+//MochiKit.Logging.logDebug(">>> checkLoginForm");
+ username = Clipperz.Base.trim(this.getDom('login_username').value);
+ if (username == "") {
+ this.getElement('login_username').focus();
+ result = false;
+ } else {
+ if (this.getDom('useOneTimePasswordCheckbox').checked == false) {
+ var passphrase;
+
+ passphrase = Clipperz.Base.trim(this.getDom('login_passphrase').value);
+
+ if (passphrase == "") {
+ this.getElement('login_passphrase').focus();
+ result = false;
+ }
+ } else {
+ if (Clipperz.Base.trim(this.getDom('oneTimePassword_1').value) == "") {
+ this.getElement('oneTimePassword_1').focus();
+ result = false;
+ } else if (Clipperz.Base.trim(this.getDom('oneTimePassword_2').value) == "") {
+ this.getElement('oneTimePassword_2').focus();
+ result = false;
+ } else if (Clipperz.Base.trim(this.getDom('oneTimePassword_3').value) == "") {
+ this.getElement('oneTimePassword_3').focus();
+ result = false;
+ } else if (Clipperz.Base.trim(this.getDom('oneTimePassword_4').value) == "") {
+ this.getElement('oneTimePassword_4').focus();
+ result = false;
+ }
+ }
+ }
+//MochiKit.Logging.logDebug("<<< checkLoginForm - " + result);
+
+ return result;
+ },
+
+ //.........................................................................
+
+ 'doRegister': function(anEvent) {
+ if ((Clipperz.PM.Proxy.defaultProxy.isReadOnly() == false) && (this.checkRegistrationForm())) {
+ this.doRegistrationWithUsernameAndPassphrase(this.getDom('registration_username').value, this.getDom('registration_passphrase').value /*, this.getDom('registration_invitationCode').value*/);
+ }
+ },
+
+ //.........................................................................
+
+ 'checkRegistrationForm': function() {
+ var result;
+ var username
+ var passphrase;
+ var rePassphrase;
+ var safetyCheck;
+ var termsOfServiceCheck;
+// var invitationCode;
+
+ username = this.getDom('registration_username').value;
+ passphrase = this.getDom('registration_passphrase').value;
+ rePassphrase = this.getDom('registration_repassphrase').value;
+ safetyCheck = this.getDom('registration_check').checked;
+ termsOfServiceCheck = this.getDom('registration_termsOfServiceCheck').checked;
+// invitationCode = this.getDom('registration_invitationCode').value;
+
+ if ((username != "") && (passphrase != "") && (rePassphrase != "") /*&& (invitationCode != "")*/) {
+ if (passphrase != rePassphrase) {
+ // show alert that the passphrase and rePassphrase should be equal
+//MochiKit.Logging.logDebug("WARNING: passphrase != rePassphrase");
+ this.showRegistrationFormErrorMessageAnimation(Clipperz.PM.Strings['registrationFormWarningMessageNotMatchingPassphrases']);
+ this.getElement('registration_repassphrase').focus().dom.select();
+// this.getElement('registration_repassphrase').select();
+ result = false;
+ } else if (safetyCheck != true) {
+ // show alert that the safetyCheck should be checed
+//MochiKit.Logging.logDebug("WARNING: safetyCheck not checked");
+ this.showRegistrationFormErrorMessageAnimation(Clipperz.PM.Strings['registrationFormWarningMessageSafetyCheckNotSelected']);
+ this.getElement('registration_check').focus();
+ result = false;
+ } else if (termsOfServiceCheck != true) {
+ this.showRegistrationFormErrorMessageAnimation(Clipperz.PM.Strings['registrationFormWarningMessageTermsOfServiceCheckNotSelected']);
+ this.getElement('registration_termsOfServiceCheck').focus();
+ } else {
+ result = true;
+ }
+ } else {
+ if (username == "") {
+ this.getElement('registration_username').focus();
+ } else if (passphrase == "") {
+ this.getElement('registration_passphrase').focus();
+ } else if (rePassphrase == "") {
+ this.getElement('registration_repassphrase').focus();
+// } else if (invitationCode == "") {
+// this.showRegistrationFormErrorMessageAnimation(Clipperz.PM.Strings['registrationFormWarningMessageInvitationCodeMissing']);
+// this.getElement('registration_invitationCode').focus();
+ }
+
+ result = false;
+ }
+
+ if (result === true) {
+ this.getActor('registration_errorMessage').hide();
+ }
+
+ return result;
+ },
+
+ //.........................................................................
+
+ 'showRegistrationFormErrorMessageAnimation': function(anErrorMessage, aCallback) {
+ var errorMessageActor;
+
+ errorMessageActor = this.getActor('registration_errorMessage');
+ errorMessageActor.update(anErrorMessage);
+ errorMessageActor.show(true);
+ errorMessageActor.play(aCallback);
+ },
+
+ //.........................................................................
+
+ 'doRegistrationWithUsernameAndPassphrase': function(anUsername, aPassphrase /*, anInvitationCode */) {
+ var deferredResult;
+ var user;
+ var loginPanel;
+
+//MochiKit.Logging.logDebug(">>> LoginPanel.doRegistrationWithUsernameAndPassphrase");
+ user = new Clipperz.PM.DataModel.User({username:anUsername, passphrase:aPassphrase});
+//MochiKit.Logging.logDebug("--- LoginPanel.doRegistrationWithUsernameAndPassphrase - 1");
+ loginPanel = this;
+//MochiKit.Logging.logDebug("--- LoginPanel.doRegistrationWithUsernameAndPassphrase - 2");
+
+ deferredResult = new MochiKit.Async.Deferred();
+//MochiKit.Logging.logDebug("--- LoginPanel.doRegistrationWithUsernameAndPassphrase - 3");
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("LoginPanel.doRegistrationWithUsernameAndPassphrase - 1: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(Clipperz.PM.Components.MessageBox(), 'deferredShow'),
+ {
+ title:Clipperz.PM.Strings['registrationMessagePanelInitialTitle'],
+ text: Clipperz.PM.Strings['registrationMessagePanelInitialText'],
+ width:240,
+ showProgressBar:true,
+ showCloseButton:false,
+ fn:MochiKit.Base.method(deferredResult, 'cancel'),
+ scope:this,
+ steps:9,
+ buttons:{
+ 'ok':Clipperz.PM.Strings['registrationMessagePanelInitialButtonLabel']
+ }
+ },
+ this.getDom('registration_submit')
+ );
+//MochiKit.Logging.logDebug("--- LoginPanel.doRegistrationWithUsernameAndPassphrase - 4");
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("LoginPanel.doRegistrationWithUsernameAndPassphrase - 2: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(user, 'register'), /*anInvitationCode*/ "VeryBraveBetaTester");
+//MochiKit.Logging.logDebug("--- LoginPanel.doRegistrationWithUsernameAndPassphrase - 5");
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("LoginPanel.doRegistrationWithUsernameAndPassphrase - 3: " + res); return res;});
+ deferredResult.addCallback(function(res) {
+ Clipperz.PM.Components.MessageBox().update({
+ title:Clipperz.PM.Strings['registrationMessagePanelRegistrationDoneTitle'],
+ text:Clipperz.PM.Strings['registrationMessagePanelRegistrationDoneText'],
+ step:'next'
+ });
+ return res;
+ });
+//MochiKit.Logging.logDebug("--- LoginPanel.doRegistrationWithUsernameAndPassphrase - 6");
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("LoginPanel.doRegistrationWithUsernameAndPassphrase - 5: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Async.wait, 1);
+//MochiKit.Logging.logDebug("--- LoginPanel.doRegistrationWithUsernameAndPassphrase - 7");
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("LoginPanel.doRegistrationWithUsernameAndPassphrase - 6: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(user, 'connect'));
+//MochiKit.Logging.logDebug("--- LoginPanel.doRegistrationWithUsernameAndPassphrase - 8");
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("LoginPanel.doRegistrationWithUsernameAndPassphrase - 7: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Async.wait, 1);
+//MochiKit.Logging.logDebug("--- LoginPanel.doRegistrationWithUsernameAndPassphrase - 9");
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("LoginPanel.doRegistrationWithUsernameAndPassphrase - 8: " + res); return res;});
+ deferredResult.addCallback(function(res) {
+ Clipperz.PM.Components.MessageBox().hide(YAHOO.ext.Element.get('main'));
+ return res;
+ });
+ deferredResult.addCallback(MochiKit.Base.method(this, 'showRegistrationSplashScreen'), user);
+//MochiKit.Logging.logDebug("--- LoginPanel.doRegistrationWithUsernameAndPassphrase - 10");
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("LoginPanel.doRegistrationWithUsernameAndPassphrase - 9: " + res); return res;});
+ deferredResult.addErrback(function(anError) {
+ Clipperz.PM.Components.MessageBox().update({
+ title:Clipperz.PM.Strings['registrationMessagePanelFailureTitle'],
+ text:anError.message,
+ showProgressBar:false,
+ buttons:{'ok':Clipperz.PM.Strings['registrationMessagePanelFailureButtonLabel']}});
+ return anError;
+ });
+//MochiKit.Logging.logDebug("--- LoginPanel.doRegistrationWithUsernameAndPassphrase - 11");
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("LoginPanel.doRegistrationWithUsernameAndPassphrase - 10: " + res); return res;});
+ deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, user, 'setupDone', null);
+ deferredResult.callback("token");
+//MochiKit.Logging.logDebug("--- LoginPanel.doRegistrationWithUsernameAndPassphrase - 12");
+
+ return deferredResult;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'showRegistrationSplashScreen': function(anUser) {
+ var deferredResult;
+ var alertElement;
+ var alertDialog;
+ var closeButton;
+ var closeFunction;
+
+ deferredResult = new MochiKit.Async.Deferred();
+
+//MochiKit.Logging.logDebug(">>> Main.showRegistrationSplashScreen");
+ alertElement = Clipperz.YUI.DomHelper.append(document.body, {tag:'div', id:'registrationSplash', children:[
+ {tag:'div', cls:'ydlg-hd', htmlString:Clipperz.PM.Strings['registrationSplashPanelTitle']},
+ {tag:'div', cls:'ydlg-bd', children:[
+ {tag:'div', cls:'alert-message', id:'splashMessage', children:[
+ {tag:'div', htmlString:Clipperz.PM.Strings['registrationSplashPanelDescription']},
+ {tag:'table', border:'0', cellpadding:'5', children:[
+ {tag:'tbody', children:[
+ {tag:'tr', children:[
+ {tag:'td', valign:'top', children:[
+ {tag:'span', cls:'label', htmlString:Clipperz.PM.Strings['registrationSplashPanelUsernameLabel']}
+ ]},
+ {tag:'td', valign:'top', children:[
+ {tag:'span', cls:'value', html:Clipperz.Base.escapeHTML(anUser.username())}
+ ]}
+ ]},
+ {tag:'tr', children:[
+ {tag:'td', valign:'top', children:[
+ {tag:'span', cls:'label', htmlString:Clipperz.PM.Strings['registrationSplashPanelPassphraseLabel']}
+ ]},
+ {tag:'td', valign:'top', children:[
+ {tag:'div', id:this.getId('showPassphraseDiv'), children:[
+ {tag:'span', cls:'value', html:Clipperz.Base.escapeHTML(anUser.passphrase())}
+ ]},
+ {tag:'div', id:this.getId('hidePassphraseDiv'), cls:'Clipperz_recordFieldData', children:[
+ {tag:'input', id:this.getId('passwordField'), type:'text', cls:'scrambledField', title:Clipperz.PM.Strings['recordDetailPasswordFieldTooltipLabel'], value:"anUser.passphrase()"}
+ ]}
+ ]}
+ ]},
+ {tag:'tr', children:[
+ {tag:'td'},
+ {tag:'td', valign:'top', children:[
+// {tag:'a', href:"#", id:this.getId('togglePassphraseVisibility'), htmlString:Clipperz.PM.Strings['registrationSplashPanelShowPassphraseButtonLabel']}
+ {tag:'input', type:'checkbox', id:this.getId('showPassphraseCheckbox')},
+ {tag:'span', cls:'activeText', id:this.getId('showPassphraseText'), htmlString:Clipperz.PM.Strings['registrationSplashPanelShowPassphraseButtonLabel']}
+ ]}
+ ]}
+ ]}
+ ]}
+ ]}
+ ]},
+ {tag:'div', cls:'ydlg-ft'}
+ ]}, true);
+//MochiKit.Logging.logDebug("--- Main.showRegistrationSplashScreen - 1");
+
+ this.getElement('passwordField').dom.value = anUser.passphrase();
+ this.getElement('passwordField').wrap({tag:'div', cls:'passwordBackground'}).setStyle('background-position', "0px -" + Math.min(128, Clipperz.PM.Crypto.passwordEntropy(anUser.passphrase())) + "px").setStyle('width', '71px');
+ MochiKit.Signal.connect(this.getId('showPassphraseCheckbox'), 'onclick', this, 'togglePassphraseVisibility');
+ MochiKit.Signal.connect(this.getId('showPassphraseText'), 'onclick', this, 'togglePassphraseCheckbox');
+//MochiKit.Logging.logDebug("--- Main.showRegistrationSplashScreen - 1.1");
+
+ this.getElement('showPassphraseDiv').setVisibilityMode(YAHOO.ext.Element.DISPLAY);
+ this.getElement('hidePassphraseDiv').setVisibilityMode(YAHOO.ext.Element.DISPLAY);
+//MochiKit.Logging.logDebug("--- Main.showRegistrationSplashScreen - 1.1.1");
+ this.togglePassphraseVisibility();
+//MochiKit.Logging.logDebug("--- Main.showRegistrationSplashScreen - 1.2");
+
+ alertDialog = new YAHOO.ext.BasicDialog(
+ alertElement, {
+ closable:false,
+ modal:true,
+ autoTabs:false,
+ resizable:false,
+ fixedcenter:true,
+ constraintoviewport:false,
+ width:450,
+ height:220,
+ shadow:true,
+ minWidth:300,
+ minHeight:300
+ }
+ );
+//MochiKit.Logging.logDebug("--- Main.showRegistrationSplashScreen - 2");
+
+ closeFunction = deferredResult.callback;
+//MochiKit.Logging.logDebug("--- Main.showRegistrationSplashScreen - 3");
+ alertDialog.addKeyListener(27, closeFunction);
+//MochiKit.Logging.logDebug("--- Main.showRegistrationSplashScreen - 4");
+ closeButton = alertDialog.addButton(Clipperz.PM.Strings['splashAlertCloseButtonLabel'], closeFunction, deferredResult);
+//MochiKit.Logging.logDebug("--- Main.showRegistrationSplashScreen - 5");
+ alertDialog.setDefaultButton(closeButton);
+//MochiKit.Logging.logDebug("--- Main.showRegistrationSplashScreen - 6");
+ alertDialog.show('main');
+//MochiKit.Logging.logDebug("--- Main.showRegistrationSplashScreen - 7");
+
+ deferredResult.addBoth(MochiKit.Base.method(alertDialog, 'hide'));
+ deferredResult.addCallback(MochiKit.Signal.disconnectAllTo, this)
+//MochiKit.Logging.logDebug("--- Main.showRegistrationSplashScreen - 8");
+ deferredResult.addCallback(MochiKit.Async.succeed);
+//MochiKit.Logging.logDebug("<<< Main.showRegistrationSplashScreen");
+
+ return deferredResult;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'showLoginFormEventHandler': function(anEvent) {
+ anEvent.stop();
+ this.showLoginForm(true);
+ },
+
+ 'showLoginForm': function(shouldAnimate) {
+ if (shouldAnimate) {
+ this.showLoginFormAnimator().play();
+ } else {
+ this.hideRegistrationForm(false);
+ this.getActor('loginForm').show(false);
+ this.getElement('login_username').focus();
+ }
+ this.setVisibleForm('login');
+ },
+
+ 'showLoginFormAnimator': function() {
+ if (this._showLoginFormAnimator == null) {
+ var animator;
+ var loginFormActor;
+ var registrationFormActor;
+ var usernameFieldActor;
+
+ animator = new YAHOO.ext.Animator();
+ loginFormActor = this.getActor('loginForm', animator);
+ loginFormActor.setVisibilityMode(YAHOO.ext.Element.DISPLAY);
+ registrationFormActor = this.getActor('registrationForm', animator);
+ registrationFormActor.setVisibilityMode(YAHOO.ext.Element.DISPLAY);
+ usernameFieldActor = this.getActor('login_username', animator);
+
+ animator.startCapture();
+ registrationFormActor.hide(true);
+ loginFormActor.show(true);
+ usernameFieldActor.focus();
+ animator.stopCapture();
+
+ this._showLoginFormAnimator = animator;
+ }
+
+ return this._showLoginFormAnimator;
+ },
+
+
+ 'hideLoginForm': function(shouldAnimate) {
+ var loginFormActor;
+
+ loginFormActor = this.getActor('loginForm');
+ loginFormActor.setVisibilityMode(YAHOO.ext.Element.DISPLAY);
+ loginFormActor.hide(shouldAnimate);
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'showRegistrationFormEventHandler': function(anEvent) {
+ anEvent.stop();
+ this.showRegistrationForm(true);
+ },
+
+ 'showRegistrationForm': function(shouldAnimate) {
+ if (shouldAnimate) {
+ this.showRegistrationFormAnimator().play(MochiKit.Base.bind(this.showRegistrationAlert, this));
+ } else {
+ var errorMessageActor;
+
+ this.hideLoginForm(shouldAnimate)
+ this.getActor('registrationForm').show(false);
+ this.getElement('registration_username').focus();
+
+ errorMessageActor = this.getActor('registration_errorMessage');
+ errorMessageActor.setVisibilityMode(YAHOO.ext.Element.DISPLAY);
+ errorMessageActor.update("---");
+ errorMessageActor.hide();
+
+ this.showRegistrationAlert();
+ }
+ this.setVisibleForm('registration');
+ },
+
+ 'showRegistrationFormAnimator': function() {
+ if (this._showRegistrationFormAnimator == null) {
+ var animator;
+ var loginFormActor;
+ var registrationFormActor;
+ var usernameFieldActor;
+ var errorMessageActor;
+
+ animator = new YAHOO.ext.Animator();
+ loginFormActor = this.getActor('loginForm', animator);
+ loginFormActor.setVisibilityMode(YAHOO.ext.Element.DISPLAY);
+ registrationFormActor = this.getActor('registrationForm', animator);
+ registrationFormActor.setVisibilityMode(YAHOO.ext.Element.DISPLAY);
+ usernameFieldActor = this.getActor('registration_username', animator);
+ errorMessageActor = this.getActor('registration_errorMessage', animator);
+ errorMessageActor.setVisibilityMode(YAHOO.ext.Element.DISPLAY);
+
+ animator.startCapture();
+ loginFormActor.hide(true);
+ errorMessageActor.update("---");
+ errorMessageActor.hide();
+ registrationFormActor.show(true);
+ usernameFieldActor.focus();
+ animator.stopCapture();
+
+ this._showRegistrationFormAnimator = animator;
+ }
+
+ return this._showRegistrationFormAnimator;
+ },
+
+ 'hideRegistrationForm': function(shouldAnimate) {
+ var registrationFormActor;
+
+ registrationFormActor = this.getActor('registrationForm');
+ registrationFormActor.setVisibilityMode(YAHOO.ext.Element.DISPLAY);
+ registrationFormActor.hide(shouldAnimate);
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'shouldShowRegistrationAlert': function() {
+ return this._shouldShowRegistrationAlert;
+ },
+
+ 'showRegistrationAlert': function() {
+ if ((this.shouldShowRegistrationAlert()) && (Clipperz.PM.Proxy.defaultProxy.isReadOnly() == false)) {
+ var alertElement;
+ var alertDialog;
+ var closeButton;
+ var closeFunction;
+
+ alertElement = Clipperz.YUI.DomHelper.append(document.body, {tag:'div', id:'alert', children:[
+ {tag:'div', cls:'ydlg-hd', htmlString:Clipperz.PM.Strings['splashAlertTitle']},
+ {tag:'div', cls:'ydlg-bd', children:[
+ {tag:'div', cls:'alert-message', id:'splashMessage', htmlString:Clipperz.PM.Strings['splashAlertText']}
+ ]},
+ {tag:'div', cls:'ydlg-ft'}
+ ]}, true);
+
+ alertDialog = new YAHOO.ext.BasicDialog(
+ alertElement, {
+ closable:false,
+ modal:true,
+ autoTabs:false,
+ resizable:false,
+ fixedcenter:true,
+ constraintoviewport:false,
+ width:450,
+ height:320,
+ shadow:true,
+ minWidth:300,
+ minHeight:300
+ }
+ );
+
+ closeFunction = MochiKit.Base.partial(MochiKit.Base.bind(this.closeResigrationAlert, this), alertDialog);
+ alertDialog.addKeyListener(27, closeFunction);
+ closeButton = alertDialog.addButton(Clipperz.PM.Strings['splashAlertCloseButtonLabel'], closeFunction, this);
+ alertDialog.setDefaultButton(closeButton);
+ alertDialog.show('main');
+
+ this._shouldShowRegistrationAlert = false;
+ }
+ },
+
+ 'closeResigrationAlert': function(anAlertDialog) {
+ anAlertDialog.hide(MochiKit.Base.bind(function() {anAlertDialog.destroy(true); this.focusOnVisibleForm();}, this));
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'onkeydown': function(anEvent) {
+//MochiKit.Logging.logDebug(">>> onkeydown - " + anEvent.src().id);
+ if (anEvent.key().code == 13) {
+ if (anEvent.src() == this.getDom('loginForm')) {
+ this.doLogin();
+ } else if (anEvent.src() == this.getDom('registrationForm')) {
+ this.doRegister();
+ } else {
+ }
+
+ anEvent.stop();
+ }
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'visibleForm': function() {
+ return this._visibleForm;
+ },
+
+ 'setVisibleForm': function(aValue) {
+ this._visibleForm = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'focusOnVisibleForm': function() {
+ if (this.visibleForm() == 'registration') {
+ this.getElement('registration_username').focus();
+ } else {
+ this.getElement('login_username').focus();
+ }
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'show': function() {
+ if (this.visibleForm() == 'registration') {
+ this.showRegistrationForm(false);
+ } else {
+ this.showLoginForm(false);
+ }
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'switchLanguage': function(anEvent) {
+ Clipperz.PM.Strings.Languages.setSelectedLanguage(anEvent.src().value);
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'selectSelectedLanguageOption': function() {
+ Clipperz.DOM.selectOptionMatchingValue(this.getDom('languageSelector'), Clipperz.PM.Strings.selectedLanguage, true);
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'switchLanguageHandler': function() {
+ this.render();
+ this.show();
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'togglePassphraseCheckbox': function(anEvent) {
+ this.getDom('showPassphraseCheckbox').click();
+ },
+
+ 'togglePassphraseVisibility': function(anEvent) {
+ if (this.getDom('showPassphraseCheckbox').checked == true) {
+ this.getElement('showPassphraseDiv').show();
+ this.getElement('hidePassphraseDiv').hide();
+ } else {
+ this.getElement('showPassphraseDiv').hide();
+ this.getElement('hidePassphraseDiv').show();
+ }
+ },
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+
+});
diff --git a/frontend/beta/js/Clipperz/PM/Components/Panels/LogoutPanel.js b/frontend/beta/js/Clipperz/PM/Components/Panels/LogoutPanel.js
new file mode 100644
index 0000000..d7abfd6
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Components/Panels/LogoutPanel.js
@@ -0,0 +1,73 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
+if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
+if (typeof(Clipperz.PM.Components) == 'undefined') { Clipperz.PM.Components = {}; }
+if (typeof(Clipperz.PM.Components.Panels) == 'undefined') { Clipperz.PM.Components.Panels = {}; }
+
+//#############################################################################
+
+Clipperz.PM.Components.Panels.LogoutPanel = function(args) {
+ args = args || {};
+
+ Clipperz.PM.Components.Panels.LogoutPanel.superclass.constructor.call(this, args);
+
+ return this;
+}
+
+//=============================================================================
+
+YAHOO.extendX(Clipperz.PM.Components.Panels.LogoutPanel, Clipperz.PM.Components.Panels.BasePanel, {
+
+ 'toString': function() {
+ return "Clipperz.PM.Components.LogoutPanel component";
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'initPanel': function() {
+ var result;
+ var layout;
+
+ result = new YAHOO.ext.ContentPanel(this.getId('panel'), {title:'logout', closable:false, autoCreate:true});
+
+ Clipperz.YUI.DomHelper.append(result.getEl().dom,
+ {tag:'div', children:[
+ {tag:'h2', html:'Logout panel'}
+ ]}
+ );
+
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+
+});
+
diff --git a/frontend/beta/js/Clipperz/PM/Components/Panels/MainPanel.js b/frontend/beta/js/Clipperz/PM/Components/Panels/MainPanel.js
new file mode 100644
index 0000000..e2036d0
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Components/Panels/MainPanel.js
@@ -0,0 +1,906 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
+if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
+if (typeof(Clipperz.PM.Components) == 'undefined') { Clipperz.PM.Components = {}; }
+if (typeof(Clipperz.PM.Components.Panels) == 'undefined') { Clipperz.PM.Components.Panels = {}; }
+
+//#############################################################################
+
+Clipperz.PM.Components.Panels.MainPanel = function(anElement, args) {
+ args = args || {};
+
+ Clipperz.PM.Components.Panels.MainPanel.superclass.constructor.call(this, anElement, args);
+
+ this._recordListDataModel = null;
+ this._selectedRecord = null;
+ this._recordDetailComponent = null;
+ this._recordListGrid = null;
+
+ this._directLinkItemTemplate = null;
+ this._recordItemTemplate = null;
+
+ this._addNewRecordButton = null;
+ this._deleteRecordButton = null;
+
+ this._creationWizard = null;
+
+ Clipperz.NotificationCenter.register(null, 'selectAndEnterEditMode', this, 'selectRecordAndEnterEditModeHandler');
+
+ Clipperz.NotificationCenter.register(null, 'recordAdded', this, 'recordAddedHandler');
+ Clipperz.NotificationCenter.register(null, 'recordUpdated', this, 'recordUpdatedHandler');
+ Clipperz.NotificationCenter.register(null, 'recordRemoved', this, 'recordRemovedHandler');
+
+ Clipperz.NotificationCenter.register(null, 'directLoginAdded', this, 'directLoginAddedHandler');
+ Clipperz.NotificationCenter.register(null, 'directLoginUpdated', this, 'directLoginUpdatedHandler');
+ Clipperz.NotificationCenter.register(null, 'directLoginRemoved', this, 'directLoginRemovedHandler');
+
+ Clipperz.NotificationCenter.register(null, 'accountLocked', this, 'accountLockedHandler');
+
+ MochiKit.Signal.connect(MochiKit.DOM.currentWindow(), 'onresize', this, 'resizeModalMask');
+ this.render();
+
+ return this;
+}
+
+//=============================================================================
+
+YAHOO.extendX(Clipperz.PM.Components.Panels.MainPanel, Clipperz.PM.Components.Panels.BasePanel, {
+
+ 'toString': function() {
+ return "Clipperz.PM.Components.Panels.MainPanel component";
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'render': function() {
+ this.element().update("");
+ Clipperz.YUI.DomHelper.append(this.element().dom, {tag:'table', id:'mainPanelTABLE', border:'0', cellspacing:'0', cellpadding:'0', children:[
+ {tag:'tbody', children:[
+ {tag:'tr', children:[
+ {tag:'td', width:'15', children:[
+ {tag:'div', cls:'mainPanelMinHeightDiv'}
+ ]},
+ {tag:'td', valign:'top', id:'directLoginsTD', width:'200', children:[
+ {tag:'div', id:'directLoginsBlock', children:[
+ {tag:'div', cls:'directLoginsBlockHeaderBox', children:[{tag:'h3', id:'directLoginTitle', htmlString:Clipperz.PM.Strings['mainPanelDirectLoginBlockLabel']}]},
+ {tag:'div', id:'directLoginsDescription', htmlString:Clipperz.PM.Strings['mainPanelDirectLoginBlockDescription']},
+ {tag:'ul', id:'directLogins'}
+ ]}
+ ]},
+ {tag:'td', width:'15', children:[
+ {tag:'div', cls:'mainPanelMinHeightDiv'}
+ ]},
+ {tag:'td', valign:'top', children:[
+ {tag:'div', id:'mainContent', children:[
+ {tag:'div', id:'recordListBlockHeader'},
+ {tag:'div', id:'recordListAndDetailBlock', children:[
+ {tag:'table', id:'recordListAndDetailBlockTABLE', border:'0', cellspacing:'0', cellpadding:'0', children:[
+ {tag:'tbody', children:[
+ {tag:'tr', children:[
+ {tag:'td', valign:'top', width:'250', children:[
+ {tag:'div', id:'recordListBlock', children:[
+ {tag:'div', id:'recordListFilterHeader'},
+ {tag:'ul', id:'records'}
+ ]}
+ ]},
+ {tag:'td', id:'recordDetailSeparatorTD', rowspan:'2', valign:'top', bgcolor:'#ddddff', html:'&nbsp;'},
+ {tag:'td', valign:'top', children:[
+ {tag:'div', id:'recordDetailMainBlock', children:[
+ {tag:'div', id:'recordTitleTopBlock'},
+ {tag:'div', id:'recordDetailBlock', children:[
+ {tag:'div', id:'recordDetail'}
+ ]}
+ ]},
+ {tag:'div', id:'recordCreationWizardMainBlock', children:[
+ {tag:'div', id:'recordCreationWizard', html:"WIZARD"}
+ ]}
+ ]}
+ ]},
+ {tag:'tr', children:[
+ {tag:'td', id:'cardBoxLowerLeftTD', html:'&nbsp;'},
+ {tag:'td', id:'cardBoxLowerRightTD', html:'&nbsp;'}
+ ]}
+ ]}
+ ]}
+ ]}
+ ]}
+ ]},
+ {tag:'td', width:'15', html:"&nbsp;"}
+ ]}
+ ]}
+ ]});
+
+ this.renderRecordListBlockHeader();
+// this.renderRecordListFilterHeader();
+
+ YAHOO.ext.Element.get('directLogins').setVisibilityMode(YAHOO.ext.Element.DISPLAY).hide();
+
+ this.recordDetailComponent();
+
+ YAHOO.ext.Element.get('recordDetailMainBlock').setVisibilityMode(YAHOO.ext.Element.DISPLAY).show();
+ YAHOO.ext.Element.get('recordCreationWizardMainBlock').setVisibilityMode(YAHOO.ext.Element.DISPLAY).hide();
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'addNewRecordButton': function() {
+ return this._addNewRecordButton;
+ },
+
+ 'setAddNewRecordButton': function(aValue) {
+ this._addNewRecordButton = aValue;
+ },
+
+ 'deleteRecordButton': function() {
+ return this._deleteRecordButton;
+ },
+
+ 'setDeleteRecordButton': function(aValue) {
+ this._deleteRecordButton = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'addNewRecord': function(anEvent) {
+ var deferredResult;
+// var currentNumberOfRecords;
+
+ deferredResult = new MochiKit.Async.Deferred();
+
+// currentNumberOfRecords = MochiKit.Base.keys(this.user().records()).length;
+/*
+// if ((this.user().preferences().shouldShowDonationPanel()) && (currentNumberOfRecords > 0) && ((currentNumberOfRecords%10) == 0)) {
+// if (true) {
+ if ((this.user().preferences().shouldShowDonationPanel()) && (currentNumberOfRecords >= 5)) {
+ deferredResult.addCallback(Clipperz.PM.showDonationSplashScreen, this.user(), 'recordListAddRecordButton');
+ }
+*/
+ deferredResult.addCallback(MochiKit.Base.bind(function() {
+ var currentlySelectedRecord;
+
+ currentlySelecedRecord = this.selectedRecord();
+ this.setSelectedRecord(null);
+
+ YAHOO.ext.Element.get('recordDetailMainBlock').hide();
+ YAHOO.ext.Element.get('recordCreationWizardMainBlock').show();
+ this.setCreationWizard(new Clipperz.PM.Components.RecordDetail.CreationWizard(YAHOO.ext.Element.get('recordCreationWizardMainBlock'), {previouslySelectedRecord:currentlySelecedRecord, mainComponent:this}));
+
+ this.enterModalView();
+ }, this));
+
+ deferredResult.callback();
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'creationWizard': function() {
+ return this._creationWizard;
+ },
+
+ 'setCreationWizard': function(aValue) {
+ this._creationWizard = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'exitWizard': function(aSelectedRecord, shouldEnterEditMode) {
+//MochiKit.Logging.logDebug(">>> MainPanel.exitWizard - " + aSelectedRecord)
+ YAHOO.ext.Element.get('recordCreationWizardMainBlock').hide();
+ YAHOO.ext.Element.get('recordDetailMainBlock').show();
+
+ if (shouldEnterEditMode == true) {
+ this.selectRecordAndEnterEditMode(aSelectedRecord);
+ } else {
+ this.setSelectedRecord(aSelectedRecord);
+ this.exitModalView();
+ }
+
+ this.creationWizard().remove();
+ this.setCreationWizard(null);
+//MochiKit.Logging.logDebug("<<< MainPanel.exitWizard");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'selectRecordAndEnterEditMode': function(aRecord) {
+ this.setSelectedRecord(aRecord);
+ this.recordDetailComponent().setEditMode('EDIT');
+ },
+
+ 'selectRecordAndEnterEditModeHandler': function(anEvent) {
+ this.selectRecordAndEnterEditMode(anEvent.source());
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'resizeModalMask': function() {
+//MochiKit.Logging.logDebug(">>> MainPanel.resizeModalMask");
+ MochiKit.Style.setElementDimensions('recordDetailEditModeHeaderMask', {w:MochiKit.Style.getElementDimensions('mainDiv').w, h:119});
+
+ MochiKit.Style.setElementDimensions('recordDetailEditModeVerticalMask', {w:511, h:MochiKit.Style.getElementDimensions('mainDiv').h - 119});
+//MochiKit.Logging.logDebug("<<< MainPanel.resizeModalMask");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'enterModalView': function() {
+ if (this.user().preferences().useSafeEditMode()) {
+ var headerMaskElement;
+ var verticalMaskElement;
+
+ this.resizeModalMask();
+
+ headerMaskElement = YAHOO.ext.Element.get('recordDetailEditModeHeaderMask');
+ headerMaskElement.show();
+ headerMaskElement.mask();
+
+ verticalMaskElement = YAHOO.ext.Element.get('recordDetailEditModeVerticalMask');
+ verticalMaskElement.show();
+ verticalMaskElement.mask();
+ }
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'exitModalView': function() {
+ if (this.user().preferences().useSafeEditMode()) {
+ var headerMaskElement;
+ var verticalMaskElement;
+
+ headerMaskElement = YAHOO.ext.Element.get('recordDetailEditModeHeaderMask');
+ headerMaskElement.unmask();
+ headerMaskElement.hide();
+
+ verticalMaskElement = YAHOO.ext.Element.get('recordDetailEditModeVerticalMask');
+ verticalMaskElement.unmask();
+ verticalMaskElement.hide();
+ }
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'removeSelectedRecord': function() {
+ var selectedRecordReferences;
+
+//MochiKit.Logging.logDebug(">>> MainPanel.removeSelectedRecord");
+ if (this.selectedRecord() != null) {
+ selectedRecordReferences = [this.selectedRecord().reference()];
+ } else {
+ selectedRecordReferences = [];
+ }
+
+ if (selectedRecordReferences.length > 0 ) {
+ var recordReference;
+ var records;
+ var deferred;
+
+ records = [];
+ for (recordReference in selectedRecordReferences) {
+ var record;
+
+//MochiKit.Logging.logDebug("### MainPanel.removeSelectedRecord - recordReference: " + selectedRecordReferences[recordReference]);
+ record = this.user().records()[selectedRecordReferences[recordReference]];
+//MochiKit.Logging.logDebug("### MainPanel.removeSelectedRecord - record: " + record);
+ records.push(record);
+ }
+//MochiKit.Logging.logDebug("### MainPanel.removeSelectedRecord - records.length: " + records.length);
+
+ deferred = new MochiKit.Async.Deferred();
+//MochiKit.Logging.logDebug("--- MainPanel.removeSelectedRecord - 1:");
+//deferred.addBoth(function(res) {MochiKit.Logging.logDebug("MainPanel.removeSelectedRecord - 1: " + res); return res;});
+//MochiKit.Logging.logDebug("--- MainPanel.removeSelectedRecord - 2:");
+ deferred.addCallback(function() {
+ var deferredResult;
+
+ deferredResult = new MochiKit.Async.Deferred();
+ Clipperz.PM.Components.MessageBox().deferredShow({
+ title:Clipperz.PM.Strings['mainPanelDeletingRecordPanelConfirmationTitle'],
+ text:Clipperz.PM.Strings['mainPanelDeleteRecordPanelConfirmationText'],
+ width:240,
+ showProgressBar:false,
+ showCloseButton:false,
+ buttons:{
+ 'yes':Clipperz.PM.Strings['mainPanelDeleteRecordPanelConfirmButtonLabel'],
+ 'no':Clipperz.PM.Strings['mainPanelDeleteRecordPanelDenyButtonLabel']
+ },
+ fn:MochiKit.Base.partial(function(aDeferred, aResult) {
+ if (aResult == 'yes') {
+ aDeferred.callback(aResult);
+ } else {
+ aDeferred.errback(aResult);
+ }
+ }, deferredResult)
+ }, 'recordListRemoveRecordButton');
+
+ return deferredResult;
+ });
+//MochiKit.Logging.logDebug("--- MainPanel.removeSelectedRecord - 3:");
+//deferred.addBoth(function(res) {MochiKit.Logging.logDebug("MainPanel.removeSelectedRecord - 2: " + res); return res;});
+//MochiKit.Logging.logDebug("--- MainPanel.removeSelectedRecord - 4:");
+//deferred.addBoth(function(res) {MochiKit.Logging.logDebug("MainPanel.removeSelectedRecord - 3: " + res); return res;});
+ deferred.addCallback(MochiKit.Base.method(Clipperz.PM.Components.MessageBox(), 'deferredShow'),
+ {
+ title:Clipperz.PM.Strings['mainPanelDeletingRecordPanelInitialTitle'],
+ text:Clipperz.PM.Strings['mainPanelDeletingRecordPanelInitialText'],
+ width:240,
+ showProgressBar:true,
+ showCloseButton:false,
+ steps:5
+ }
+ );
+//MochiKit.Logging.logDebug("--- MainPanel.removeSelectedRecord - 5:");
+//deferred.addBoth(function(res) {MochiKit.Logging.logDebug("MainPanel.removeSelectedRecord - 4: " + res); return res;});
+ deferred.addCallback(MochiKit.Base.method(this.user(), 'deleteRecordsAction'), records);
+//MochiKit.Logging.logDebug("--- MainPanel.removeSelectedRecord - 6:");
+//deferred.addBoth(function(res) {MochiKit.Logging.logDebug("MainPanel.removeSelectedRecord - 5: " + res); return res;});
+//MochiKit.Logging.logDebug("--- MainPanel.removeSelectedRecord - 7:");
+//deferred.addBoth(function(res) {MochiKit.Logging.logDebug("MainPanel.removeSelectedRecord - 6: " + res); return res;});
+ deferred.addCallback(function() {
+ Clipperz.PM.Components.MessageBox().update({
+ title:null,
+ text:Clipperz.PM.Strings['mainPanelDeletingRecordPanelCompletedText'],
+ step:'next',
+ buttons:{}
+ });
+ });
+//MochiKit.Logging.logDebug("--- MainPanel.removeSelectedRecord - 8:");
+//deferred.addBoth(function(res) {MochiKit.Logging.logDebug("MainPanel.removeSelectedRecord - 7: " + res); return res;});
+ deferred.addCallback(MochiKit.Async.wait, 1);
+//MochiKit.Logging.logDebug("--- MainPanel.removeSelectedRecord - 9:");
+//deferred.addBoth(function(res) {MochiKit.Logging.logDebug("MainPanel.removeSelectedRecord - 8: " + res); return res;});
+ deferred.addCallback(function(res) {
+ Clipperz.PM.Components.MessageBox().hide(YAHOO.ext.Element.get('main'));
+ return res;
+ });
+//MochiKit.Logging.logDebug("--- MainPanel.removeSelectedRecord - 10:");
+//deferred.addBoth(function(res) {MochiKit.Logging.logDebug("MainPanel.removeSelectedRecord - 9: " + res); return res;});
+ deferred.callback();
+ } else {
+//MochiKit.Logging.logDebug("+++ MainPanel.removeSelectedRecord - nothing selected");
+ }
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'recordDetailComponent': function() {
+//MochiKit.Logging.logDebug(">>> MainPanel.recordDetailComponent");
+ if (this._recordDetailComponent == null) {
+//MochiKit.Logging.logDebug("--- MainPanel.recordDetailComponent - 1");
+//MochiKit.Logging.logDebug("--- MainPanel.recordDetailComponent - 1 - user: " + this.user());
+ this._recordDetailComponent = new Clipperz.PM.Components.RecordDetail.MainComponent(
+ YAHOO.ext.Element.get('recordDetail'),
+ {user:this.user(), mainPanel:this}
+ );
+ }
+
+//MochiKit.Logging.logDebug("<<< MainPanel.recordDetailComponent");
+
+ return this._recordDetailComponent;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'selectedRecord': function() {
+ return this._selectedRecord;
+ },
+
+ 'setSelectedRecord': function(aValue) {
+// this.hideNewRecordPanel();
+//MochiKit.Logging.logDebug(">>> MainPanel.setSelectedRecord");
+ if (aValue != this._selectedRecord) {
+//MochiKit.Logging.logDebug("--- MainPanel.setSelectedRecord - 1");
+ this._selectedRecord = aValue;
+//MochiKit.Logging.logDebug("--- MainPanel.setSelectedRecord - 2");
+ this.redrawRecordItems();
+//MochiKit.Logging.logDebug("--- MainPanel.setSelectedRecord - 3");
+ this.recordDetailComponent().setRecord(aValue);
+//MochiKit.Logging.logDebug("--- MainPanel.setSelectedRecord - 4");
+ }
+
+ if ((aValue == null) || (Clipperz.PM.Proxy.defaultProxy.isReadOnly())) {
+ this.deleteRecordButton().disable();
+ } else {
+ this.deleteRecordButton().enable();
+ }
+//MochiKit.Logging.logDebug("<<< MainPanel.setSelectedRecord");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'recordAddedHandler': function(anEvent) {
+//MochiKit.Logging.logDebug(">>> MainPanel.recordAddedHandler");
+ this.recordDetailComponent();
+ this.redrawRecordItems();
+//MochiKit.Logging.logDebug("<<< MainPanel.recordAddedHandler");
+ },
+
+ 'recordUpdatedHandler': function(anEvent) {
+//MochiKit.Logging.logDebug(">>> MainPanel.recordUpdatedHandler");
+ this.redrawRecordItems();
+//MochiKit.Logging.logDebug("<<< MainPanel.recordUpdatedHandler");
+ },
+
+ 'recordRemovedHandler': function(anEvent) {
+//MochiKit.Logging.logDebug(">>> MainPanel.recordRemovedHandler");
+ this.setSelectedRecord(null);
+//MochiKit.Logging.logDebug("--- MainPanel.recordRemovedHandler - 1");
+ this.redrawRecordItems();
+//MochiKit.Logging.logDebug("<<< MainPanel.recordRemovedHandler");
+ },
+
+ 'compareRecords': function(a, b) {
+//MochiKit.Logging.logDebug("=== compareRecords: " + a.toString() + " - " + b.toString());
+ return MochiKit.Base.compare(a.label().toLowerCase(), b.label().toLowerCase());
+ },
+
+ 'redrawRecordItems': function() {
+ var template;
+ var allRecords;
+
+//MochiKit.Logging.logDebug(">>> MainPanel.redrawRecordItems");
+ MochiKit.Iter.forEach(YAHOO.ext.Element.get('records').getChildrenByTagName('li'), function(aRecordElement) {
+ MochiKit.Signal.disconnectAll(aRecordElement.dom);
+ })
+//MochiKit.Logging.logDebug("--- MainPanel.redrawRecordItems - 1");
+ YAHOO.ext.Element.get('records').update("");
+//MochiKit.Logging.logDebug("--- MainPanel.redrawRecordItems - 2");
+ allRecords = MochiKit.Base.values(this.user().records());
+//MochiKit.Logging.logDebug("--- MainPanel.redrawRecordItems - 3");
+ allRecords.sort(this.compareRecords);
+//MochiKit.Logging.logDebug("--- MainPanel.redrawRecordItems - 4");
+ template = this.recordItemTemplate();
+//MochiKit.Logging.logDebug("--- MainPanel.redrawRecordItems - 5");
+ MochiKit.Iter.forEach(allRecords, MochiKit.Base.bind(function(aRecord) {
+ var recordElement;
+ recordElement = template.append('records', {
+ recordTitle:aRecord.label(),
+ recordReference:aRecord.reference(),
+ cls:((aRecord == this.selectedRecord()) ? 'selected': '')
+ }, true);
+//MochiKit.Logging.logDebug("--- MainPanel.redrawRecordItems - 6: " + recordElement.dom);
+ recordElement.addClassOnOver('hover');
+ MochiKit.Signal.connect(recordElement.dom, 'onclick', this, 'selectRecord');
+ }, this));
+//MochiKit.Logging.logDebug("<<< MainPanel.redrawRecordItems");
+ },
+
+ 'selectRecord': function(anEvent) {
+//MochiKit.Logging.logDebug(">>> MainPanel.selectRecord");
+//MochiKit.Logging.logDebug("--- MainPanel.selectRecord !!! - ", this.user().records()[anEvent.src().id].label());
+ this.setSelectedRecord(this.user().records()[anEvent.src().id]);
+//MochiKit.Logging.logDebug("<<< MainPanel.selectRecord");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'directLoginAddedHandler': function(anEvent) {
+//MochiKit.Logging.logDebug(">>> MainPanel.recordRemovedHandler");
+ this.redrawDirectLoginItems();
+//MochiKit.Logging.logDebug("<<< MainPanel.recordRemovedHandler");
+ },
+
+ 'directLoginUpdatedHandler': function(anEvent) {
+//MochiKit.Logging.logDebug(">>> MainPanel.directLoginUpdatedHandler");
+ this.redrawDirectLoginItems();
+//MochiKit.Logging.logDebug("<<< MainPanel.directLoginUpdatedHandler");
+ },
+
+ 'directLoginRemovedHandler': function(anEvent) {
+//MochiKit.Logging.logDebug(">>> MainPanel.directLoginRemovedHandler");
+ this.redrawDirectLoginItems();
+//MochiKit.Logging.logDebug("<<< MainPanel.directLoginRemovedHandler");
+ },
+
+ 'compareDirectLogins': function(a, b) {
+ return MochiKit.Base.compare(a.label().toLowerCase(), b.label().toLowerCase());
+ },
+
+ 'redrawDirectLoginItems': function() {
+ var template;
+ var allDirectLogins;
+
+//MochiKit.Logging.logDebug(">>> MainPanel.redrawDirectLoginItems");
+ MochiKit.Iter.forEach(YAHOO.ext.Element.get('directLogins').getChildrenByTagName('li'), function(aDirectLoginElement) {
+ MochiKit.Signal.disconnectAll(aDirectLoginElement.dom);
+//MochiKit.Logging.logDebug("disconnecting IMG " + aDirectLoginElement.getChildrenByTagName('img')[0].dom.src);
+ MochiKit.Signal.disconnectAll(aDirectLoginElement.getChildrenByTagName('img')[0].dom);
+ })
+//MochiKit.Logging.logDebug("--- MainPanel.redrawDirectLoginItems - 1");
+ YAHOO.ext.Element.get('directLogins').update("");
+//MochiKit.Logging.logDebug("--- MainPanel.redrawDirectLoginItems - 2");
+ allDirectLogins = MochiKit.Base.values(this.user().directLoginReferences());
+//MochiKit.Logging.logDebug("--- MainPanel.redrawDirectLoginItems - 3");
+ allDirectLogins.sort(this.compareDirectLogins);
+
+ if (allDirectLogins.length == 0) {
+ YAHOO.ext.Element.get('directLoginsDescription').show();
+ YAHOO.ext.Element.get('directLogins').setVisibilityMode(YAHOO.ext.Element.DISPLAY).hide();
+ } else {
+ YAHOO.ext.Element.get('directLoginsDescription').setVisibilityMode(YAHOO.ext.Element.DISPLAY).hide();
+ YAHOO.ext.Element.get('directLogins').show();
+ }
+//MochiKit.Logging.logDebug("--- MainPanel.redrawDirectLoginItems - 4");
+ template = this.directLoginItemTemplate();
+//MochiKit.Logging.logDebug("--- MainPanel.redrawDirectLoginItems - 5");
+ MochiKit.Iter.forEach(allDirectLogins, MochiKit.Base.bind(function(aDirectLogin) {
+ var directLoginElement;
+ var faviconImageElementID;
+
+ faviconImageElementID = aDirectLogin.reference() + "_faviconIMG";
+ directLoginElement = template.append('directLogins', {
+ elementID:faviconImageElementID,
+ faviconUrl:aDirectLogin.fixedFavicon(),
+ directLoginTitle:aDirectLogin.label(),
+ directLoginReference:aDirectLogin.reference()
+ }, true);
+//MochiKit.Logging.logDebug("--- MainPanel.redrawDirectLoginItems - 6: " + recordElement.dom);
+ directLoginElement.addClassOnOver("hover");
+ MochiKit.Signal.connect(directLoginElement.dom, 'onclick', this, 'handleDirectLoginClick');
+
+ MochiKit.Signal.connect(faviconImageElementID, 'onload', this, 'handleLoadedFaviconImage');
+ MochiKit.Signal.connect(faviconImageElementID, 'onerror', aDirectLogin, 'handleMissingFaviconImage');
+ MochiKit.Signal.connect(faviconImageElementID, 'onabort', aDirectLogin, 'handleMissingFaviconImage');
+
+// YAHOO.ext.Element.get(faviconImageElementID).dom.src = aDirectLogin.fixedFavicon();
+ }, this));
+//MochiKit.Logging.logDebug("<<< MainPanel.redrawDirectLoginItems");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'handleDirectLoginClick': function(anEvent) {
+ var directLoginReference;
+//MochiKit.Logging.logDebug(">>> MainPanel.handleDirectLoginClick !!!");
+
+ directLoginReference = this.user().directLoginReferences()[anEvent.src().id];
+ if (anEvent.target().className == 'directLoginItemEditButton') {
+ this.editDirectLogin(directLoginReference);
+ } else {
+ this.openDirectLogin(directLoginReference);
+ }
+//MochiKit.Logging.logDebug("<<< MainPanel.handleDirectLoginClick");
+ },
+
+ 'editDirectLogin': function(aDirectLoginReference) {
+//MochiKit.Logging.logDebug("=== MainPanel.editDirectLogin - " + aDirectLoginReference.label());
+ this.setSelectedRecord(aDirectLoginReference.record());
+ },
+
+ 'openDirectLogin': function(aDirectLoginReference) {
+ var deferredResult;
+ var newWindow;
+
+//MochiKit.Logging.logDebug(">>> MainPanel.openDirectLogin - " + aDirectLoginReference.label());
+ deferredResult = new MochiKit.Async.Deferred();
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("MainPanel.openDirectLogin - 1: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(aDirectLoginReference, 'setupJumpPageWindow'));
+ deferredResult.addCallback(MochiKit.Base.method(aDirectLoginReference, 'deferredDirectLogin'));
+ deferredResult.addCallback(function(aDirectLogin) {
+ aDirectLogin.runDirectLogin(newWindow);
+ });
+
+ newWindow = window.open(Clipperz.PM.Strings['directLoginJumpPageUrl'], "");
+// MochiKit.Signal.connect(newWindow, 'onload', MochiKit.Base.method(deferredResult, 'callback', newWindow))
+// MochiKit.Signal.connect(newWindow, 'onload', MochiKit.Base.partial(alert, "done"));
+ deferredResult.callback(newWindow);
+//MochiKit.Logging.logDebug("<<< MainPanel.openDirectLogin");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'handleLoadedFaviconImage': function(anEvent) {
+//MochiKit.Logging.logDebug(">>> MainPanel.handleLoadedFaviconImage");
+ MochiKit.Signal.disconnectAll(anEvent.src())
+//MochiKit.Logging.logDebug("<<< MainPanel.handleLoadedFaviconImage");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'recordItemTemplate': function() {
+ if (this._recordItemTemplate == null) {
+ this._recordItemTemplate = Clipperz.YUI.DomHelper.createTemplate({tag:'li', cls:'{cls}', id:'{recordReference}', children:[
+ {tag:'span', html:'{recordTitle}'}
+ ]});
+ this._recordItemTemplate.compile();
+ }
+
+ return this._recordItemTemplate;
+ },
+
+ 'directLoginItemTemplate': function() {
+ if (this._directLoginItemTemplate == null) {
+ this._directLoginItemTemplate = Clipperz.YUI.DomHelper.createTemplate({tag:'li', id:'{directLoginReference}', children:[
+ {tag:'table', border:'0', cellpadding:'0', cellspacing:'0', children:[
+ {tag:'tbody', children:[
+ {tag:'tr', children:[
+ {tag:'td', width:'20', align:'center', valign:'top', children:[
+ {tag:'img', id:'{elementID}', src:'{faviconUrl}'}
+ ]},
+ {tag:'td', valign:'top', children:[
+ {tag:'a', cls:'directLoginItemTitle', html:'{directLoginTitle}'}
+ ]},
+ {tag:'td', valign:'top', align:'right', children:[
+// {tag:'span', cls:'directLoginItemEditButton', htmlString:Clipperz.PM.Strings['directLinkReferenceShowButtonLabel']}
+ {tag:'a', cls:'directLoginItemEditButton', htmlString:Clipperz.PM.Strings['directLinkReferenceShowButtonLabel']}
+ ]}
+ ]}
+ ]}
+ ]}
+ ]});
+ this._directLoginItemTemplate.compile();
+ }
+
+ return this._directLoginItemTemplate;
+ },
+
+ //-------------------------------------------------------------------------
+/*
+ 'newRecordButton': function() {
+ return this._newRecordButton;
+ },
+
+ 'setNewRecordButton': function(aValue) {
+ this._newRecordButton = aValue;
+ },
+
+ 'newRecordCancelButton': function() {
+ return this._newRecordCancelButton;
+ },
+
+ 'setNewRecordCancelButton': function(aValue) {
+ this._newRecordCancelButton = aValue;
+ },
+*/
+ //-------------------------------------------------------------------------
+
+ 'onkeydown': function(anEvent) {
+//MochiKit.Logging.logDebug(">>> onkeydown - " + anEvent.src().id + ": " + anEvent.key().code);
+ switch (anEvent.src().id) {
+/*
+ case this.getId('newRecordForm'):
+ if (anEvent.key().code == 13) {
+ this.newRecordButton().focus();
+// this.addNewRecord();
+ } else if (anEvent.key().code == 27) {
+ this.newRecordCancelButton().focus();
+ this.hideNewRecordPanel(true);
+ }
+ break;
+*/
+ case "recordFilterSearchForm":
+ if (anEvent.key().code == 13) {
+//MochiKit.Logging.logDebug("SEARCH");
+ this.filterCardsWithName(YAHOO.ext.Element.get('recordFilterSearchValue').dom.value);
+ anEvent.event().stopPropagation();
+ YAHOO.ext.Element.get('recordFilterSearchValue').focus();
+ } else if (anEvent.key().code == 27) {
+ this.hideRecordFilterSearchPanel(true);
+ this.showRecordFilterAllPanel();
+ }
+ break;
+ }
+
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'renderRecordListBlockHeader': function(){
+ var recordListBlockHeaderElement;
+
+ recordListBlockHeaderElement = YAHOO.ext.Element.get('recordListBlockHeader');
+ recordListBlockHeaderElement.update("");
+ Clipperz.YUI.DomHelper.append(recordListBlockHeaderElement.dom,
+ {tag:'table', cls:'recordListBlockHeaderTABLE', border:'0', cellspacing:'0', cellpadding:'0', children:[
+ {tag:'tbody', children:[
+ {tag:'tr', children:[
+ {tag:'td', /*width:'50%',*/ cls:'recordBlockTitleTD', children:[
+ {tag:'h3', id:'recordBlockTitle', htmlString:Clipperz.PM.Strings['mainPanelRecordsBlockLabel']}
+ ]},
+ {tag:'td', align:'right', children:[
+ {tag:'table', id:'recordListButtonsTABLE', border:'0', cellspacing:'0', cellpadding:'0', children:[
+ {tag:'tbody', children:[
+ {tag:'tr', children:[
+ {tag:'td', cls:'recordButtonTD', align:'right', children:[
+ {tag:'div', cls:'recordButton', id:'recordListAddRecordButton'}
+ ]},
+ {tag:'td', cls:'recordButtonTD', align:'left', children:[
+ {tag:'div', cls:'recordButton', id:'recordListRemoveRecordButton'}
+ ]}
+ ]}
+ ]}
+ ]}
+ ]},
+ {tag:'td', width:'15', html:"&nbsp;"}
+ ]}
+ ]}
+ ]}
+ );
+
+ this.setAddNewRecordButton(new YAHOO.ext.Button('recordListAddRecordButton', {text:Clipperz.PM.Strings['mainPanelAddRecordButtonLabel'], handler:this.addNewRecord, scope:this}));
+// this.setAddNewRecordButton(new YAHOO.ext.Button('recordListAddRecordButton', {text:Clipperz.PM.Strings['mainPanelAddRecordButtonLabel'], handler:this.showNewRecordPanel, scope:this}));
+ this.setDeleteRecordButton(new YAHOO.ext.Button('recordListRemoveRecordButton', {text:Clipperz.PM.Strings['mainPanelRemoveRecordButtonLabel'], handler:this.removeSelectedRecord, scope:this}));
+
+
+ if ((Clipperz.PM.Proxy.defaultProxy.isReadOnly()) || (this.selectedRecord() == null)) {
+ this.deleteRecordButton().disable();
+ }
+
+ if (Clipperz.PM.Proxy.defaultProxy.isReadOnly()) {
+ this.addNewRecordButton().disable();
+ }
+
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'renderRecordListFilterHeader': function(){
+ var recordListFilterHeaderElement;
+
+ recordListFilterHeaderElement = YAHOO.ext.Element.get('recordListFilterHeader');
+ recordListFilterHeaderElement.update("");
+ Clipperz.YUI.DomHelper.append(recordListFilterHeaderElement.dom,
+ {tag:'div', id:'recordFiltersDIV', children:[
+ {tag:'div', id:'recordFiltersTableWrapper', children:[
+ {tag:'table', id:'recordFiltersTABLE', border:'0', cellspacing:'0', cellpadding:'0', children:[
+ {tag:'tbody', children:[
+ {tag:'tr', children:[
+ {tag:'td', id:'recordFilterAllTD', children:[{tag:'div', children:[{tag:'a', id:'recordFilterAll', htmlString:Clipperz.PM.Strings['mainPanelRecordFilterBlockAllLabel']}]}]},
+ {tag:'td', id:'recordFilterTagsTD', children:[{tag:'div', children:[{tag:'a', id:'recordFilterTags', htmlString:Clipperz.PM.Strings['mainPanelRecordFilterBlockTagsLabel']}]}]},
+ {tag:'td', id:'recordFilterSearchTD', children:[{tag:'div', children:[{tag:'a', id:'recordFilterSearch', htmlString:Clipperz.PM.Strings['mainPanelRecordFilterBlockSearchLabel']}]}]}
+ ]}
+ ]}
+ ]}
+ ]},
+ {tag:'div', id:'recordFiltersTagsPanel'},
+ {tag:'div', id:'recordFiltersSearchPanel', children:[{tag:'div', id:'recordFiltersSearchInnerPanel', children:[{tag:'div', id:'recordFiltersSearchInnerInnerPanel', children:[
+ {tag:'form', id:'recordFilterSearchForm', children:[
+ {tag:'input', type:'text', name:'search', id:'recordFilterSearchValue'}
+ ]}
+ ]}]}]}
+ ]}
+ );
+
+/// YAHOO.ext.Element.get('recordFiltersSearchPanel').setVisibilityMode(YAHOO.ext.Element.DISPLAY).hide();
+ this.showRecordFilterAllPanel(false);
+
+ MochiKit.Signal.connect('recordFilterSearchForm', 'onkeydown', this, 'onkeydown');
+ MochiKit.Signal.connect('recordFilterSearchForm', 'onsubmit', this, 'onkeydown');
+
+ MochiKit.Signal.connect('recordFilterAll', 'onclick', this, 'showRecordFilterAllPanel');
+ MochiKit.Signal.connect('recordFilterTags', 'onclick', this, 'showRecordFilterTagsPanel');
+ MochiKit.Signal.connect('recordFilterSearch', 'onclick', this, 'showRecordFilterSearchPanel');
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'showRecordFilterAllPanel': function(shouldSlide) {
+ this.hideRecordFilterTagsPanel(shouldSlide);
+ this.hideRecordFilterSearchPanel(shouldSlide);
+ YAHOO.ext.Element.get('recordFilterAllTD').addClass('selectedTab');
+ },
+
+ 'hideRecordFilterAllPanel': function(shouldSlide) {
+ YAHOO.ext.Element.get('recordFilterAllTD').removeClass('selectedTab');
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'showRecordFilterTagsPanel': function(shouldSlide) {
+ this.hideRecordFilterAllPanel(shouldSlide);
+ this.hideRecordFilterSearchPanel(shouldSlide);
+ YAHOO.ext.Element.get('recordFilterTagsTD').addClass('selectedTab');
+ },
+
+ 'hideRecordFilterTagsPanel': function(shouldSlide) {
+ YAHOO.ext.Element.get('recordFilterTagsTD').removeClass('selectedTab');
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'showRecordFilterSearchPanel': function(shouldSlide) {
+ var searchPanelActor;
+
+ this.hideRecordFilterAllPanel(shouldSlide);
+ this.hideRecordFilterTagsPanel(shouldSlide);
+ YAHOO.ext.Element.get('recordFilterSearchTD').addClass('selectedTab');
+ YAHOO.ext.Element.get('recordFilterSearchValue').dom.value = "";
+
+ searchPanelActor = new YAHOO.ext.Actor('recordFiltersSearchPanel');
+
+ searchPanelActor.startCapture(true);
+ searchPanelActor.slideShow('top', 54);
+ searchPanelActor.play(MochiKit.Base.bind(function() {
+ YAHOO.ext.Element.get('recordFilterSearchValue').focus();
+ }, this));
+ },
+
+ 'hideRecordFilterSearchPanel': function(shouldSlide) {
+ var searchPanelActor;
+ var callback;
+
+ YAHOO.ext.Element.get('recordFilterSearchTD').removeClass('selectedTab');
+
+ searchPanelActor = new YAHOO.ext.Actor('recordFiltersSearchPanel');
+
+ searchPanelActor.startCapture(true)
+ if (shouldSlide === false) {
+ searchPanelActor.hide();
+ searchPanelActor.slideHide('top');
+ searchPanelActor.show();
+ } else {
+ searchPanelActor.slideHide('top');
+ }
+
+ callback = MochiKit.Base.bind(function() {
+ }, this);
+
+ searchPanelActor.play(callback);
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'filterCardsWithName': function(aValue) {
+MochiKit.Logging.logDebug(">>> filterCardsWithName: " + aValue);
+
+MochiKit.Logging.logDebug("<<< filterCardsWithName");
+ },
+
+ 'accountLockedHandler': function() {
+ this.setSelectedRecord(null);
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'switchLanguageHandler': function() {
+ YAHOO.ext.Element.get('directLoginTitle').update(Clipperz.PM.Strings['mainPanelDirectLoginBlockLabel']);
+ YAHOO.ext.Element.get('directLoginsDescription').update("");
+ MochiKit.Iter.forEach(Clipperz.PM.Strings['mainPanelDirectLoginBlockDescriptionConfig'], function(aConfigItem) {
+ Clipperz.YUI.DomHelper.append(YAHOO.ext.Element.get('directLoginsDescription').dom, aConfigItem);
+ });
+ YAHOO.ext.Element.get('recordBlockTitle').update(Clipperz.PM.Strings['mainPanelRecordsBlockLabel']);
+ this.renderRecordListBlockHeader();
+// this.renderRecordListFilterHeader();
+
+// YAHOO.ext.Element.get('newRecordPanelTitleH2').update(Clipperz.PM.Strings['mainPanelNewRecordPanelTitle']);
+// YAHOO.ext.Element.get('newRecordPanelTitleLabel').update(Clipperz.PM.Strings['mainPanelNewRecordPanelRecordTitleLabel']);
+// YAHOO.ext.Element.get('newRecordPanelConfigLabel').update("");
+// MochiKit.Iter.forEach(Clipperz.PM.Strings['mainPanelNewRecordPanelRecordConfigConfig'], function(aConfigItem) {
+// Clipperz.YUI.DomHelper.append(YAHOO.ext.Element.get('newRecordPanelConfigLabel').dom, aConfigItem);
+// });
+// this.newRecordButton().setText(Clipperz.PM.Strings['mainPanelNewRecordPanelCreateButtonLabel']);
+// this.newRecordCancelButton().setText(Clipperz.PM.Strings['mainPanelNewRecordPanelCancelButtonLabel']);
+
+ this.recordDetailComponent().render();
+ },
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+
+});
diff --git a/frontend/beta/js/Clipperz/PM/Components/Panels/ToolsPanel.js b/frontend/beta/js/Clipperz/PM/Components/Panels/ToolsPanel.js
new file mode 100644
index 0000000..abd2621
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Components/Panels/ToolsPanel.js
@@ -0,0 +1,305 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
+if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
+if (typeof(Clipperz.PM.Components) == 'undefined') { Clipperz.PM.Components = {}; }
+if (typeof(Clipperz.PM.Components.Panels) == 'undefined') { Clipperz.PM.Components.Panels = {}; }
+
+//#############################################################################
+
+Clipperz.PM.Components.Panels.ToolsPanel = function(anElement, args) {
+ args = args || {};
+
+ Clipperz.PM.Components.Panels.ToolsPanel.superclass.constructor.call(this, anElement, args);
+
+ this._generateButtonElement = null;
+ this._needsRenderingUponTabSwitch = false;
+
+ this.render();
+
+ return this;
+}
+
+//=============================================================================
+
+YAHOO.extendX(Clipperz.PM.Components.Panels.ToolsPanel, Clipperz.PM.Components.Panels.BasePanel, {
+
+ 'toString': function() {
+ return "Clipperz.PM.Components.Panels.ToolsPanel component";
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'render': function() {
+ var bookmarkletUrl;
+
+//MochiKit.Logging.logDebug(">>> ToolsPanel.render");
+ Clipperz.NotificationCenter.unregister(this);
+ MochiKit.Signal.disconnectAllTo(this);
+
+ if (Clipperz_IEisBroken == true) {
+ bookmarkletUrl = bookmarklet_ie;
+ } else {
+ bookmarkletUrl = bookmarklet;
+ }
+
+ this.element().update("");
+ Clipperz.YUI.DomHelper.append(this.element().dom, {tag:'table', border:'0', cellspacing:'0', cellpadding:'0', children:[
+ {tag:'tbody', children:[
+ {tag:'tr', children:[
+ {tag:'td', valign:'top', width:'200', children:[
+ {tag:'ul', id:"dataSubMenu", cls:'subMenu', children:[
+ {tag:'li', id:this.getId('passwordGenerator'), htmlString:Clipperz.PM.Strings['passwordGeneratorTabLabel']},
+ {tag:'li', id:this.getId('bookmarklet'), htmlString:Clipperz.PM.Strings['bookmarkletTabLabel']},
+ {tag:'li', id:this.getId('compact'), htmlString:Clipperz.PM.Strings['compactTabLabel']},
+ {tag:'li', id:this.getId('httpAuth'), htmlString:Clipperz.PM.Strings['httpAuthTabLabel']}
+ ]}
+ ]},
+ {tag:'td', valign:'top', children:[
+ {tag:'ul', cls:'clipperzTabPanels', children:[
+ {tag:'li', id:this.getId('passwordGeneratorPanel'), children:[
+ {tag:'div', cls:'clipperzSubPanel', children:[
+ {tag:'h5', htmlString:Clipperz.PM.Strings['passwordGeneratorTabTitle']},
+ {tag:'div', cls:'panelDescription', htmlString:Clipperz.PM.Strings['paswordGeneratorTabDescription']},
+
+ //---------------------------------------------------
+ {tag:'div', children:[
+ {tag:'form', id:this.getId('passwordGeneratorForm'), cls:'passwordGenerator', children:[
+ {tag:'input', type:'text', cls:'clipperz_passwordGenerator_password', id:this.getId('passwordField')},
+ {tag:'table', children:[
+ {tag:'tbody', children:[
+ {tag:'tr', children:[
+ {tag:'td', width:'20%', children:[
+ {tag:'input', type:'checkbox', name:'lowercase', id:this.getId('lowercase'), checked:true},
+ {tag:'span', htmlString:Clipperz.PM.Strings['passwordGeneratorLowercaseLabel']}
+ ]},
+ {tag:'td', width:'20%', children:[
+ {tag:'input', type:'checkbox', name:'uppercase', id:this.getId('uppercase'), checked:true},
+ {tag:'span', htmlString:Clipperz.PM.Strings['passwordGeneratorUppercaseLabel']}
+ ]},
+ {tag:'td', width:'20%', children:[
+ {tag:'input', type:'checkbox', name:'numbers', id:this.getId('numbers'), checked:true},
+ {tag:'span', htmlString:Clipperz.PM.Strings['passwordGeneratorNumberLabel']}
+ ]},
+ {tag:'td', width:'20%', children:[
+ {tag:'input', type:'checkbox', name:'symbols', id:this.getId('symbols'), checked:true},
+ {tag:'span', htmlString:Clipperz.PM.Strings['passwordGeneratorSymbolLabel']}
+ ]},
+ {tag:'td', width:'20%', children:[
+ {tag:'span', cls:'passwordGeneratorLength', children:[
+ {tag:'span', htmlString:Clipperz.PM.Strings['passwordGeneratorLengthLabel']},
+ {tag:'span', id:this.getId('passwordLength'), cls:'passwordGeneratorLengthValue', html:'0'}
+ ]}
+ ]}
+ ]}
+ ]}
+ ]}
+ ]},
+ {tag:'div', id:this.getId('generateRandomPassword')}
+ ]}
+ //---------------------------------------------------
+
+ ]}
+ ]},
+ {tag:'li', id:this.getId('bookmarkletPanel'), children:[
+ {tag:'div', cls:'clipperzSubPanel', children:[
+ {tag:'h5', htmlString:Clipperz.PM.Strings['bookmarkletTabTitle']},
+ {tag:'div', cls:'panelDescription', htmlString:Clipperz.PM.Strings['bookmarkletTabDescription']},
+ {tag:'a', href:bookmarkletUrl, cls:'bookmarkletLink', htmlString:Clipperz.PM.Strings['bookmarkletTabBookmarkletTitle']},
+ {tag:'div', cls:'panelDescription', htmlString:Clipperz.PM.Strings['bookmarkletTabInstructions']}
+ ]}
+ ]},
+ {tag:'li', id:this.getId('compactPanel'), children:[
+ {tag:'div', cls:'clipperzSubPanel', children:[
+ {tag:'h5', htmlString:Clipperz.PM.Strings['compactTabTitle']},
+ {tag:'div', cls:'panelDescription', htmlString:Clipperz.PM.Strings['compactTabDescription']}
+ ]}
+ ]},
+ {tag:'li', id:this.getId('httpAuthPanel'), children:[
+ {tag:'div', cls:'clipperzSubPanel', children:[
+ {tag:'h5', htmlString:Clipperz.PM.Strings['httpAuthTabTitle']},
+ {tag:'div', cls:'panelDescription', htmlString:Clipperz.PM.Strings['httpAuthTabDescription']},
+ {tag:'div', cls:'bookmarkletConfiguration', children:[Clipperz.PM.Strings['httpAuthBookmarkletConfiguration']]}
+ ]}
+ ]}
+ ]}
+ ]}
+ ]}
+ ]}
+ ]});
+
+ new Clipperz.PM.Components.PasswordEntropyDisplay(this.getElement('passwordField'));
+
+ MochiKit.Signal.connect(this.getId('lowercase'), 'onclick', this, 'updatePasswordValue');
+ MochiKit.Signal.connect(this.getId('uppercase'), 'onclick', this, 'updatePasswordValue');
+ MochiKit.Signal.connect(this.getId('numbers'), 'onclick', this, 'updatePasswordValue');
+ MochiKit.Signal.connect(this.getId('symbols'), 'onclick', this, 'updatePasswordValue');
+
+ MochiKit.Signal.connect(this.getDom('passwordField'), 'onkeyup', this, 'updatePasswordLengthLabel');
+ MochiKit.Signal.connect(this.getDom('passwordField'), 'onchange', this, 'updatePasswordLengthLabel');
+ MochiKit.Signal.connect(this.getDom('passwordField'), 'onblur', this, 'updatePasswordLengthLabel');
+
+ this.setGenerateButtonElement(new YAHOO.ext.Button(this.getDom('generateRandomPassword'), {text:Clipperz.PM.Strings['passwordGeneratorTabButtonLabel'], handler:this.updatePasswordValue, scope:this}));
+
+ this.setNeedsRenderingUponTabSwitch(false);
+ this.tabPanelController().setUp();
+ Clipperz.NotificationCenter.register(null, 'tabSelected', this, 'tabSelectedHandler');
+ Clipperz.NotificationCenter.register(null, 'switchLanguage', this, 'switchLanguageHandler');
+//MochiKit.Logging.logDebug("<<< ToolsPanel.render");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'needsRenderingUponTabSwitch': function() {
+ return this._needsRenderingUponTabSwitch;
+ },
+
+ 'setNeedsRenderingUponTabSwitch': function(aValue) {
+ this._needsRenderingUponTabSwitch = aValue;
+ },
+
+ 'tabSelectedHandler': function(anEvent) {
+ if (this.needsRenderingUponTabSwitch()) {
+ this.render();
+ }
+
+ if (anEvent.parameters() == this.getId('httpAuth')) {
+ var textarea;
+
+ textarea = document.getElementById("httpAuthDefaultConfiguration");
+ textarea.focus();
+ textarea.select();
+ }
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'tabPanelController': function() {
+ if (this._tabPanelController == null) {
+ var tabPanelControllerConfig;
+
+ tabPanelControllerConfig = {}
+ tabPanelControllerConfig[this.getId('passwordGenerator')] = this.getId('passwordGeneratorPanel');
+ tabPanelControllerConfig[this.getId('bookmarklet')] = this.getId('bookmarkletPanel');
+ tabPanelControllerConfig[this.getId('compact')] = this.getId('compactPanel');
+ tabPanelControllerConfig[this.getId('httpAuth')] = this.getId('httpAuthPanel');
+ this._tabPanelController = new Clipperz.PM.Components.TabPanel.TabPanelController({ config:tabPanelControllerConfig, selectedTab:this.getId('passwordGenerator') });
+ }
+
+ return this._tabPanelController;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'generateButtonElement': function() {
+ return this._generateButtonElement;
+ },
+
+ 'setGenerateButtonElement': function(aValue) {
+ this._generateButtonElement = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'updatePasswordValue': function(anEvent) {
+ var randomBytes;
+ var randomValue;
+ var charset;
+ var charsetBitSize;
+ var stringValue;
+ var blockIndex;
+
+//MochiKit.Logging.logDebug(">>> updatePasswordValue");
+ randomBytes = Clipperz.Crypto.PRNG.defaultRandomGenerator().getRandomBytes(50);
+ stringValue = "";
+ blockIndex = 0;
+
+ charset = "";
+ if (this.getDom('lowercase').checked) {
+ charset += Clipperz.PM.Strings['passwordGeneratorLowercaseCharset'];
+ }
+ if (this.getDom('uppercase').checked) {
+ charset += Clipperz.PM.Strings['passwordGeneratorUppercaseCharset'];
+ }
+ if (this.getDom('numbers').checked) {
+ charset += Clipperz.PM.Strings['passwordGeneratorNumberCharset'];
+ }
+ if (this.getDom('symbols').checked) {
+ charset += Clipperz.PM.Strings['passwordGeneratorSymbolCharset'];
+ }
+
+ charsetBitSize = 0;
+ while (Math.pow(2, charsetBitSize) < charset.length) {
+ charsetBitSize ++;
+ }
+
+ if (charsetBitSize > 0) {
+ while (Clipperz.PM.Crypto.passwordEntropy(stringValue) < 128) {
+ if (((blockIndex + 1)*charsetBitSize) > (randomBytes.length() * 8)) {
+ randomBytes = Clipperz.Crypto.PRNG.defaultRandomGenerator().getRandomBytes(50);
+ blockIndex = 0;
+ }
+ randomValue = randomBytes.bitBlockAtIndexWithSize(blockIndex*charsetBitSize, charsetBitSize);
+ if (randomValue < charset.length) {
+ stringValue += charset.charAt(randomValue);
+ }
+
+ blockIndex ++;
+ }
+ } else {
+ stringValue = "";
+ }
+
+ this.getElement('passwordField').dom.focus()
+ this.getElement('passwordField').dom.value = stringValue;
+
+
+ if (anEvent.src) {
+ anEvent.src().focus();
+ } else {
+ this.generateButtonElement().el.focus();
+ }
+
+ this.setNeedsRenderingUponTabSwitch(true);
+
+ return false;
+//MochiKit.Logging.logDebug("<<< updatePasswordValue");
+ },
+
+ //-----------------------------------------------------
+
+ 'updatePasswordLengthLabel': function() {
+ this.getElement('passwordLength').update(this.getDom('passwordField').value.length);
+ },
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+
+});
+
diff --git a/frontend/beta/js/Clipperz/PM/Components/PasswordEntropyDisplay.js b/frontend/beta/js/Clipperz/PM/Components/PasswordEntropyDisplay.js
new file mode 100644
index 0000000..530d2cb
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Components/PasswordEntropyDisplay.js
@@ -0,0 +1,118 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
+if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
+if (typeof(Clipperz.PM.Components) == 'undefined') { Clipperz.PM.Components = {}; }
+
+Clipperz.PM.Components.PasswordEntropyDisplay = function(anElement, args) {
+ args = args || {};
+
+//MochiKit.Logging.logDebug(">>> new TextFormField");
+ Clipperz.PM.Components.PasswordEntropyDisplay.superclass.constructor.call(this, anElement, args);
+
+ this._wrapperElement = null;
+ this._entropyElement = null;
+
+ this.render();
+//MochiKit.Logging.logDebug("<<< new TextFormField");
+
+ return this;
+};
+
+YAHOO.extendX(Clipperz.PM.Components.PasswordEntropyDisplay, Clipperz.PM.Components.BaseComponent, {
+
+ 'toString': function() {
+ return "Clipperz.PM.Components.PasswordEntropyDisplay";
+ },
+
+ //-----------------------------------------------------
+
+ 'wrapperElement': function() {
+ return this._wrapperElement;
+ },
+
+ 'setWrapperElement': function(aValue) {
+ this._wrapperElement = aValue;
+ },
+
+ //-----------------------------------------------------
+
+ 'passwordElement': function() {
+ return this.element();
+ },
+
+ //-----------------------------------------------------
+
+ 'entropyElement': function() {
+ return this._entropyElement;
+ },
+
+ 'setEntropyElement': function(aValue) {
+ this._entropyElement = aValue;
+ },
+
+ //-----------------------------------------------------
+
+ 'render': function() {
+ MochiKit.Signal.disconnectAllTo(this);
+
+ this.setWrapperElement(this.element().wrap({tag:'div'}));
+ this.setEntropyElement(Clipperz.YUI.DomHelper.append(this.wrapperElement().dom, {tag:'div', cls:'passwordEntropy', html:"&nbsp;"}, true));
+
+// this.entropyElement().setWidth(this.passwordElement().getWidth());
+ this.updateEntropyElement();
+
+ MochiKit.Signal.connect(this.element().dom, 'onkeyup', this, 'updateEntropyElement');
+ MochiKit.Signal.connect(this.element().dom, 'onchange', this, 'updateEntropyElement');
+ MochiKit.Signal.connect(this.element().dom, 'onblur', this, 'updateEntropyElement');
+ },
+
+ //-----------------------------------------------------
+
+ 'computeEntropyForString': function(aValue) {
+ return Clipperz.PM.Crypto.passwordEntropy(aValue);
+ },
+
+ //-----------------------------------------------------
+
+ 'updateEntropyElement': function(anEvent) {
+//MochiKit.Logging.logDebug(">>> PasswordEntropyDisplay.updateEntropyElement");
+ var maxExtent;
+ var entropy;
+
+ entropy = Math.min(128, this.computeEntropyForString(this.passwordElement().dom.value));
+//MochiKit.Logging.logDebug("--- PasswordEntropyDisplay.updateEntropyElement - entropy: " + entropy);
+ this.entropyElement().setStyle('background-position', "0px " + -entropy + "px");
+ this.entropyElement().setWidth(this.passwordElement().getWidth() * (entropy/128));
+//MochiKit.Logging.logDebug("<<< PasswordEntropyDisplay.updateEntropyElement");
+ },
+
+ //-----------------------------------------------------
+ __syntaxFix__: '__syntaxFix__'
+});
diff --git a/frontend/beta/js/Clipperz/PM/Components/PasswordGenerator.js b/frontend/beta/js/Clipperz/PM/Components/PasswordGenerator.js
new file mode 100644
index 0000000..8195f2e
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Components/PasswordGenerator.js
@@ -0,0 +1,285 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
+if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
+if (typeof(Clipperz.PM.Components) == 'undefined') { Clipperz.PM.Components = {}; }
+
+Clipperz.PM.Components.PasswordGenerator = function(anElement, aFieldValueComponent, args) {
+ args = args || {};
+
+//MochiKit.Logging.logDebug(">>> new TextFormField");
+ Clipperz.PM.Components.PasswordGenerator.superclass.constructor.call(this, anElement, args);
+
+ this._fieldValueComponent = aFieldValueComponent;
+ this._panelButton = null;
+ this.render();
+//MochiKit.Logging.logDebug("<<< new TextFormField");
+
+ return this;
+};
+
+YAHOO.extendX(Clipperz.PM.Components.PasswordGenerator, Clipperz.PM.Components.BaseComponent, {
+
+ 'toString': function() {
+ return "Clipperz.PM.Components.PasswordGenerator";
+ },
+
+ //-----------------------------------------------------
+
+ 'fieldValueComponent': function() {
+ return this._fieldValueComponent;
+ },
+
+ //-----------------------------------------------------
+
+ 'render': function() {
+ MochiKit.Signal.disconnectAllTo(this);
+
+// this._panelButton = new YAHOO.ext.Button(this.element().dom, {text:Clipperz.PM.Strings['passwordGeneratorButtonLabel'], handler:this.openPasswordPanel, scope:this});
+ MochiKit.Signal.connect(this.element().dom, 'onmouseenter', this, 'onMouseEnter');
+ MochiKit.Signal.connect(this.element().dom, 'onmouseleave', this, 'onMouseLeave');
+ MochiKit.Signal.connect(this.element().dom, 'onclick', this, 'openPasswordPanel');
+ },
+
+ //-----------------------------------------------------
+
+ 'onMouseEnter': function() {
+ this.element().addClass('hover');
+ },
+
+ 'onMouseLeave': function() {
+ this.element().removeClass('hover');
+ },
+
+ //-----------------------------------------------------
+
+ 'panelButton': function() {
+ return this._panelButton;
+ },
+
+ //-----------------------------------------------------
+
+ 'openPasswordPanel': function() {
+ var passwordGeneratorElement;
+ var passwordGeneratorDialog;
+ var cancelButton;
+ var okButton;
+ var cancelFunction;
+ var okFunction;
+
+//MochiKit.Logging.logDebug(">>> PasswordGenerator.openPasswordPanel");
+ passwordGeneratorElement = Clipperz.YUI.DomHelper.append(document.body, {tag:'div', id:'passwordGenerator', children:[
+ {tag:'div', cls:'ydlg-hd', htmlString:Clipperz.PM.Strings['passwordGeneratorPanelTitle']},
+ {tag:'div', cls:'ydlg-bd', children:[
+ {tag:'form', id:this.getId('passwordGeneratorForm'), cls:'passwordGenerator', children:[
+ {tag:'input', type:'text', cls:'clipperz_passwordGenerator_password', id:this.getId('passwordField')},
+ {tag:'table', children:[
+ {tag:'tbody', children:[
+ {tag:'tr', children:[
+ {tag:'td', width:'20%', children:[
+ {tag:'input', type:'checkbox', name:'lowercase', id:this.getId('lowercase'), checked:true},
+ {tag:'span', htmlString:Clipperz.PM.Strings['passwordGeneratorLowercaseLabel']}
+ ]},
+ {tag:'td', width:'20%', children:[
+ {tag:'input', type:'checkbox', name:'uppercase', id:this.getId('uppercase'), checked:true},
+ {tag:'span', htmlString:Clipperz.PM.Strings['passwordGeneratorUppercaseLabel']}
+ ]},
+ {tag:'td', width:'20%', children:[
+ {tag:'input', type:'checkbox', name:'numbers', id:this.getId('numbers'), checked:true},
+ {tag:'span', htmlString:Clipperz.PM.Strings['passwordGeneratorNumberLabel']}
+ ]},
+ {tag:'td', width:'20%', children:[
+ {tag:'input', type:'checkbox', name:'symbols', id:this.getId('symbols'), checked:true},
+ {tag:'span', htmlString:Clipperz.PM.Strings['passwordGeneratorSymbolLabel']}
+ ]},
+ {tag:'td', width:'20%', children:[
+ {tag:'span', cls:'passwordGeneratorLength', children:[
+ {tag:'span', htmlString:Clipperz.PM.Strings['passwordGeneratorLengthLabel']},
+ {tag:'span', id:this.getId('passwordLength'), cls:'passwordGeneratorLengthValue', html:'0'}
+ ]}
+ ]}
+ ]}
+ ]}
+ ]}
+ ]}
+ ]},
+ {tag:'div', cls:'ydlg-ft'}
+ ]}, true);
+
+ new Clipperz.PM.Components.PasswordEntropyDisplay(this.getElement('passwordField'));
+
+ MochiKit.Signal.connect(this.getId('lowercase'), 'onclick', this, 'updatePasswordValue');
+ MochiKit.Signal.connect(this.getId('uppercase'), 'onclick', this, 'updatePasswordValue');
+ MochiKit.Signal.connect(this.getId('numbers'), 'onclick', this, 'updatePasswordValue');
+ MochiKit.Signal.connect(this.getId('symbols'), 'onclick', this, 'updatePasswordValue');
+
+ MochiKit.Signal.connect(this.getDom('passwordField'), 'onkeyup', this, 'updatePasswordLengthLabel');
+ MochiKit.Signal.connect(this.getDom('passwordField'), 'onchange', this, 'updatePasswordLengthLabel');
+ MochiKit.Signal.connect(this.getDom('passwordField'), 'onblur', this, 'updatePasswordLengthLabel');
+
+ this.updatePasswordValue();
+
+ passwordGeneratorDialog = new YAHOO.ext.BasicDialog(
+ passwordGeneratorElement, {
+ autoCreate:false,
+ closable:false,
+ modal:true,
+ autoTabs:false,
+ resizable:false,
+ fixedcenter:true,
+ constraintoviewport:false,
+ width:320,
+ height:130,
+ shadow:true,
+ minWidth:200,
+ minHeight:100
+ }
+ );
+
+ cancelFunction = MochiKit.Base.partial(MochiKit.Base.bind(this.cancelPasswordPanel, this), passwordGeneratorDialog);
+ passwordGeneratorDialog.addKeyListener(27, cancelFunction);
+ cancelButton = passwordGeneratorDialog.addButton(Clipperz.PM.Strings['passwordGeneratorPanelCancelLabel'], cancelFunction, this);
+
+ okFunction = MochiKit.Base.partial(MochiKit.Base.bind(this.okPasswordPanel, this), passwordGeneratorDialog);
+ passwordGeneratorDialog.addKeyListener([10, 13], okFunction);
+ okButton = passwordGeneratorDialog.addButton(Clipperz.PM.Strings['passwordGeneratorPanelOkLabel'], okFunction, this);
+
+ MochiKit.Signal.connect(this.getId('passwordGeneratorForm'), 'onsubmit', okFunction);
+
+ passwordGeneratorDialog.setDefaultButton(okButton);
+
+ this.fieldValueComponent().mainComponent().mainPanel().exitModalView();
+ this.fieldValueComponent().mainComponent().scrollToTop();
+
+// passwordGeneratorDialog.show(this.panelButton().getEl());
+ passwordGeneratorDialog.show(this.element());
+ this.onMouseLeave();
+ },
+
+ //-----------------------------------------------------
+
+ 'cancelPasswordPanel': function(aPasswordGeneratorPanel) {
+ this.fieldValueComponent().mainComponent().mainPanel().enterModalView();
+ aPasswordGeneratorPanel.hide(MochiKit.Base.bind(function() {
+ aPasswordGeneratorPanel.destroy(true);
+ MochiKit.Signal.disconnectAllTo(this);
+ }, this));
+ },
+
+ //-----------------------------------------------------
+
+ 'updatePasswordLengthLabel': function() {
+ this.getElement('passwordLength').update(this.getDom('passwordField').value.length);
+ },
+
+ //-----------------------------------------------------
+
+ 'okPasswordPanel': function(aPasswordGeneratorPanel, anEvent) {
+//MochiKit.Logging.logDebug(">>> PasswordGenerator.okPasswordPanel");
+
+ if (anEvent.stop) {
+ anEvent.stop();
+ }
+
+ this.fieldValueComponent().inputElement().dom.focus();
+ this.fieldValueComponent().inputElement().dom.value = this.getElement('passwordField').dom.value;
+ this.getElement('passwordField').dom.focus();
+ this.cancelPasswordPanel(aPasswordGeneratorPanel);
+
+ return false;
+ },
+
+ //-----------------------------------------------------
+
+ 'updatePasswordValue': function(anEvent) {
+ var randomBytes;
+ var randomValue;
+ var charset;
+ var charsetBitSize;
+ var stringValue;
+ var blockIndex;
+
+//MochiKit.Logging.logDebug(">>> updatePasswordValue");
+ randomBytes = Clipperz.Crypto.PRNG.defaultRandomGenerator().getRandomBytes(50);
+ stringValue = "";
+ blockIndex = 0;
+
+ charset = "";
+ if (this.getDom('lowercase').checked) {
+ charset += Clipperz.PM.Strings['passwordGeneratorLowercaseCharset'];
+ }
+ if (this.getDom('uppercase').checked) {
+ charset += Clipperz.PM.Strings['passwordGeneratorUppercaseCharset'];
+ }
+ if (this.getDom('numbers').checked) {
+ charset += Clipperz.PM.Strings['passwordGeneratorNumberCharset'];
+ }
+ if (this.getDom('symbols').checked) {
+ charset += Clipperz.PM.Strings['passwordGeneratorSymbolCharset'];
+ }
+
+ charsetBitSize = 0;
+ while (Math.pow(2, charsetBitSize) < charset.length) {
+ charsetBitSize ++;
+ }
+
+ if (charsetBitSize > 0) {
+ while (Clipperz.PM.Crypto.passwordEntropy(stringValue) < 128) {
+ if (((blockIndex + 1)*charsetBitSize) > (randomBytes.length() * 8)) {
+ randomBytes = Clipperz.Crypto.PRNG.defaultRandomGenerator().getRandomBytes(50);
+ blockIndex = 0;
+ }
+ randomValue = randomBytes.bitBlockAtIndexWithSize(blockIndex*charsetBitSize, charsetBitSize);
+ if (randomValue < charset.length) {
+ stringValue += charset.charAt(randomValue);
+ }
+
+ blockIndex ++;
+ }
+ } else {
+ stringValue = "";
+ }
+
+ this.getElement('passwordField').dom.focus()
+ this.getElement('passwordField').dom.value = stringValue;
+
+
+ if (anEvent) {
+ anEvent.src().focus();
+ } else {
+ this.element().focus();
+ }
+
+ return false;
+//MochiKit.Logging.logDebug("<<< updatePasswordValue");
+ },
+
+ //-----------------------------------------------------
+ __syntaxFix__: '__syntaxFix__'
+});
diff --git a/frontend/beta/js/Clipperz/PM/Components/Printing/Footer.js b/frontend/beta/js/Clipperz/PM/Components/Printing/Footer.js
new file mode 100644
index 0000000..6bede3e
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Components/Printing/Footer.js
@@ -0,0 +1,28 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
diff --git a/frontend/beta/js/Clipperz/PM/Components/Printing/Header.js b/frontend/beta/js/Clipperz/PM/Components/Printing/Header.js
new file mode 100644
index 0000000..6bede3e
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Components/Printing/Header.js
@@ -0,0 +1,28 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
diff --git a/frontend/beta/js/Clipperz/PM/Components/Printing/Record.js b/frontend/beta/js/Clipperz/PM/Components/Printing/Record.js
new file mode 100644
index 0000000..910d4b1
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Components/Printing/Record.js
@@ -0,0 +1,95 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
+if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
+if (typeof(Clipperz.PM.Components) == 'undefined') { Clipperz.PM.Components = {}; }
+if (typeof(Clipperz.PM.Components.Printing) == 'undefined') { Clipperz.PM.Components.Printing = {}; }
+
+Clipperz.PM.Components.Printing.Record = function(args) {
+ args = args || {};
+
+ this._record = args['record'];
+
+ return this;
+}
+
+MochiKit.Base.update(Clipperz.PM.Components.Printing.Record.prototype, {
+
+ 'record': function() {
+ return this._record;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'deferredDrawToWindow': function(aWindow) {
+ var deferredResult;
+
+ deferredResult = new MochiKit.Async.Deferred();
+ deferredResult.addCallback(MochiKit.Base.method(this.record(), 'deferredData'));
+ deferredResult.addCallback(MochiKit.Base.method(this, 'appendToWindow', aWindow));
+ deferredResult.callback();
+ return deferredResult;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'appendToWindow': function(aWindow) {
+ MochiKit.DOM.withWindow(aWindow, MochiKit.Base.bind(function() {
+ var newBlock;
+ var fields;
+
+ fields = MochiKit.Base.concat(
+ MochiKit.Base.map(MochiKit.Base.bind(function(aField) {
+ var result;
+ var dt, dd;
+ var label, value;
+
+ label = aField.label();
+ value = aField.value();
+ dt = MochiKit.DOM.createDOM('DT', null, label);
+ dd = MochiKit.DOM.createDOM('DD', null, value)
+ result = [dt, dd];
+
+ return result
+ }, this), MochiKit.Base.values(this.record().currentVersion().fields()))
+ );
+
+ newBlock = MochiKit.DOM.DIV({'class': 'recordBlock'},
+ MochiKit.DOM.H2(null, this.record().label()),
+ MochiKit.DOM.DIV({'class': 'recordNotes'}, MochiKit.Base.map(MochiKit.Base.partial(MochiKit.DOM.P, null), this.record().notes().split("\n"))),
+ MochiKit.DOM.createDOM('DL', null, fields)
+ );
+ MochiKit.DOM.appendChildNodes(MochiKit.DOM.currentDocument().body, newBlock);
+
+ }, this));
+ },
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+});
diff --git a/frontend/beta/js/Clipperz/PM/Components/RecordDetail/AbstractComponent.js b/frontend/beta/js/Clipperz/PM/Components/RecordDetail/AbstractComponent.js
new file mode 100644
index 0000000..840d555
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Components/RecordDetail/AbstractComponent.js
@@ -0,0 +1,105 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
+if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
+if (typeof(Clipperz.PM.Components) == 'undefined') { Clipperz.PM.Components = {}; }
+if (typeof(Clipperz.PM.Components.RecordDetail) == 'undefined') { Clipperz.PM.Components.RecordDetail = {}; }
+
+//#############################################################################
+
+Clipperz.PM.Components.RecordDetail.AbstractComponent = function(anElement, args) {
+ args = args || {};
+
+ Clipperz.PM.Components.RecordDetail.AbstractComponent.superclass.constructor.call(this, args);
+
+ this._element = anElement;
+ this._mainComponent = args.mainComponent;
+
+ return this;
+}
+
+//=============================================================================
+
+YAHOO.extendX(Clipperz.PM.Components.RecordDetail.AbstractComponent, Clipperz.PM.Components.BaseComponent, {
+
+ 'toString': function() {
+ return "Clipperz.PM.Components.RecordDetail.AbstractComponent";
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'mainComponent': function() {
+ return this._mainComponent;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'record': function() {
+ return this.mainComponent().record();
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'editMode': function() {
+ return this.mainComponent().editMode();
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'render': function() {
+ this.element().update("");
+ this.update();
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'update': function(anEvent) {
+ if (this.editMode() == 'EDIT') {
+ this.updateEditMode();
+ } else if (this.editMode() == 'VIEW') {
+ this.updateViewMode();
+ }
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'updateViewMode': function() {},
+ 'updateEditMode': function() {},
+ 'synchronizeComponentValues': function() {},
+
+ //-------------------------------------------------------------------------
+
+ 'destroy': function() {
+ this.element().remove();
+ },
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+});
+
diff --git a/frontend/beta/js/Clipperz/PM/Components/RecordDetail/AbstractFieldSubComponent.js b/frontend/beta/js/Clipperz/PM/Components/RecordDetail/AbstractFieldSubComponent.js
new file mode 100644
index 0000000..7596184
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Components/RecordDetail/AbstractFieldSubComponent.js
@@ -0,0 +1,77 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
+if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
+if (typeof(Clipperz.PM.Components) == 'undefined') { Clipperz.PM.Components = {}; }
+if (typeof(Clipperz.PM.Components.RecordDetail) == 'undefined') { Clipperz.PM.Components.RecordDetail = {}; }
+
+//#############################################################################
+
+Clipperz.PM.Components.RecordDetail.AbstractFieldSubComponent = function(anElement, args) {
+ args = args || {};
+
+ Clipperz.PM.Components.RecordDetail.AbstractFieldSubComponent.superclass.constructor.call(this, anElement, args);
+
+ this._fieldComponent = args.fieldComponent || null;
+
+ this.render();
+
+ return this;
+}
+
+//=============================================================================
+
+YAHOO.extendX(Clipperz.PM.Components.RecordDetail.AbstractFieldSubComponent, Clipperz.PM.Components.RecordDetail.AbstractComponent, {
+
+ 'toString': function() {
+ return "Clipperz.PM.Components.RecordDetail.AbstractFieldSubComponent";
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'fieldComponent': function() {
+ return this._fieldComponent;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'mainComponent': function() {
+ return this.fieldComponent().mainComponent();
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'recordField': function() {
+ return this.fieldComponent().recordField();
+ },
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+});
+
diff --git a/frontend/beta/js/Clipperz/PM/Components/RecordDetail/CreationWizard.js b/frontend/beta/js/Clipperz/PM/Components/RecordDetail/CreationWizard.js
new file mode 100644
index 0000000..a92285f
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Components/RecordDetail/CreationWizard.js
@@ -0,0 +1,317 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
+if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
+if (typeof(Clipperz.PM.Components) == 'undefined') { Clipperz.PM.Components = {}; }
+if (typeof(Clipperz.PM.Components.RecordDetail) == 'undefined') { Clipperz.PM.Components.RecordDetail = {}; }
+
+//#############################################################################
+
+Clipperz.PM.Components.RecordDetail.CreationWizard = function(anElement, args) {
+ args = args || {};
+
+ Clipperz.PM.Components.RecordDetail.CreationWizard.superclass.constructor.call(this, anElement, args);
+
+ this._mainComponent = args.mainComponent;
+ this._previouslySelectedRecord = args.previouslySelectedRecord;
+//MochiKit.Logging.logDebug("--- new CreationWizard - previouslySelectedRecord: " + args.previouslySelectedRecord);
+ this._createButton_header = null;
+ this._createButton_footer = null;
+
+ this._cancelButton_header = null;
+ this._cancelButton_footer = null;
+
+ this.render();
+
+ return this;
+}
+
+//=============================================================================
+
+YAHOO.extendX(Clipperz.PM.Components.RecordDetail.CreationWizard, Clipperz.PM.Components.BaseComponent, {
+
+ 'toString': function() {
+ return "Clipperz.PM.Components.RecordDetail.CreationWizard component";
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'previouslySelectedRecord': function() {
+ return this._previouslySelectedRecord;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'render': function() {
+ var templateListElement;
+ var templates;
+
+ this.element().update("");
+
+ Clipperz.YUI.DomHelper.append(this.element().dom,
+ {tag:'form', cls:'recordDataFORM', id:this.getId('form'), children:[
+ {tag:'div', id:'recordDetailDataBox', cls:'recordDetailDataBox', children:[
+ {tag:'div', id:this.getId('wizardBox'), cls:'recordCreationWizard', children:[
+ {tag:'div', id:this.getId('recordCreationWizardTitleBox'), cls:'recordCreationWizardTitleBox', htmlString:Clipperz.PM.Strings['newRecordWizardTitleBox']},
+ {tag:'ul', id:this.getId('templateList'), cls:'radioList'}
+ ]}
+ ]}
+ ]}
+ );
+
+ Clipperz.YUI.DomHelper.append(this.getDom('recordCreationWizardTitleBox'), {tag:'div', cls:'newRecordWizardHeader', children:[
+ {tag:'table', width:'100%', cellpadding:'5', children:[
+ {tag:'tbody', children:[
+ {tag:'tr', children:[
+ {tag:'td', width:'49%', align:'right', children:[
+ {tag:'div', id:this.getId('cancelButton_header')}
+ ]},
+ {tag:'td', width:'10', html:'&nbsp;'},
+ {tag:'td', width:'49%', align:'left', children:[
+ {tag:'div', id:this.getId('createButton_header')}
+ ]}
+ ]}
+ ]}
+ ]}
+ ]});
+
+ templateListElement = this.getElement('templateList');
+ templates = Clipperz.PM.Strings['recordTemplates'];
+ MochiKit.Iter.forEach(MochiKit.Base.keys(templates), MochiKit.Base.bind(function(aTemplateKey) {
+ Clipperz.YUI.DomHelper.append(templateListElement.dom, {tag:'li', children:[
+ {tag:'table', children:[
+ {tag:'tbody', children:[
+ {tag:'tr', children:[
+ {tag:'td', valign:'top', children:[
+ {tag:'input', id:this.getId(aTemplateKey+"_radio"), type:'radio', name:'recordTemplate', value:"aTemplateKey"}
+ ]},
+ {tag:'td', valign:'top', children:[
+ {tag:'h4', id:this.getId(aTemplateKey+"_title"), html:templates[aTemplateKey]['title']},
+ {tag:'div', cls:'templateDescription', htmlString:templates[aTemplateKey]['description']}
+ ]}
+ ]}
+ ]}
+ ]}
+ ]});
+ this.getElement(aTemplateKey+"_radio").dom.value = aTemplateKey;
+ MochiKit.Signal.connect(this.getDom(aTemplateKey+"_title"), 'onclick', MochiKit.Base.partial(function(aRadioButton) {aRadioButton.click();}, this.getDom(aTemplateKey+"_radio")));
+ }, this));
+
+ Clipperz.YUI.DomHelper.append(templateListElement.dom, {tag:'li', children:[
+ {tag:'table', children:[
+ {tag:'tbody', children:[
+ {tag:'tr', children:[
+ {tag:'td', valign:'top', children:[
+ {tag:'input', type:'radio', name:'recordTemplate', id:this.getId('bookmarkletRadioButton'), value:'BookmarkletConfigurationTemplate'}
+ ]},
+ {tag:'td', valign:'top', children:[
+ {tag:'h4', htmlString:Clipperz.PM.Strings['newRecordWizardBookmarkletConfigurationTitle']},
+ {tag:'div', cls:'templateDescription', htmlString:Clipperz.PM.Strings['newRecordWizardBookmarkletConfigurationDescription']},
+ {tag:'div', cls:'bookmarkletConfiguration', children:[
+// {tag:'span', htmlString:Clipperz.PM.Strings['newRecordWizardBookmarkletConfigurationLabel']},
+ {tag:'div', htmlString:Clipperz.PM.Strings['recordDetailNewDirectLoginDescription']},
+ {tag:'textarea', id:this.getId('bookmarkletConfiguration')}
+ ]}
+ ]}
+ ]}
+ ]}
+ ]}
+ ]});
+
+ Clipperz.YUI.DomHelper.append(this.getDom('wizardBox'), {tag:'div', cls:'newRecordWizardFooter', children:[
+ {tag:'table', width:'100%', cellpadding:'5', children:[
+ {tag:'tbody', children:[
+ {tag:'tr', children:[
+ {tag:'td', width:'49%', align:'right', children:[
+ {tag:'div', id:this.getId('cancelButton_footer')}
+ ]},
+ {tag:'td', width:'10', html:'&nbsp;'},
+ {tag:'td', width:'49%', align:'left', children:[
+ {tag:'div', id:this.getId('createButton_footer')}
+ ]}
+ ]}
+ ]}
+ ]}
+ ]});
+
+ this.setCreateButton_header(new YAHOO.ext.Button(this.getDom('createButton_header'), {text:Clipperz.PM.Strings['newRecordWizardCreateButtonLabel'], handler:this.createRecord, scope:this}));
+ this.setCreateButton_footer(new YAHOO.ext.Button(this.getDom('createButton_footer'), {text:Clipperz.PM.Strings['newRecordWizardCreateButtonLabel'], handler:this.createRecord, scope:this}));
+
+ this.setCancelButton_header(new YAHOO.ext.Button(this.getDom('cancelButton_header'), {text:Clipperz.PM.Strings['newRecordWizardCancelButtonLabel'], handler:this.exitWizard, scope:this}));
+ this.setCancelButton_footer(new YAHOO.ext.Button(this.getDom('cancelButton_footer'), {text:Clipperz.PM.Strings['newRecordWizardCancelButtonLabel'], handler:this.exitWizard, scope:this}));
+
+ this.createButton_header().disable();
+ this.createButton_footer().disable();
+
+ MochiKit.Iter.forEach(this.getElement('form').getChildrenByTagName('input'), MochiKit.Base.bind(function(anInput) {
+// MochiKit.Signal.connect(anInput.dom, 'onchange', this, 'enableCreateButton');
+ MochiKit.Signal.connect(anInput.dom, 'onclick', this, 'enableCreateButton'); // for Safari
+ },this));
+
+ MochiKit.Signal.connect(this.getDom('bookmarkletConfiguration'), 'onkeyup', this, 'enableCreateButton');
+ MochiKit.Signal.connect(this.getDom('bookmarkletConfiguration'), 'onkeydown', this, 'enableCreateButton'); // for Safari
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'createButton_header': function() {
+ return this._createButton_header;
+ },
+
+ 'setCreateButton_header': function(aValue) {
+ this._createButton_header = aValue;
+ },
+
+ //.........................................................................
+
+ 'createButton_footer': function() {
+ return this._createButton_footer;
+ },
+
+ 'setCreateButton_footer': function(aValue) {
+ this._createButton_footer = aValue;
+ },
+
+
+ //-------------------------------------------------------------------------
+
+ 'cancelButton_header': function() {
+ return this._cancelButton_header;
+ },
+
+ 'setCancelButton_header': function(aValue) {
+ this._cancelButton_header = aValue;
+ },
+
+ //.........................................................................
+
+ 'cancelButton_footer': function() {
+ return this._cancelButton_footer;
+ },
+
+ 'setCancelButton_footer': function(aValue) {
+ this._cancelButton_footer = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'enableCreateButton': function(anEvent, skipKeyDownCheck) {
+//MochiKit.Logging.logDebug(">>> CreationWizard.enableCreateButton (" + anEvent.type() + ")");
+ if ((anEvent.type() == "keydown") && (skipKeyDownCheck != true)) {
+//MochiKit.Logging.logDebug("--- CreationWizard.enableCreateButton - handling 'keydown' event with a postponed execution of the check");
+ MochiKit.Async.callLater(0.3, MochiKit.Base.method(this, 'enableCreateButton', anEvent, true));
+ } else {
+ var shouldEnableCreateButton;
+ var isBookmarkletConfigurationEmpty;
+
+//MochiKit.Logging.logDebug("--- CreationWizard.enableCreateButton - common execution");
+
+ shouldEnableCreateButton = true;
+
+ isBookmarkletConfigurationEmpty = !/[^ \n]/.test(this.getDom('bookmarkletConfiguration').value);
+//MochiKit.Logging.logDebug("--- CreationWizard.enableCreateButton - isBookmarkletConfigurationEmpty: " + isBookmarkletConfigurationEmpty);
+
+ if ((anEvent.src() == this.getDom('bookmarkletConfiguration')) && !isBookmarkletConfigurationEmpty) {
+ this.getDom('bookmarkletRadioButton').checked = true;
+ }
+
+ if ((this.getDom('bookmarkletRadioButton').checked) && isBookmarkletConfigurationEmpty) {
+ shouldEnableCreateButton = false;
+ }
+
+ if (shouldEnableCreateButton) {
+//MochiKit.Logging.logDebug("--- CreationWizard.enableCreateButton - enabling button");
+ this.createButton_header().enable();
+ this.createButton_footer().enable();
+ } else {
+//MochiKit.Logging.logDebug("--- CreationWizard.enableCreateButton - disabling button");
+ this.createButton_header().disable();
+ this.createButton_footer().disable();
+ }
+ }
+//MochiKit.Logging.logDebug("<<< CreationWizard.enableCreateButton");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'createRecord': function() {
+ var selectedTemplateKey;
+ var newRecord;
+
+ selectedTemplateKey = MochiKit.Base.filter(function(aCheckBoxElement) {
+ return aCheckBoxElement.dom.checked;
+ },this.getElement('form').getChildrenByTagName('input'))[0].dom.value;
+
+//MochiKit.Logging.logDebug("--- CreationWizard.createRecord - selectedTemplateKey: " + selectedTemplateKey);
+ if (selectedTemplateKey == 'BookmarkletConfigurationTemplate') {
+ var bookmarkletConfiguration;
+
+ this.mainComponent().exitModalView();
+ bookmarkletConfiguration = Clipperz.PM.BookmarkletProcessor.checkBookmarkletConfiguration(this.getDom('bookmarkletConfiguration').value, this.getDom('createButton'), MochiKit.Base.method(this.mainComponent(), 'enterModalView'));
+ this.mainComponent().enterModalView();
+ newRecord = Clipperz.PM.BookmarkletProcessor.createRecordFromBookmarkletConfiguration(this.mainComponent().user(), bookmarkletConfiguration);
+ } else {
+ var fieldsConfigurations;
+
+ newRecord = this.mainComponent().user().addNewRecord();
+ newRecord.setLabel(Clipperz.PM.Strings['recordTemplates'][selectedTemplateKey]['title']);
+
+ fieldsConfigurations = Clipperz.PM.Strings['recordTemplates'][selectedTemplateKey]['fields'];
+
+ MochiKit.Iter.forEach(fieldsConfigurations, MochiKit.Base.partial(function(aRecord, aFieldConfiguration) {
+ var newField;
+
+ newField = new Clipperz.PM.DataModel.RecordField({recordVersion:aRecord.currentVersion()});
+ newField.setLabel(aFieldConfiguration['label']);
+ newField.setType(aFieldConfiguration['type']);
+ aRecord.currentVersion().addField(newField);
+ }, newRecord));
+ }
+
+ this.mainComponent().exitWizard(newRecord, true);
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'exitWizard': function() {
+//MochiKit.Logging.logDebug(">>> CreationWizard.exitWizard - " + this.previouslySelectedRecord());
+ this.mainComponent().exitWizard(this.previouslySelectedRecord());
+//MochiKit.Logging.logDebug("<<< CreationWizard.exitWizard");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'mainComponent': function() {
+ return this._mainComponent;
+ },
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+});
+
diff --git a/frontend/beta/js/Clipperz/PM/Components/RecordDetail/DirectLoginBindingComponent.js b/frontend/beta/js/Clipperz/PM/Components/RecordDetail/DirectLoginBindingComponent.js
new file mode 100644
index 0000000..6171a4e
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Components/RecordDetail/DirectLoginBindingComponent.js
@@ -0,0 +1,174 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
+if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
+if (typeof(Clipperz.PM.Components) == 'undefined') { Clipperz.PM.Components = {}; }
+if (typeof(Clipperz.PM.Components.RecordDetail) == 'undefined') { Clipperz.PM.Components.RecordDetail = {}; }
+
+//#############################################################################
+
+Clipperz.PM.Components.RecordDetail.DirectLoginBindingComponent = function(anElement, args) {
+//MochiKit.Logging.logDebug(">>> new DirectLoginBindingComponent");
+ args = args || {};
+
+ Clipperz.PM.Components.RecordDetail.DirectLoginBindingComponent.superclass.constructor.call(this, anElement, args);
+
+ this._directLoginBinding = args.directLoginBinding || null;
+ this.render();
+
+ Clipperz.NotificationCenter.register(this.record(), 'addNewRecordField', this, 'syncAndUpdateEditMode');
+ Clipperz.NotificationCenter.register(this.record(), 'removedField', this, 'syncAndUpdateEditMode');
+ Clipperz.NotificationCenter.register(this.record(), 'updatedFieldLabel', this, 'syncAndUpdateEditMode');
+//MochiKit.Logging.logDebug("<<< new DirectLoginBindingComponent");
+
+ return this;
+}
+
+//=============================================================================
+
+YAHOO.extendX(Clipperz.PM.Components.RecordDetail.DirectLoginBindingComponent, Clipperz.PM.Components.RecordDetail.AbstractComponent, {
+
+ 'toString': function() {
+ return "Clipperz.PM.Components.RecordDetail.DirectLoginBindingComponent component";
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'directLoginBinding': function() {
+ return this._directLoginBinding;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'render': function() {
+// Clipperz.YUI.DomHelper.append(this.element().dom, {tag:'span', style:'font-weight:bold;', html:this.directLoginBinding().key()})
+// Clipperz.YUI.DomHelper.append(this.element().dom, {tag:'span', html:this.directLoginBinding().value()})
+//MochiKit.Logging.logDebug(">>> DirectLoginBindingComponent.render");
+ Clipperz.YUI.DomHelper.append(this.element().dom, {tag:'td', cls:'directLoginBindingLabelTD', children:[
+ {tag:'span', html:this.directLoginBinding().key()}
+ ]});
+//MochiKit.Logging.logDebug("--- DirectLoginBindingComponent.render - 1");
+ Clipperz.YUI.DomHelper.append(this.element().dom, {tag:'td', cls:'directLoginBindingValueTD', children:[
+ {tag:'div', id:this.getId('editModeBox'), children:[
+ {tag:'select', id:this.getId('select'), children:this.recordFieldOptions()}
+ ]},
+ {tag:'div', id:this.getId('viewModeBox'), children:[
+ {tag:'span', id:this.getId('viewValue'), html:""}
+ ]}
+ ]});
+//MochiKit.Logging.logDebug("--- DirectLoginBindingComponent.render - 2");
+ this.getElement('editModeBox').setVisibilityMode(YAHOO.ext.Element.DISPLAY);
+ this.getElement('viewModeBox').setVisibilityMode(YAHOO.ext.Element.DISPLAY);
+
+ this.update();
+//MochiKit.Logging.logDebug("<<< DirectLoginBindingComponent.render");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'recordFieldOptions': function() {
+ var result;
+ var option;
+ var recordFieldKey;
+ var recordFields;
+
+//MochiKit.Logging.logDebug(">>> DirectLoginBindingComponent.recordFieldOptions");
+ recordFields = this.directLoginBinding().directLogin().record().currentVersion().fields();
+ result = [];
+ option = {tag:'option', value:null, html:'---'};
+ result.push(option);
+ for (recordFieldKey in recordFields) {
+// TODO: remove the value: field and replace it with element.dom.value = <some value>
+ option = {tag:'option', value:recordFieldKey, html:recordFields[recordFieldKey].label()}
+ if (recordFieldKey == this.directLoginBinding().fieldKey()) {
+ option['selected'] = true;
+ }
+ result.push(option);
+ }
+//MochiKit.Logging.logDebug("<<< DirectLoginBindingComponent.recordFieldOptions");
+
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'syncAndUpdateEditMode': function() {
+ this.synchronizeComponentValues();
+ this.updateEditMode();
+ },
+
+ 'updateEditMode': function() {
+ var selectElementBox;
+
+//MochiKit.Logging.logDebug(">>> DirectLoginBindingComponent.updateEditMode");
+ this.getElement('viewModeBox').hide();
+
+ selectElementBox = this.getElement('editModeBox');
+ selectElementBox.update("");
+
+ Clipperz.YUI.DomHelper.append(selectElementBox.dom, {tag:'select', id:this.getId('select'), children:this.recordFieldOptions()});
+
+/*
+ selectElement = this.getElement('select');
+
+ selectElement.update("");
+ MochiKit.Iter.forEach(this.recordFieldOptions(), function(anOption) {
+ Clipperz.YUI.DomHelper.append(selectElement.dom, anOption);
+ });
+*/
+
+
+ this.getElement('editModeBox').show();
+//MochiKit.Logging.logDebug("<<< DirectLoginBindingComponent.updateEditMode");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'updateViewMode': function() {
+//MochiKit.Logging.logDebug(">>> DirectLoginBindingComponent.updateViewMode");
+ this.getElement('editModeBox').hide();
+ this.getElement('viewModeBox').show();
+
+ this.getElement('viewValue').update(this.directLoginBinding().field().label());
+//MochiKit.Logging.logDebug("<<< DirectLoginBindingComponent.updateViewMode");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'synchronizeComponentValues': function() {
+//MochiKit.Logging.logDebug(">>> DirectLoginBindingComponent.synchronizeComponentValues")
+//MochiKit.Logging.logDebug("--- DirectLoginBindingComponent.synchronizeComponentValues - 1 - " + this.getId('select'));
+ this.directLoginBinding().setFieldKey(this.getDom('select').value);
+//MochiKit.Logging.logDebug("<<< DirectLoginBindingComponent.synchronizeComponentValues");
+ },
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+});
+
diff --git a/frontend/beta/js/Clipperz/PM/Components/RecordDetail/DirectLoginComponent.js b/frontend/beta/js/Clipperz/PM/Components/RecordDetail/DirectLoginComponent.js
new file mode 100644
index 0000000..7638f00
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Components/RecordDetail/DirectLoginComponent.js
@@ -0,0 +1,362 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
+if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
+if (typeof(Clipperz.PM.Components) == 'undefined') { Clipperz.PM.Components = {}; }
+if (typeof(Clipperz.PM.Components.RecordDetail) == 'undefined') { Clipperz.PM.Components.RecordDetail = {}; }
+
+//#############################################################################
+
+Clipperz.PM.Components.RecordDetail.DirectLoginComponent = function(anElement, args) {
+ args = args || {};
+
+ Clipperz.PM.Components.RecordDetail.DirectLoginComponent.superclass.constructor.call(this, anElement, args);
+
+ this._directLogin = args.directLogin || null;
+// this._titleElement = null;
+ this._structureElement = null;
+ this._removeButton = null;
+ this._directLoginBindingComponents = null;
+ this._collapser = null;
+
+ this.mainComponent().addEditComponent(this);
+ this.render();
+
+ return this;
+}
+
+//=============================================================================
+
+YAHOO.extendX(Clipperz.PM.Components.RecordDetail.DirectLoginComponent, Clipperz.PM.Components.RecordDetail.AbstractComponent, {
+
+ 'toString': function() {
+ return "Clipperz.PM.Components.RecordDetail.DirectLoginComponent component";
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'directLogin': function() {
+ return this._directLogin;
+ },
+
+ 'directLoginBindingComponents': function() {
+ return this._directLoginBindingComponents;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'removeDirectLogin': function() {
+//MochiKit.Logging.logDebug(">>> DirectLoginComponent.removeDirectLogin");
+ this.mainComponent().synchronizeComponentValues();
+ this.directLogin().remove();
+ this.mainComponent().removeEditComponent(this);
+ this.mainComponent().render();
+//MochiKit.Logging.logDebug("<<< DirectLoginComponent.removeDirectLogin");
+ },
+
+ //-------------------------------------------------------------------------
+/*
+ 'formDataValue': function() {
+ return Clipperz.Base.serializeJSON(this.directLogin().formData());
+ },
+
+ 'setFormDataValue': function(aValue) {
+
+ },
+*/
+ //-------------------------------------------------------------------------
+
+ 'removeButton': function() {
+ return this._removeButton;
+ },
+
+ 'setRemoveButton': function(aValue) {
+ this._removeButton = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+/*
+ 'titleElement': function() {
+ return this._titleElement;
+ },
+
+ 'setTitleElement': function(aValue) {
+ this._titleElement = aValue;
+ },
+*/
+ //-------------------------------------------------------------------------
+
+ 'structureElement': function() {
+ return this._structureElement;
+ },
+
+ 'setStructureElement': function(aValue) {
+ this._structureElement = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'render': function() {
+//MochiKit.Logging.logDebug(">>> DirectLoginComponent.render");
+ try {
+ this.element().update("");
+ Clipperz.YUI.DomHelper.append(this.element().dom,
+ {tag:'li', children:[
+ {tag:'table', width:'100%', border:'0', cellpadding:'0', cellspacing:'0', children:[
+ {tag:'tbody', children:[
+ {tag:'tr', children:[
+ {tag:'td', rowspan:'2', width:'30', valign:'top', html:'&#160', children:[
+ {tag:'div', id:this.getId('removeDirectLogin'), children:[
+ {tag:'div', id:this.getId('removeDirectLoginButton')}
+ ]},
+ {tag:'div', id:this.getId('collapseLink'), cls:'directLoginCollapseLink'}
+ ]},
+ {tag:'td', valign:'top', children:[
+ {tag:'table', width:'100%', border:'0', cellpadding:'0', cellspacing:'0', children:[
+ {tag:'tbody', children:[
+ {tag:'tr', children:[
+ {tag:'td', width:'20', valign:'top', children:[
+ {tag:'a', href:'#', id:this.getId('directLogin'), children:[
+ {tag:'img', id:this.getId('faviconImage'), width:'16', height:'16', src:this.directLogin().fixedFavicon()}
+ ]}
+ ]},
+ {tag:'td', valign:'top', children:[
+ {tag:'div', cls:'directLoginDetailTitle', children:[
+ {tag:'div', id:this.getId('titleViewBox'), children:[
+ {tag:'a', href:'#', id:this.getId('titleLink')}
+ ]},
+ {tag:'div', id:this.getId('titleEditBox'), children:[
+ {tag:'input', type:'text', id:this.getId('titleInput')}
+ ]}
+ ]}
+ ]}
+ ]}
+ ]}
+ ]}
+ ]}
+ ]},
+ {tag:'tr', children:[
+ {tag:'td', /*colspan:'2',*/ children:[
+ {tag:'div', id:this.getId('details'), children:[
+ {tag:'table', cls:'directLoginBindings', border:'0', cellpadding:'0', cellspacing:'0', children:[
+ {tag:'tbody', id:this.getId('tbodyBindings'), children:[]}
+ ]}
+ ]}
+ ]}
+ ]}
+ ]}
+ ]}
+ ]}
+ );
+
+ MochiKit.Signal.connect(this.getId('faviconImage'), 'onload', this, 'handleLoadedFaviconImage');
+ MochiKit.Signal.connect(this.getId('faviconImage'), 'onerror', this.directLogin(), 'handleMissingFaviconImage');
+ MochiKit.Signal.connect(this.getId('faviconImage'), 'onabort', this.directLogin(), 'handleMissingFaviconImage');
+
+ this.getElement('removeDirectLogin').setVisibilityMode(YAHOO.ext.Element.DISPLAY);
+//MochiKit.Logging.logDebug("--- DirectLoginComponent.render - 1");
+ this.getElement('collapseLink').addClassOnOver('hover');
+ this._collapser = new Clipperz.YUI.Collapser(this.getElement('collapseLink'), this.getElement('details'), true);
+//MochiKit.Logging.logDebug("--- DirectLoginComponent.render - 2");
+ MochiKit.Signal.connect(this.getId('directLogin'), 'onclick', this, 'runDirectLogin');
+// this.getElement('directLogin').on('click', this.runDirectLogin, this, false);
+//MochiKit.Logging.logDebug("--- DirectLoginComponent.render - 3");
+// this.setTitleElement(new Clipperz.PM.Components.TextFormField(this.getElement('title'), {
+// editMode:this.editMode(),
+// value:this.directLogin().label()
+// }));
+ this.getElement('titleViewBox').setVisibilityMode(YAHOO.ext.Element.DISPLAY);
+ this.getElement('titleEditBox').setVisibilityMode(YAHOO.ext.Element.DISPLAY);
+//- this.getElement('titleLink').on('click', this.runDirectLogin, this, false);
+ MochiKit.Signal.connect(this.getId('titleLink'), 'onclick', this, 'runDirectLogin');
+
+//MochiKit.Logging.logDebug("--- DirectLoginComponent.render - 4");
+//- this.setStructureElement(new Clipperz.PM.Components.TextFormField(this.getElement('formStructure'), {
+//- editMode:this.editMode(),
+//- value:this.formDataValue(), multiline:true
+//- }));
+//MochiKit.Logging.logDebug("--- DirectLoginComponent.render - 5");
+ {
+ var bindingKey;
+ var valueName;
+ var inputsRequiringAdditionalValues;
+ var bindingsElement;
+ var i,c;
+
+//MochiKit.Logging.logDebug("--- DirectLoginComponent.render - 6");
+ this._directLoginBindingComponents = [];
+//MochiKit.Logging.logDebug("--- DirectLoginComponent.render - 7");
+ bindingsElement = this.getElement('tbodyBindings');
+//MochiKit.Logging.logDebug("--- DirectLoginComponent.render - 8");
+ for (bindingKey in this.directLogin().bindings()) {
+ try {
+ var directLoginBindingElement;
+ var directLoginBindingComponent;
+
+//MochiKit.Logging.logDebug("--- DirectLoginComponent.render - 9");
+ directLoginBindingElement = Clipperz.YUI.DomHelper.append(bindingsElement.dom, {tag:'tr'}, true);
+//MochiKit.Logging.logDebug("--- DirectLoginComponent.render - 10");
+ directLoginBindingComponent = new Clipperz.PM.Components.RecordDetail.DirectLoginBindingComponent(directLoginBindingElement, {
+ mainComponent:this,
+ directLoginBinding:this.directLogin().bindings()[bindingKey]
+ });
+//MochiKit.Logging.logDebug("--- DirectLoginComponent.render - 11");
+ this._directLoginBindingComponents.push(directLoginBindingComponent);
+ } catch (e) {
+ MochiKit.Logging.logError("Error while rendering a DirectLoginBindingComponent - " + e);
+ }
+//MochiKit.Logging.logDebug("--- DirectLoginComponent.render - 12");
+ }
+//MochiKit.Logging.logDebug("--- DirectLoginComponent.render - 13");
+
+ inputsRequiringAdditionalValues = this.directLogin().inputsRequiringAdditionalValues();
+//MochiKit.Logging.logDebug("--- DirectLoginComponent.render - 13.1");
+ for (valueName in inputsRequiringAdditionalValues) {
+//- Clipperz.YUI.DomHelper.append(bindingsElement.dom, {tag:'tr', children:[
+//- {tag:'td', html:valueName},
+//- {tag:'td', children:inputsRequiringAdditionalValues[valueName].inputElementConfiguration()}
+//- ]}, true)
+ var directLoginValueElement;
+ var directLoginValueComponent;
+
+//MochiKit.Logging.logDebug("--- DirectLoginComponent.render - 13.2");
+ directLoginValueElement = Clipperz.YUI.DomHelper.append(bindingsElement.dom, {tag:'tr'}, true);
+//MochiKit.Logging.logDebug("--- DirectLoginComponent.render - 13.3");
+ directLoginValueComponent = new Clipperz.PM.Components.RecordDetail.DirectLoginValueComponent(directLoginValueElement, {
+ mainComponent:this,
+ directLoginInputValue:inputsRequiringAdditionalValues[valueName]
+ });
+//MochiKit.Logging.logDebug("--- DirectLoginComponent.render - 13.4");
+ this._directLoginBindingComponents.push(directLoginValueComponent);
+//MochiKit.Logging.logDebug("--- DirectLoginComponent.render - 13.5");
+ }
+//MochiKit.Logging.logDebug("--- DirectLoginComponent.render - 13.6");
+ }
+//MochiKit.Logging.logDebug("--- DirectLoginComponent.render - 14");
+ this.setRemoveButton(new YAHOO.ext.Button(this.getDom('removeDirectLoginButton'), {text:Clipperz.PM.Strings['recordDetailDeleteDirectLoginButtonLabel'], handler:this.removeDirectLogin, scope:this}));
+//MochiKit.Logging.logDebug("--- DirectLoginComponent.render - 15");
+ this.update();
+ } catch (e) {
+ MochiKit.Logging.logError("Error while rendering a DirectLoginComponent - " + e);
+ }
+//MochiKit.Logging.logDebug("<<< DirectLoginComponent.render");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'collapser': function() {
+ return this._collapser;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'handleLoadedFaviconImage': function(anEvent) {
+ MochiKit.Signal.disconnectAll(anEvent.src())
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'update': function() {
+ var i,c;
+ var bindingComponents;
+
+//MochiKit.Logging.logDebug(">>> DirectLoginComponent.update");
+ bindingComponents = this.directLoginBindingComponents();
+ c = bindingComponents.length;
+ for (i=0; i<c; i++) {
+ bindingComponents[i].update();
+ }
+
+ Clipperz.PM.Components.RecordDetail.DirectLoginComponent.superclass.update.call(this);
+//MochiKit.Logging.logDebug("<<< DirectLoginComponent.update");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'updateEditMode': function() {
+// this.element().update("");
+// Clipperz.YUI.DomHelper.append(this.element().dom, {tag:'div', style:'border:4px solid red; padding:10px;', children:[
+// {tag:'div', style:'font-weight:bold;', html:this.directLogin().label()},
+// {tag:'div', style:'border:1px solid #aaaaaa;', html:Clipperz.Base.serializeJSON(this.directLogin().formData())},
+// {tag:'div', style:'border:1px solid #aaaaaa;', html:Clipperz.Base.serializeJSON(this.directLogin().bindings())}
+// ]});
+
+ this.getElement('titleEditBox').show();
+ this.getElement('titleViewBox').hide();
+
+ this.getDom('titleInput').value = this.directLogin().label();
+
+//MochiKit.Logging.logDebug(">>> DirectLoginComponent.updateEditMode");
+ this.collapser().expand();
+ this.getElement('collapseLink').hide();
+ this.getElement('removeDirectLogin').show();
+// this.removeButton().show();
+//MochiKit.Logging.logDebug("<<< DirectLoginComponent.updateEditMode");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'updateViewMode': function() {
+//MochiKit.Logging.logDebug(">>> DirectLoginComponent.updateViewMode");
+ this.getElement('titleEditBox').hide();
+ this.getElement('titleViewBox').show();
+ this.getElement('titleLink').update(this.directLogin().label());
+
+ this.getElement('collapseLink').show();
+ this.getElement('removeDirectLogin').hide();
+// this.removeButton().hide();
+//MochiKit.Logging.logDebug("<<< DirectLoginComponent.updateViewMode");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'synchronizeComponentValues': function() {
+//MochiKit.Logging.logDebug(">>> DirectLoginComponent.syncronizeComponentValues");
+ this.directLogin().setLabel(this.getDom('titleInput').value);
+// this.setFormDataValue(this.structureElement().value());
+
+ MochiKit.Iter.forEach(this.directLoginBindingComponents(), MochiKit.Base.methodcaller('synchronizeComponentValues'));
+//MochiKit.Logging.logDebug("<<< DirectLoginComponent.syncronizeComponentValues");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'runDirectLogin': function(anEvent) {
+//MochiKit.Logging.logDebug("--- DirectLoginComponent.runDirectLogin - 1");
+//MochiKit.Logging.logDebug("--- DirectLoginComponent.runDirectLogin - 1 anEvent: " + anEvent);
+ anEvent.stop();
+//MochiKit.Logging.logDebug("--- DirectLoginComponent.runDirectLogin - 2");
+ this.directLogin().runDirectLogin();
+//MochiKit.Logging.logDebug("--- DirectLoginComponent.runDirectLogin - 3");
+ },
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+});
+
diff --git a/frontend/beta/js/Clipperz/PM/Components/RecordDetail/DirectLoginValueComponent.js b/frontend/beta/js/Clipperz/PM/Components/RecordDetail/DirectLoginValueComponent.js
new file mode 100644
index 0000000..e70229b
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Components/RecordDetail/DirectLoginValueComponent.js
@@ -0,0 +1,257 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
+if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
+if (typeof(Clipperz.PM.Components) == 'undefined') { Clipperz.PM.Components = {}; }
+if (typeof(Clipperz.PM.Components.RecordDetail) == 'undefined') { Clipperz.PM.Components.RecordDetail = {}; }
+
+//#############################################################################
+
+Clipperz.PM.Components.RecordDetail.DirectLoginValueComponent = function(anElement, args) {
+//MochiKit.Logging.logDebug(">>> new DirectLoginValueComponent");
+ args = args || {};
+
+ Clipperz.PM.Components.RecordDetail.DirectLoginValueComponent.superclass.constructor.call(this, anElement, args);
+
+ this._directLoginInputValue = args.directLoginInputValue || null;
+ this._value = this.directLoginInputValue().directLogin().formValues()[this.directLoginInputValue().name()];
+
+ this.render();
+//MochiKit.Logging.logDebug("<<< new DirectLoginValueComponent - record: " + this.record());
+
+ return this;
+}
+
+//=============================================================================
+
+YAHOO.extendX(Clipperz.PM.Components.RecordDetail.DirectLoginValueComponent, Clipperz.PM.Components.RecordDetail.AbstractComponent, {
+
+ 'toString': function() {
+ return "Clipperz.PM.Components.RecordDetail.DirectLoginValueComponent component - " + this.directLoginInputValue().name();
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'directLoginInputValue': function() {
+ return this._directLoginInputValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'render': function() {
+//MochiKit.Logging.logDebug(">>> DirectLoginValueComponent.render");
+ Clipperz.YUI.DomHelper.append(this.element().dom, {tag:'td', cls:'directLoginDataLabelTD', children:[
+ {tag:'span', html:this.directLoginInputValue().name()}
+ ]});
+//MochiKit.Logging.logDebug("--- DirectLoginValueComponent.render - 1");
+ Clipperz.YUI.DomHelper.append(this.element().dom, {tag:'td', cls:'directLoginDataValueTD', children:[
+ {tag:'span', id:this.getId('inputElement')}
+ ]});
+//MochiKit.Logging.logDebug("--- DirectLoginValueComponent.render - 2");
+ this.update();
+//MochiKit.Logging.logDebug("<<< DirectLoginValueComponent.render");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'inputElementConfiguration': function() {
+ var result;
+ var currentValue;
+
+//MochiKit.Logging.logDebug(">>> DirectLoginValueComponent.inputElementConfiguration - " + this.directLoginInputValue().name());
+ result = [];
+ currentValue = this.value();
+
+ switch (this.directLoginInputValue().type()) {
+ case 'checkbox':
+ var checkbox;
+//{"type":"checkbox", "name":"rememberUsernameChk", "value":"checkbox"}
+ checkbox = {tag:'input', id:this.getId('checkbox'), type:'checkbox'}
+ if (currentValue == true) {
+ checkbox.checked = true;
+ }
+ result.push(checkbox);
+ break;
+
+ case 'select':
+ var input;
+//{"type":"select", "name":"DOMAIN", "options":[{"selected":true, "label":"@tin.it", "value":"tin.it"}, {"selected":false, "label":"@virgilio.it", "value":"virgilio.it"}]}
+ input = {tag:'select', id:this.getId('select'), name:this.directLoginInputValue().name(), children:[]};
+ input.children.push({tag:'option', value:null, html:"---"});
+ MochiKit.Iter.forEach(this.directLoginInputValue().args()['options'], function(anOption) {
+ var option;
+
+// TODO: remove the value: field and replace it with element.dom.value = <some value>
+ option = {tag:'option', value:anOption['value'], html:anOption['label']}
+ if (currentValue == anOption['value']) {
+ option.selected = true;
+ }
+ input.children.push(option);
+ })
+ result.push(input);
+ break;
+
+ case 'radio':
+ var name;
+ var radioBox;
+
+//MochiKit.Logging.logDebug("--- DirectLoginValueComponent.inputElementConfiguration - 3");
+ name = this.getId(this.directLoginInputValue().name());
+ radioBox = {tag:'div', id:this.getId('radioBox'), children:[]};
+ result.push(radioBox);
+//MochiKit.Logging.logDebug("--- DirectLoginValueComponent.inputElementConfiguration - 3.1 - options.length: " + this.directLoginInputValue().args()['options'].length);
+//{"name":"dominio", "type":"radio", "options":[{"value":"@alice.it", "checked":true}, {"value":"@tin.it", "checked":false}, {"value":"@virgilio.it", "checked":false}, {"value":"@tim.it", "checked":false}]}
+
+ MochiKit.Iter.forEach(this.directLoginInputValue().args()['options'], function(anOption) {
+ var radio;
+
+//MochiKit.Logging.logDebug("--- DirectLoginValueComponent.inputElementConfiguration - 3.1.1");
+// TODO: remove the value: field and replace it with element.dom.value = <some value>
+ radio = {tag:'input', type:'radio', name:name, value:anOption['value']};
+//MochiKit.Logging.logDebug("--- DirectLoginValueComponent.inputElementConfiguration - 3.1.2");
+ if (currentValue == anOption['value']) {
+//MochiKit.Logging.logDebug("--- DirectLoginValueComponent.inputElementConfiguration - 3.1.3");
+ radio.checked = true;
+//MochiKit.Logging.logDebug("--- DirectLoginValueComponent.inputElementConfiguration - 3.1.4");
+ }
+//MochiKit.Logging.logDebug("--- DirectLoginValueComponent.inputElementConfiguration - 3.1.5");
+ radioBox.children.push({tag:'div', children:[ radio, {tag:'span', html:anOption['value']} ]})
+//MochiKit.Logging.logDebug("--- DirectLoginValueComponent.inputElementConfiguration - 3.1.6");
+ })
+//MochiKit.Logging.logDebug("--- DirectLoginValueComponent.inputElementConfiguration - 3.2");
+ break;
+ }
+//MochiKit.Logging.logDebug("<<< DirectLoginValueComponent.inputElementConfiguration");
+
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'inputValue': function() {
+ var result;
+
+ switch (this.directLoginInputValue().type()) {
+ case 'checkbox':
+ result = this.getDom('checkbox').checked;
+ break;
+ case 'select':
+ result = this.getDom('select').value;
+ break;
+ case 'radio':
+ var checkedRadioButtons;
+
+ checkedRadioButtons = MochiKit.Base.filter( function(aRadioButton) { return aRadioButton.dom.checked },
+ this.getElement('radioBox').getChildrenByTagName('input'));
+
+ if (checkedRadioButtons.length == 0) {
+ result = null;
+ } else {
+ result = checkedRadioButtons[0].dom.value;
+ }
+ break;
+ }
+
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'value': function() {
+ return this._value;
+ },
+
+ 'setValue': function(aValue) {
+ this._value = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'updateEditMode': function() {
+//MochiKit.Logging.logDebug(">>> DirectLoginValueComponent.updateEditMode - " + this);
+ this.getElement('inputElement').update("");
+//MochiKit.Logging.logDebug("--- DirectLoginValueComponent.updateEditMode - 1");
+ Clipperz.YUI.DomHelper.append(this.getDom('inputElement'), {tag:'div', children:this.inputElementConfiguration()});
+//MochiKit.Logging.logDebug("<<< DirectLoginValueComponent.updateEditMode");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'updateViewMode': function() {
+//MochiKit.Logging.logDebug(">>> DirectLoginValueComponent.updateViewMode");
+// this.getElement('inputElement').update(this.directLoginInputValue().value());
+
+ this.getElement('inputElement').update("");
+
+ switch (this.directLoginInputValue().type()) {
+ case 'checkbox':
+ if (this.value() == true) {
+ this.getElement('inputElement').update(Clipperz.PM.Strings['directLoginConfigurationCheckBoxFieldSelectedValue']);
+ } else {
+ this.getElement('inputElement').update(Clipperz.PM.Strings['directLoginConfigurationCheckBoxFieldNotSelectedValue'])
+ }
+ break;
+ case 'select':
+ var displayedValue;
+ var selectedOptions;
+ var currentValue;
+
+ currentValue = this.value();
+ selectedOptions = MochiKit.Base.filter( function(anOption) { return (anOption['value'] == currentValue); },
+ this.directLoginInputValue().args()['options']);
+ if (selectedOptions.length == 0) {
+ displayedValue = "---";
+ } else {
+//MochiKit.Logging.logDebug("+++ " + Clipperz.Base.serializeJSON(selectedOptions));
+//MochiKit.Logging.logDebug("*** " + Clipperz.Base.serializeJSON(selectedOptions[0]));
+ displayedValue = selectedOptions[0]['label'];
+ }
+ this.getElement('inputElement').update(displayedValue);
+ break;
+ case 'radio':
+ this.getElement('inputElement').update(this.value());
+ break;
+ }
+//MochiKit.Logging.logDebug("<<< DirectLoginValueComponent.updateViewMode");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'synchronizeComponentValues': function() {
+//MochiKit.Logging.logDebug(">>> DirectLoginValueComponent.synchronizeComponentValues");
+//MochiKit.Logging.logDebug("--- DirectLoginValueComponent.synchronizeComponentValues - 1; value: " + this.inputValue());
+ this.setValue(this.inputValue());
+ this.directLoginInputValue().directLogin().formValues()[this.directLoginInputValue().name()] = this.value();
+//MochiKit.Logging.logDebug("<<< DirectLoginValueComponent.synchronizeComponentValues");
+ },
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+});
+
diff --git a/frontend/beta/js/Clipperz/PM/Components/RecordDetail/DirectLoginsComponent.js b/frontend/beta/js/Clipperz/PM/Components/RecordDetail/DirectLoginsComponent.js
new file mode 100644
index 0000000..3292a95
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Components/RecordDetail/DirectLoginsComponent.js
@@ -0,0 +1,199 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
+if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
+if (typeof(Clipperz.PM.Components) == 'undefined') { Clipperz.PM.Components = {}; }
+if (typeof(Clipperz.PM.Components.RecordDetail) == 'undefined') { Clipperz.PM.Components.RecordDetail = {}; }
+
+//#############################################################################
+
+Clipperz.PM.Components.RecordDetail.DirectLoginsComponent = function(anElement, args) {
+//MochiKit.Logging.logDebug(">>> new Clipperz.PM.Components.RecordDetail.DirectLoginsComponent");
+ args = args || {};
+
+//MochiKit.Logging.logDebug("--- new Clipperz.PM.Components.RecordDetail.DirectLoginsComponent - 0");
+ Clipperz.PM.Components.RecordDetail.DirectLoginsComponent.superclass.constructor.call(this, anElement, args);
+//MochiKit.Logging.logDebug("--- new Clipperz.PM.Components.RecordDetail.DirectLoginsComponent - 1");
+
+ this._addDirectLoginButton = null;
+
+//MochiKit.Logging.logDebug("--- new Clipperz.PM.Components.RecordDetail.DirectLoginsComponent - 2");
+ this.mainComponent().addEditComponent(this);
+//MochiKit.Logging.logDebug("--- new Clipperz.PM.Components.RecordDetail.DirectLoginsComponent - 3");
+ this.render();
+//MochiKit.Logging.logDebug("<<< new Clipperz.PM.Components.RecordDetail.DirectLoginsComponent");
+
+ return this;
+}
+
+//=============================================================================
+
+YAHOO.extendX(Clipperz.PM.Components.RecordDetail.DirectLoginsComponent, Clipperz.PM.Components.RecordDetail.AbstractComponent, {
+
+ 'toString': function() {
+ return "Clipperz.PM.Components.RecordDetail.DirectLoginsComponent component";
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'addDirectLoginButton': function() {
+ return this._addDirectLoginButton;
+ },
+
+ 'setAddDirectLoginButton': function(aValue) {
+ this._addDirectLoginButton = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'render': function() {
+ this.element().update("");
+
+ Clipperz.YUI.DomHelper.append(this.element().dom,
+ {tag:'div', cls:'directLoginsRecordBox', children:[
+ {tag:'h3', htmlString:Clipperz.PM.Strings['recordDetailDirectLoginBlockTitle']},
+ {tag:'ul', id:this.getId('directLogins')},
+
+ {tag:'div', cls:'addDirectLoginBox', id:this.getId('addDirectLogin'), children:[
+ {tag:'div', cls:'addDirectLoginBoxContent', children:[
+ {tag:'div', cls:'bookmarkletConfiguration', children:[
+// {tag:'span', htmlString:Clipperz.PM.Strings['newRecordWizardBookmarkletConfigurationLabel']},
+ {tag:'div', htmlString:Clipperz.PM.Strings['recordDetailNewDirectLoginDescription']},
+ {tag:'textarea', id:this.getId('addDirectLoginTextarea')}
+ ]},
+ {tag:'div', id:this.getId('addDirectLoginButton')}
+ ]}
+ ]}
+ ]}
+ );
+
+ if (MochiKit.Base.keys(this.record().directLogins()).length == 0) {
+//MochiKit.Logging.logDebug("--- DirectLoginsComponent.render - 3");
+ Clipperz.YUI.DomHelper.append(this.getElement('directLogins'),
+ {tag:'li', children:[
+// {tag:'span', htmlString:Clipperz.PM.Strings['recordDetailDirectLoginBlockNoDirectLoginConfiguredLabel']}
+ {tag:'div', cls:'recordDetailNoDirectLoginDescriptionBox', htmlString:Clipperz.PM.Strings['recordDetailDirectLoginBlockNoDirectLoginConfiguredDescription']}
+ ]}
+ );
+//MochiKit.Logging.logDebug("--- DirectLoginsComponent.render - 4");
+ } else {
+//MochiKit.Logging.logDebug("--- DirectLoginsComponent.render - 5");
+ for (directLoginReference in this.record().directLogins()) {
+//MochiKit.Logging.logDebug("--- DirectLoginsComponent.render - 6");
+ this.addDirectLogin(this.record().directLogins()[directLoginReference]);
+//MochiKit.Logging.logDebug("--- DirectLoginsComponent.render - 7");
+ }
+//MochiKit.Logging.logDebug("--- DirectLoginsComponent.render - 8");
+ }
+//MochiKit.Logging.logDebug("--- DirectLoginsComponent.render - 9");
+
+ this.setAddDirectLoginButton(new YAHOO.ext.Button(this.getDom('addDirectLoginButton'), {
+ text:Clipperz.PM.Strings['recordDetailAddNewDirectLoginButtonLabel'],
+ handler:this.addNewDirectLogin,
+ scope:this
+ }));
+ MochiKit.Signal.connect(this.getId('addDirectLoginTextarea'), 'onkeydown', this, 'onkeydown');
+//MochiKit.Logging.logDebug("--- DirectLoginsComponent.render - 11");
+
+ this.update();
+//MochiKit.Logging.logDebug("<<< DirectLoginsComponent.render");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'addDirectLogin': function(aDirectLogin) {
+//MochiKit.Logging.logDebug(">>> DirectLoginsComponent.addDirectLogin");
+ new Clipperz.PM.Components.RecordDetail.DirectLoginComponent(
+ Clipperz.YUI.DomHelper.append(this.getDom('directLogins'), {tag:'div'}, true),
+ {
+ mainComponent:this.mainComponent(),
+ directLogin:aDirectLogin
+ }
+ );
+//MochiKit.Logging.logDebug("<<< DirectLoginsComponent.addDirectLogin");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'addNewDirectLogin': function() {
+ var newDirectLogin;
+ var configuration;
+
+//MochiKit.Logging.logDebug(">>> DirectLoginsComponent.addNewDirectLogin");
+ if (MochiKit.Base.keys(this.record().directLogins()).length == 0) {
+ this.getElement('directLogins').update("");
+ }
+
+ this.mainComponent().synchronizeComponentValues();
+
+ this.mainComponent().exitModalView();
+ configuration = Clipperz.PM.BookmarkletProcessor.checkBookmarkletConfiguration(
+ this.getDom('addDirectLoginTextarea').value,
+ this.getDom('addDirectLoginButton'),
+ MochiKit.Base.method(this.mainComponent(), 'enterModalView')
+ );
+ this.mainComponent().enterModalView();
+
+ newDirectLogin = new Clipperz.PM.DataModel.DirectLogin({record:this.record(),
+ label:configuration['page']['title'],
+ bookmarkletVersion:'0.2',
+// bookmarkletVersion:configuration['version'],
+ formData:configuration['form']});
+ this.record().addDirectLogin(newDirectLogin);
+ this.addDirectLogin(newDirectLogin);
+ this.getDom('addDirectLoginTextarea').value = "";
+//MochiKit.Logging.logDebug("<<< DirectLoginsComponent.addNewDirectLogin");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'updateViewMode': function() {
+ this.getElement('addDirectLogin').setVisibilityMode(YAHOO.ext.Element.DISPLAY);
+ this.getElement('addDirectLogin').hide();
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'updateEditMode': function() {
+ this.getElement('addDirectLogin').show();
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'onkeydown': function(anEvent) {
+//MochiKit.Logging.logDebug(">>> onkeydown - " + anEvent.src().id + ": " + anEvent.key().code);
+ if (anEvent.key().code == 13) {
+ this.addNewDirectLogin();
+ }
+ },
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+});
+
diff --git a/frontend/beta/js/Clipperz/PM/Components/RecordDetail/FieldButtonComponent.js b/frontend/beta/js/Clipperz/PM/Components/RecordDetail/FieldButtonComponent.js
new file mode 100644
index 0000000..9e1d56a
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Components/RecordDetail/FieldButtonComponent.js
@@ -0,0 +1,117 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
+if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
+if (typeof(Clipperz.PM.Components) == 'undefined') { Clipperz.PM.Components = {}; }
+if (typeof(Clipperz.PM.Components.RecordDetail) == 'undefined') { Clipperz.PM.Components.RecordDetail = {}; }
+
+//#############################################################################
+
+Clipperz.PM.Components.RecordDetail.FieldButtonComponent = function(anElement, args) {
+ args = args || {};
+
+ Clipperz.PM.Components.RecordDetail.FieldButtonComponent.superclass.constructor.call(this, anElement, args);
+
+ this._button = null;
+
+ this.render();
+
+ return this;
+}
+
+//=============================================================================
+
+YAHOO.extendX(Clipperz.PM.Components.RecordDetail.FieldButtonComponent, Clipperz.PM.Components.RecordDetail.AbstractFieldSubComponent, {
+
+ 'toString': function() {
+ return "Clipperz.PM.Components.RecordDetail.FieldButtonComponent";
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'buttonText': function() {
+ var result;
+
+ if (this.recordField() == null) {
+ // TODO: this is never used. It is just an obsolete legacy chunk of code
+ result = Clipperz.PM.Strings['recordDetailAddFieldButtonLabel'];
+ } else {
+ result = Clipperz.PM.Strings['recordDetailRemoveFieldButtonLabel'];
+ }
+
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'button': function() {
+ return this._button;
+ },
+
+ 'setButton': function(aValue) {
+ this._button = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'render': function() {
+ this.element().update("");
+
+ Clipperz.YUI.DomHelper.append(this.element().dom, {tag:'div', id:this.getId('button')})
+ this.setButton(new YAHOO.ext.Button(this.getDom('button'), {text:this.buttonText(), handler:this.handleButtonClick, scope:this}));
+
+ this.update();
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'handleButtonClick': function() {
+ if (this.recordField() == null) {
+ this.mainComponent().addNewField();
+ } else {
+ this.mainComponent().removeField(this.fieldComponent());
+ }
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'updateEditMode': function() {
+ this.button().show();
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'updateViewMode': function() {
+ this.button().hide();
+ },
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+});
+
diff --git a/frontend/beta/js/Clipperz/PM/Components/RecordDetail/FieldComponent.js b/frontend/beta/js/Clipperz/PM/Components/RecordDetail/FieldComponent.js
new file mode 100644
index 0000000..c2d947e
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Components/RecordDetail/FieldComponent.js
@@ -0,0 +1,189 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
+if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
+if (typeof(Clipperz.PM.Components) == 'undefined') { Clipperz.PM.Components = {}; }
+if (typeof(Clipperz.PM.Components.RecordDetail) == 'undefined') { Clipperz.PM.Components.RecordDetail = {}; }
+
+//#############################################################################
+
+Clipperz.PM.Components.RecordDetail.FieldComponent = function(anElement, args) {
+//MochiKit.Logging.logDebug(">>> new FieldComponent");
+ args = args || {};
+
+ Clipperz.PM.Components.RecordDetail.FieldComponent.superclass.constructor.call(this, anElement, args);
+
+ this._element = anElement;
+ this._recordField = args.recordField || null;
+
+ this._buttonComponent = null;
+ this._labelComponent = null;
+ this._dragHandler = null;
+ this._valueComponent = null;
+ this._typeComponent = null;
+
+ this.mainComponent().addEditComponent(this);
+
+ this.render();
+
+ return this;
+}
+
+//=============================================================================
+
+YAHOO.extendX(Clipperz.PM.Components.RecordDetail.FieldComponent, Clipperz.PM.Components.RecordDetail.AbstractComponent, {
+
+ 'toString': function() {
+ return "Clipperz.PM.Components.RecordDetail.FieldComponent component";
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'recordField': function() {
+ return this._recordField;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'buttonComponent': function() {
+ return this._buttonComponent;
+ },
+
+ 'setButtonComponent': function(aValue) {
+ this._buttonComponent = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'labelComponent': function() {
+ return this._labelComponent;
+ },
+
+ 'setLabelComponent': function(aValue) {
+ this._labelComponent = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'dragHandler': function() {
+ return this._dragHandler;
+ },
+
+ 'setDragHandler': function(aValue) {
+ this._dragHandler = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'valueComponent': function() {
+ return this._valueComponent;
+ },
+
+ 'setValueComponent': function(aValue) {
+ this._valueComponent = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'typeComponent': function() {
+ return this._typeComponent;
+ },
+
+ 'setTypeComponent': function(aValue) {
+ this._typeComponent = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'render': function() {
+//MochiKit.Logging.logDebug(">>> RecordDetail.FieldComponent.render");
+ Clipperz.YUI.DomHelper.append(this.element().dom, {tag:'td',/* width:'32',*/ height:'24', cls:'removeFieldButton', align:'left', valign:'top', id:this.getId('button')});
+ Clipperz.YUI.DomHelper.append(this.element().dom, {tag:'td',/* width:'25%',*/ valign:'top', id:this.getId('label')});
+ Clipperz.YUI.DomHelper.append(this.element().dom, {tag:'td',/* width:'3',*/ valign:'top', id:this.getId('dragHandler')});
+ Clipperz.YUI.DomHelper.append(this.element().dom, {tag:'td',/* width:'50%',*/ valign:'top', children:[
+ {tag:'div', cls:'Clipperz_recordFieldData', id:this.getId('value')}
+ ]});
+
+
+ this.setButtonComponent(new Clipperz.PM.Components.RecordDetail.FieldButtonComponent(this.getElement('button'), {fieldComponent:this}));
+ this.setLabelComponent(new Clipperz.PM.Components.RecordDetail.FieldLabelComponent(this.getElement('label'), {fieldComponent:this}));
+ this.setDragHandler(new Clipperz.PM.Components.RecordDetail.FieldDragHandler(this.getElement('dragHandler'), {fieldComponent:this}));
+ this.setValueComponent(new Clipperz.PM.Components.RecordDetail.FieldValueComponent(this.getElement('value'), {fieldComponent:this}));
+
+ if (this.editMode() == 'EDIT') {
+ Clipperz.YUI.DomHelper.append(this.element().dom, {tag:'td',/* width:'60',*/ align:'left', cls:'fieldTypeTD', valign:'top', id:this.getId('type')});
+ this.setTypeComponent(new Clipperz.PM.Components.RecordDetail.FieldTypeComponent(this.getElement('type'), {fieldComponent:this}));
+ }
+
+ this.update();
+//MochiKit.Logging.logDebug("<<< RecordDetail.FieldComponent.render");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'handleButtonClick': function() {
+ this.mainComponent().record().removeField(this.recordField());
+
+// if (this.recordField() == null) {
+// this.mainComponent().record().addNewField();
+// } else {
+// this.mainComponent().record().removeField(this.recordField());
+// }
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'update': function(anEvent) {
+//MochiKit.Logging.logDebug(">>> RecordDetail.FieldComponent.update");
+ this.buttonComponent().update();
+ this.labelComponent().update();
+ this.dragHandler().update();
+ this.valueComponent().update();
+ if (this.editMode() == 'EDIT') {
+ this.typeComponent().update();
+ }
+//MochiKit.Logging.logDebug("<<< RecordDetail.FieldComponent.update");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'synchronizeComponentValues': function() {
+//MochiKit.Logging.logDebug(">>> FieldComponent.synchronizeComponentValues");
+ this.labelComponent().synchronizeComponentValues();
+ this.valueComponent().synchronizeComponentValues();
+ if (this.editMode() == 'EDIT') {
+ this.typeComponent().synchronizeComponentValues();
+ }
+//MochiKit.Logging.logDebug("<<< FieldComponent.synchronizeComponentValues");
+ },
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+});
+
diff --git a/frontend/beta/js/Clipperz/PM/Components/RecordDetail/FieldDragHandler.js b/frontend/beta/js/Clipperz/PM/Components/RecordDetail/FieldDragHandler.js
new file mode 100644
index 0000000..13a08fc
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Components/RecordDetail/FieldDragHandler.js
@@ -0,0 +1,59 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
+if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
+if (typeof(Clipperz.PM.Components) == 'undefined') { Clipperz.PM.Components = {}; }
+if (typeof(Clipperz.PM.Components.RecordDetail) == 'undefined') { Clipperz.PM.Components.RecordDetail = {}; }
+
+//#############################################################################
+
+Clipperz.PM.Components.RecordDetail.FieldDragHandler = function(anElement, args) {
+ args = args || {};
+
+ Clipperz.PM.Components.RecordDetail.FieldDragHandler.superclass.constructor.call(this, anElement, args);
+
+ this._element = anElement;
+
+ this.render();
+
+ return this;
+}
+
+//=============================================================================
+
+YAHOO.extendX(Clipperz.PM.Components.RecordDetail.FieldDragHandler, Clipperz.PM.Components.RecordDetail.AbstractFieldSubComponent, {
+
+ 'toString': function() {
+ return "Clipperz.PM.Components.RecordDetail.FieldDragHandler component";
+ },
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+});
+
diff --git a/frontend/beta/js/Clipperz/PM/Components/RecordDetail/FieldLabelComponent.js b/frontend/beta/js/Clipperz/PM/Components/RecordDetail/FieldLabelComponent.js
new file mode 100644
index 0000000..3bbcd1d
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Components/RecordDetail/FieldLabelComponent.js
@@ -0,0 +1,141 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
+if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
+if (typeof(Clipperz.PM.Components) == 'undefined') { Clipperz.PM.Components = {}; }
+if (typeof(Clipperz.PM.Components.RecordDetail) == 'undefined') { Clipperz.PM.Components.RecordDetail = {}; }
+
+//#############################################################################
+
+Clipperz.PM.Components.RecordDetail.FieldLabelComponent = function(anElement, args) {
+ args = args || {};
+
+ Clipperz.PM.Components.RecordDetail.FieldLabelComponent.superclass.constructor.call(this, anElement, args);
+
+ this._inputElement = null;
+
+ this.render();
+
+ return this;
+}
+
+//=============================================================================
+
+YAHOO.extendX(Clipperz.PM.Components.RecordDetail.FieldLabelComponent, Clipperz.PM.Components.RecordDetail.AbstractFieldSubComponent, {
+
+ 'toString': function() {
+ return "Clipperz.PM.Components.RecordDetail.FieldLabelComponent component";
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'value': function() {
+ return this.recordField().label();
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'inputElement': function() {
+ return this._inputElement;
+ },
+
+ 'setInputElement': function(aValue) {
+ this._inputElement = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'render': function() {
+ var newTextFormField;
+ this.element().update("");
+ Clipperz.YUI.DomHelper.append(this.element().dom, {tag:'div', cls:'Clipperz_recordFieldLabel', id:this.getId('label')});
+// Clipperz.YUI.DomHelper.append(this.element().dom, {tag:'div', style:'font-size:8pt;', html:this.recordField().key()});
+
+// this.setInputElement(new Clipperz.PM.Components.TextFormField(this.getElement('label'), {editMode:this.editMode(), value:this.value()}));
+ newTextFormField = new Clipperz.PM.Components.TextFormField(this.getElement('label'), {editMode:this.editMode(), value:this.value()});
+// newTextFormField.inputElement().setStyle({border:'3px solid cyan;'});
+ newTextFormField.on('change', this.notifyChanges, this, true)
+// this.inputElement().on('change', function() {alert("CHANGE");});
+// this.inputElement().getElement('editComponent_input').on('change', function() {alert("CHANGE");})
+// this.inputElement().on('blur', this.notifyChanges, this, true);
+
+ this.setInputElement(newTextFormField);
+ this.update();
+ },
+
+ 'notifyChanges': function() {
+//MochiKit.Logging.logDebug(">>> FieldLabelComponent.notifyChanges - " + this);
+ this.synchronizeComponentValues();
+ Clipperz.NotificationCenter.notify(this.recordField().recordVersion().record(), 'updatedFieldLabel');
+//MochiKit.Logging.logDebug("<<< FieldLabelComponent.notifyChanges");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'update': function() {
+//MochiKit.Logging.logDebug(">>> FieldLabelComponent.update");
+ this.inputElement().update({editMode:this.editMode(), value:this.value()});
+//MochiKit.Logging.logDebug("<<< FieldLabelComponent.update");
+ },
+
+ //-------------------------------------------------------------------------
+/*
+ 'updateViewMode': function() {
+ var width;
+ var element;
+
+ this.element().update("");
+ width = this.element().getWidth();
+ element = Clipperz.YUI.DomHelper.append(this.element().dom, {tag:'div', html:this.value()}, true);
+ element.setWidth(width-1);
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'updateEditMode': function() {
+ var width;
+
+ this.element().update("");
+ width = this.element().getWidth(true);
+ this.setInputElement(Clipperz.YUI.DomHelper.append(this.element().dom, {tag:'input', type:'text', value:this.value()}, true));
+ this.inputElement().setWidth(width-1);
+ },
+*/
+ //-------------------------------------------------------------------------
+
+ 'synchronizeComponentValues': function() {
+ if (this.inputElement() != null) {
+ this.recordField().setLabel(this.inputElement().value());
+ }
+ },
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+});
+
diff --git a/frontend/beta/js/Clipperz/PM/Components/RecordDetail/FieldTypeComponent.js b/frontend/beta/js/Clipperz/PM/Components/RecordDetail/FieldTypeComponent.js
new file mode 100644
index 0000000..3bdd093
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Components/RecordDetail/FieldTypeComponent.js
@@ -0,0 +1,157 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
+if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
+if (typeof(Clipperz.PM.Components) == 'undefined') { Clipperz.PM.Components = {}; }
+if (typeof(Clipperz.PM.Components.RecordDetail) == 'undefined') { Clipperz.PM.Components.RecordDetail = {}; }
+
+//#############################################################################
+
+Clipperz.PM.Components.RecordDetail.FieldTypeComponent = function(anElement, args) {
+ args = args || {};
+
+ Clipperz.PM.Components.RecordDetail.FieldTypeComponent.superclass.constructor.call(this, anElement, args);
+
+ this._inputElement = null;
+
+ this.render();
+
+ return this;
+}
+
+//=============================================================================
+
+YAHOO.extendX(Clipperz.PM.Components.RecordDetail.FieldTypeComponent, Clipperz.PM.Components.RecordDetail.AbstractFieldSubComponent, {
+
+ 'toString': function() {
+ return "Clipperz.PM.Components.RecordDetail.FieldTypeComponent component";
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'inputElement': function() {
+ return this._inputElement;
+ },
+
+ 'setInputElement': function(aValue) {
+ this._inputElement = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'value': function() {
+ return this.recordField().type();
+ },
+
+ 'canChangeType': function() {
+ var value;
+ var result;
+
+ value = this.value();
+ result = ((value == 'TXT') || (value == 'PWD') || (value == 'URL') || (value == 'DATE') || (value == 'ADDR'));
+
+ return result
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'updateViewMode': function() {
+ this.element().update("");
+ if (this.canChangeType()) {
+ var width;
+ var element;
+
+ width = this.element().getWidth(true);
+ element = Clipperz.YUI.DomHelper.append(this.element().dom, {tag:'div', html:this.recordField().typeShortDescription()}, true);
+ element.setWidth(width-1);
+ }
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'updateEditMode': function() {
+ this.element().update("");
+
+ if (this.canChangeType()) {
+ var width;
+
+ width = this.element().getWidth(true);
+ this.setInputElement(Clipperz.YUI.DomHelper.append(this.element().dom, {tag:'select', children:[
+ {tag:'option', value:'TXT', htmlString:Clipperz.PM.Strings['recordFieldTypologies']['TXT']['shortDescription']},
+ {tag:'option', value:'PWD', htmlString:Clipperz.PM.Strings['recordFieldTypologies']['PWD']['shortDescription']},
+ {tag:'option', value:'URL', htmlString:Clipperz.PM.Strings['recordFieldTypologies']['URL']['shortDescription']},
+ {tag:'option', value:'DATE', htmlString:Clipperz.PM.Strings['recordFieldTypologies']['DATE']['shortDescription']},
+ {tag:'option', value:'ADDR', htmlString:Clipperz.PM.Strings['recordFieldTypologies']['ADDR']['shortDescription']}
+
+// {tag:'option', value:'CHECK', html:Clipperz.PM.DataModel.RecordField.TypeDescriptions['CHECK']['shortDescription']},
+// {tag:'option', value:'RADIO', html:Clipperz.PM.DataModel.RecordField.TypeDescriptions['RADIO']['shortDescription']},
+// {tag:'option', value:'CHECK', html:Clipperz.PM.DataModel.RecordField.TypeDescriptions['SELECT']['shortDescription']}
+// {tag:'option', value:'NOTE', html:Clipperz.PM.DataModel.RecordField.TypeDescriptions['NOTE']['shortDescription']}
+ ]}, true));
+ this.inputElement().setWidth(width-1);
+ this.inputElement().addHandler('change', true, this.onChange, this, true);
+// this.selectCorrectOption();
+ Clipperz.DOM.selectOptionMatchingValue(this.inputElement().dom, this.value());
+ }
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'onChange': function() {
+ this.synchronizeComponentValues();
+ this.fieldComponent().valueComponent().handleTypeChange();
+ },
+
+ //-------------------------------------------------------------------------
+/*
+ 'selectCorrectOption': function() {
+ var options;
+ var i,c;
+
+ options = this.inputElement().getChildrenByTagName('option');
+ c = options.length;
+ for (i=0; i<c; i++) {
+ if (options[i].dom.value == this.value()) {
+ options[i].dom.selected = true;
+ }
+ }
+ },
+*/
+ //-------------------------------------------------------------------------
+
+ 'synchronizeComponentValues': function() {
+ if (this.inputElement() != null) {
+ this.recordField().setType(this.inputElement().dom.value);
+ }
+ },
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+});
+
diff --git a/frontend/beta/js/Clipperz/PM/Components/RecordDetail/FieldValueComponent.js b/frontend/beta/js/Clipperz/PM/Components/RecordDetail/FieldValueComponent.js
new file mode 100644
index 0000000..a30992a
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Components/RecordDetail/FieldValueComponent.js
@@ -0,0 +1,275 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
+if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
+if (typeof(Clipperz.PM.Components) == 'undefined') { Clipperz.PM.Components = {}; }
+if (typeof(Clipperz.PM.Components.RecordDetail) == 'undefined') { Clipperz.PM.Components.RecordDetail = {}; }
+
+//#############################################################################
+
+Clipperz.PM.Components.RecordDetail.FieldValueComponent = function(anElement, args) {
+ args = args || {};
+
+ Clipperz.PM.Components.RecordDetail.FieldValueComponent.superclass.constructor.call(this, anElement, args);
+
+ this._inputElement = null;
+ this._scrambledStatus = 'SCRAMBLED'; // 'UNSCRAMBLED'
+
+ this.render();
+
+ return this;
+}
+
+//=============================================================================
+
+YAHOO.extendX(Clipperz.PM.Components.RecordDetail.FieldValueComponent, Clipperz.PM.Components.RecordDetail.AbstractFieldSubComponent, {
+
+ 'toString': function() {
+ return "Clipperz.PM.Components.RecordDetail.FieldValueComponent component";
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'value': function() {
+ return this.recordField().value();
+ },
+
+ 'setValue': function(aValue) {
+ this.recordField().setValue(aValue);
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'inputElement': function() {
+ return this._inputElement;
+ },
+
+ 'setInputElement': function(aValue) {
+ this._inputElement = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'scrambledStatus': function() {
+ return this._scrambledStatus;
+ },
+
+ 'setScrambledStatus': function(aValue) {
+ this._scrambledStatus = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'handleTypeChange': function() {
+//MochiKit.Logging.logDebug(">>> handling type change - " + this.recordField().type());
+ this.synchronizeComponentValues();
+ this.update();
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'addrUrl': function() {
+ var result;
+
+ result = "http://maps.google.com/maps?q=" + this.value().split(' ').join('+');
+
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'updateViewMode': function() {
+ var scarmbledStatus;
+
+ scrambledStatus = this.scrambledStatus() || 'SCRAMBLED';
+
+ this.element().update("");
+ if (this.recordField().hidden() == false) {
+ switch(this.recordField().type()) {
+ case 'TXT':
+ case 'PWD':
+ Clipperz.YUI.DomHelper.append(this.element().dom, {tag:'span', html:this.value()});
+ break;
+ case 'URL':
+ var urlLocation;
+
+ urlLocation = Clipperz.Base.sanitizeString(this.value());
+ if (! (/^(https?|ftp|svn):\/\//.test(urlLocation))) {
+ urlLocation = 'http://' + urlLocation;
+ }
+ Clipperz.YUI.DomHelper.append(this.element().dom, {tag:'a', href:urlLocation, html:this.value(), target:'_blank'});
+ break;
+ case 'DATE':
+ Clipperz.YUI.DomHelper.append(this.element().dom, {tag:'span', html:this.value()});
+ break;
+ case 'ADDR':
+ Clipperz.YUI.DomHelper.append(this.element().dom, {tag:'a', href:this.addrUrl(), html:this.value(), target:'_blank'});
+ break;
+ }
+ } else {
+ var tableElement;
+ var tdElement;
+ var inputElement;
+ var passwordElementConfiguration;
+
+ if (scrambledStatus == 'SCRAMBLED') {
+ var scrambledInputElement;
+
+ if ((Clipperz_IEisBroken === true) && (Clipperz.PM.Proxy.defaultProxy.isReadOnly())) {
+ scrambledInputElement = {tag:'input', type:'password', value:"this.value()"};
+ } else {
+ scrambledInputElement = {tag:'input', type:'text', cls:'scrambledField', title:Clipperz.PM.Strings['recordDetailPasswordFieldTooltipLabel'], value:"this.value()"};
+ }
+
+ passwordElementConfiguration =
+ {tag:'table', border:'0', cellspacing:'2', cellpadding:'0', children:[
+ {tag:'tbody', children:[
+ {tag:'tr', children:[
+ {tag:'td', valign:'top', children:[
+ scrambledInputElement,
+ {tag:'a', cls:'scrambleLink', id:this.getId('scrambleLink'), href:'#', htmlString:Clipperz.PM.Strings['recordDetailPasswordFieldUnscrambleLabel']}
+ ]},
+ {tag:'td', valign:'top', children:[
+ {tag:'span', cls:'scrambledFieldLabel', htmlString:Clipperz.PM.Strings['recordDetailPasswordFieldHelpLabel']}
+ ]}
+ ]}
+ ]}
+ ]};
+ } else {
+ passwordElementConfiguration =
+ {tag:'div', children:[
+ {tag:'input', type:'text', cls:'unscrambledField', value:"this.value()"},
+ {tag:'a', cls:'scrambleLink', id:this.getId('scrambleLink'), href:'#', htmlString:Clipperz.PM.Strings['recordDetailPasswordFieldScrambleLabel']}
+ ]};
+ }
+
+ tableElement = Clipperz.YUI.DomHelper.append(this.element().dom, passwordElementConfiguration, true);
+
+ inputElement = tableElement.getChildrenByTagName('input')[0];
+ inputElement.dom.value = this.value();
+ inputElement.wrap({tag:'div', cls:'passwordBackground'}).setStyle('background-position', "0px -" + Math.min(128, Clipperz.PM.Crypto.passwordEntropy(this.value())) + "px");
+
+ MochiKit.Signal.connect(inputElement.dom, 'onfocus', this, 'selectHiddenFieldOnFocus');
+ MochiKit.Signal.connect(this.getDom('scrambleLink'), 'onclick', this, 'toggleScramble');
+ }
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'updateEditMode': function() {
+ var inputElement;
+ var scarmbledStatus;
+
+ scrambledStatus = this.scrambledStatus() || 'SCRAMBLED';
+
+ this.element().update("");
+ switch(this.recordField().type()) {
+ case 'TXT':
+ case 'URL':
+ case 'ADDR':
+ inputElement = Clipperz.YUI.DomHelper.append(this.element().dom, {tag:'input', type:'text', value:"this.value()"}, true);
+ inputElement.dom.value = this.value();
+ break;
+ case 'PWD':
+ Clipperz.YUI.DomHelper.append(this.element().dom, {tag:'table', width:'100%', cellpadding:'0', cellspacing:'0', children:[
+ {tag:'tbody', children:[
+ {tag:'tr', children:[
+ {tag:'td', valign:'top', children:[
+ {tag:'input', type:((scrambledStatus == 'SCRAMBLED') ? 'password' : 'text'), id:this.getId('passwordInputElement'), value:"this.value()"},
+ {tag:'a', cls:'scrambleLink', id:this.getId('scrambleLink'), href:'#', html:(scrambledStatus == 'SCRAMBLED' ? Clipperz.PM.Strings['recordDetailPasswordFieldUnscrambleLabel'] : Clipperz.PM.Strings['recordDetailPasswordFieldScrambleLabel'])}
+ ]},
+ {tag:'td', valign:'top', children:[
+ {tag:'div', id:this.getId('passwordGenerator'), cls:'Clipperz_PasswordGenerator_button', html:'&nbsp;'}
+ ]}
+ ]}
+ ]}
+ ]})
+ inputElement = this.getElement('passwordInputElement');
+ inputElement.dom.value = this.value();
+ new Clipperz.PM.Components.PasswordEntropyDisplay(this.getElement('passwordInputElement'));
+ new Clipperz.PM.Components.PasswordGenerator(this.getElement('passwordGenerator'), this);
+ MochiKit.Signal.connect(this.getDom('scrambleLink'), 'onclick', this, 'toggleScramble');
+ break;
+// case 'NOTE':
+// inputElement = Clipperz.YUI.DomHelper.append(this.element().dom, {tag:'textarea', rows:'5', html:this.value()}, true);
+// break
+ case 'DATE':
+ inputElement = Clipperz.YUI.DomHelper.append(this.element().dom, {tag:'input', type:'text', value:"this.value()"}, true);
+ inputElement.dom.value = this.value();
+ break;
+ }
+
+ this.setInputElement(inputElement);
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'synchronizeComponentValues': function() {
+//MochiKit.Logging.logDebug(">>> FieldValueComponent.synchronizeComponentValues");
+ if (this.inputElement() != null) {
+ var value;
+
+ switch(this.recordField().type()) {
+ case 'TXT':
+ case 'URL':
+ case 'ADDR':
+ case 'PWD':
+ case 'DATE':
+ value = this.inputElement().dom.value;
+ break;
+ }
+ this.setValue(value);
+ }
+//MochiKit.Logging.logDebug("<<< FieldValueComponent.synchronizeComponentValues");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'selectHiddenFieldOnFocus': function(anEvent) {
+ anEvent.src().select();
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'toggleScramble': function(anEvent) {
+ this.synchronizeComponentValues();
+
+ if (this.scrambledStatus() == 'SCRAMBLED') {
+ this.setScrambledStatus('UNSCRAMBLED');
+ } else {
+ this.setScrambledStatus('SCRAMBLED');
+ };
+
+ this.update();
+ },
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+});
+
diff --git a/frontend/beta/js/Clipperz/PM/Components/RecordDetail/HeaderComponent.js b/frontend/beta/js/Clipperz/PM/Components/RecordDetail/HeaderComponent.js
new file mode 100644
index 0000000..7aaca3e
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Components/RecordDetail/HeaderComponent.js
@@ -0,0 +1,165 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
+if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
+if (typeof(Clipperz.PM.Components) == 'undefined') { Clipperz.PM.Components = {}; }
+if (typeof(Clipperz.PM.Components.RecordDetail) == 'undefined') { Clipperz.PM.Components.RecordDetail = {}; }
+
+//#############################################################################
+
+Clipperz.PM.Components.RecordDetail.HeaderComponent = function(anElement, args) {
+ args = args || {};
+
+ Clipperz.PM.Components.RecordDetail.HeaderComponent.superclass.constructor.call(this, anElement, args);
+ this.mainComponent().addEditComponent(this);
+
+ this._saveButton = null;
+
+ this.render();
+
+ return this;
+}
+
+//=============================================================================
+
+YAHOO.extendX(Clipperz.PM.Components.RecordDetail.HeaderComponent, Clipperz.PM.Components.RecordDetail.AbstractComponent, {
+
+ 'toString': function() {
+ return "Clipperz.PM.Components.RecordDetail.HeaderComponent component";
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'render': function() {
+ var editButton;
+
+//MochiKit.Logging.logDebug(">>> RecordDetail.HeaderComponent.appendTo");
+ Clipperz.YUI.DomHelper.append(this.element().dom, {tag:'div', cls:'recordDetailButtonsBox', children:[
+ {tag:'div', id:this.getId('editButtonBox'), children:[
+ {tag:'table', cls:'recordDetailButtonsTABLE', border:'0', cellpadding:'0', cellspacing:'0', children:[
+ {tag:'tbody', children:[
+ {tag:'tr', children:[
+ {tag:'td', align:'center', children:[
+ {tag:'div', id:this.getId('editButton')}
+ ]}
+ ]}
+ ]}
+ ]}
+ ]},
+ {tag:'div', id:this.getId('saveCancelButtonBox'), children:[
+ {tag:'table', cls:'recordDetailButtonsTABLE', border:'0', cellpadding:'0', cellspacing:'0', children:[
+ {tag:'tbody', children:[
+ {tag:'tr', children:[
+ {tag:'td', width:'49%', align:'right', children:[
+ {tag:'div', id:this.getId('saveButton')}
+ ]},
+ {tag:'td', html:'&nbsp'},
+ {tag:'td', width:'49%', align:'left', children:[
+ {tag:'div', id:this.getId('cancelButton')}
+ ]}
+ ]}
+ ]}
+ ]}
+ ]}
+ ]});
+
+ this.getElement('editButtonBox').setVisibilityMode(YAHOO.ext.Element.DISPLAY);
+ this.getElement('saveCancelButtonBox').setVisibilityMode(YAHOO.ext.Element.DISPLAY);
+
+ editButton = new YAHOO.ext.Button(this.getDom('editButton'), {text:Clipperz.PM.Strings['recordDetailEditButtonLabel'], handler:this.editButtonHandler, scope:this});
+ this.setSaveButton(new YAHOO.ext.Button(this.getDom('saveButton'), {text:Clipperz.PM.Strings['recordDetailSaveButtonLabel'], handler:this.saveButtonHandler, scope:this}));
+ new YAHOO.ext.Button(this.getDom('cancelButton'), {text:Clipperz.PM.Strings['recordDetailCancelButtonLabel'], handler:this.cancelButtonHandler, scope:this});
+
+ if (Clipperz.PM.Proxy.defaultProxy.isReadOnly()) {
+ editButton.disable();
+ }
+
+ this.update();
+//MochiKit.Logging.logDebug("<<< RecordDetail.HeaderComponent.appendTo");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'updateViewMode': function() {
+//MochiKit.Logging.logDebug(">>> HeaderComponent.updateViewMode");
+ this.getElement('editButtonBox').show();
+ this.getElement('saveCancelButtonBox').hide();
+//MochiKit.Logging.logDebug("<<< HeaderComponent.updateViewMode");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'updateEditMode': function() {
+ this.getElement('editButtonBox').hide();
+ this.getElement('saveCancelButtonBox').show();
+ if (this.mainComponent().enableSaveButton() == true) {
+//MochiKit.Logging.logDebug("--- HeaderComponent.updateViewMode - ENABLE");
+ this.saveButton().enable();
+ } else {
+ this.saveButton().disable();
+ }
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'saveButton': function() {
+ return this._saveButton;
+ },
+
+ 'setSaveButton': function(aValue) {
+ this._saveButton = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'editButtonHandler': function(anEvent) {
+ this.mainComponent().setEditMode('EDIT');
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'saveButtonHandler': function(anEvent) {
+//MochiKit.Logging.logDebug(">>> RecordDetail.HeaderComponent.saveButtonHandler");
+ this.mainComponent().setEditMode('VIEW', this.getElement('saveButton'));
+//MochiKit.Logging.logDebug("<<< RecordDetail.HeaderComponent.saveButtonHandler");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'cancelButtonHandler': function(anEvent) {
+ this.record().cancelChanges();
+//MochiKit.Logging.logDebug("--- HeaderComponent.cancelButtonHandler - " + Clipperz.Base.serializeJSON(this.record().currentDataSnapshot()));
+ this.mainComponent().setEditMode('VIEW', null, true);
+ },
+
+ //-------------------------------------------------------------------------
+
+ __syntaxFix__: "syntax fix"
+});
+
diff --git a/frontend/beta/js/Clipperz/PM/Components/RecordDetail/MainComponent.js b/frontend/beta/js/Clipperz/PM/Components/RecordDetail/MainComponent.js
new file mode 100644
index 0000000..53bf9c5
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Components/RecordDetail/MainComponent.js
@@ -0,0 +1,758 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
+if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
+if (typeof(Clipperz.PM.Components) == 'undefined') { Clipperz.PM.Components = {}; }
+if (typeof(Clipperz.PM.Components.RecordDetail) == 'undefined') { Clipperz.PM.Components.RecordDetail = {}; }
+
+//#############################################################################
+
+Clipperz.PM.Components.RecordDetail.MainComponent = function(anElement, args) {
+ args = args || {};
+
+ Clipperz.PM.Components.RecordDetail.MainComponent.superclass.constructor.call(this, anElement, args);
+
+// this._element = args.element;
+ this._user = args.user;
+ this._editMode = args.editMode || 'VIEW'; // [ 'VIEW' | 'EDIT' ]
+ this._mainPanel = args.mainPanel;
+
+ this._record = null;
+ this._editComponents = [];
+ this._addFieldButton = null;
+
+ this._enableSaveButton = true;
+ this._shouldShowLoginInfo = (Clipperz.PM.Proxy.defaultProxy.isReadOnly() ? false : true);
+
+// this._mainLayoutManager = null;
+// this._layoutRegion = null;
+
+ Clipperz.NotificationCenter.register(null, 'loadingRecordData', this, 'render');
+ Clipperz.NotificationCenter.register(null, 'decryptingRecordData', this, 'render');
+ Clipperz.NotificationCenter.register(null, 'loadingRecordVersionData', this, 'render');
+ Clipperz.NotificationCenter.register(null, 'decryptingRecordVersionData', this, 'render');
+ Clipperz.NotificationCenter.register(null, 'setupDone', this, 'render');
+ Clipperz.NotificationCenter.register(null, 'switchLanguage', this, 'render');
+
+ this.render();
+
+ return this;
+}
+
+//=============================================================================
+
+YAHOO.extendX(Clipperz.PM.Components.RecordDetail.MainComponent, Clipperz.PM.Components.BaseComponent, {
+
+ 'toString': function() {
+ return "Clipperz.PM.Components.RecordDetail.MainComponent component";
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'editMode': function() {
+ return this._editMode;
+ },
+
+ 'setEditMode': function(aValue, aButtonElement, shouldSkipComponentSynchronization) {
+//MochiKit.Logging.logDebug(">>> MainComponent.setEditingMode");
+ this.scrollToTop();
+
+ if (aValue == 'VIEW') {
+ if (shouldSkipComponentSynchronization == true) {
+ this.exitModalView();
+ } else {
+ this.synchronizeComponentValues();
+ if (this.record().hasPendingChanges()) {
+ if (this.record().isBrandNew()) {
+ this.record().removeEmptyFields();
+ }
+ this.saveCurrentRecordChanges(aButtonElement);
+ } else {
+ if (this.record().isBrandNew()) {
+ this.record().user().removeRecord(this.record());
+ }
+ this.exitModalView();
+ }
+ }
+ } else if (aValue == 'EDIT') {
+ this.enterModalView();
+ } else {
+ // ????
+ }
+
+ this._editMode = aValue;
+ this.render();
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'user': function() {
+ return this._user;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'mainPanel': function() {
+ return this._mainPanel;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'render': function() {
+//MochiKit.Logging.logDebug(">>> RecordDetail.MainComponent.render");
+ this.setEnableSaveButton(true);
+ this.element().update("");
+
+ if (this.record() == null) {
+ if (MochiKit.Base.keys(this.user().records()).length == 0) {
+ this.renderWithNoRecordAtAll();
+ } else {
+ this.renderWithNoSelectedRecord();
+ }
+ } else {
+ this.renderWithSelectedRecord();
+ }
+//MochiKit.Logging.logDebug("<<< RecordDetail.MainComponent.render");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'renderWithNoRecordAtAll': function() {
+//MochiKit.Logging.logDebug(">>> RecordDetail.MainComponent.renderWithNoRecordAtAll");
+ Clipperz.YUI.DomHelper.append(this.element().dom,
+ {tag:'form', cls:'noRecordAtAllFORM', children:[
+ {tag:'div', cls:'recordTitleBlock', children:[
+ {tag:'h2', id:'recordTitle', htmlString:Clipperz.PM.Strings['recordDetailNoRecordAtAllTitle']}
+ ]},
+ {tag:'table', border:'0', cellspacing:'0', cellpadding:'0', children:[
+ {tag:'tbody', children:[
+ {tag:'tr', children:[
+ {tag:'td', colspan:'5', children:[
+ {tag:'div', cls:'recordDetailDescriptionBox', htmlString:Clipperz.PM.Strings['recordDetailNoRecordAtAllDescription']}
+ ]}
+ ]}
+ ]}
+ ]}
+ ]}
+ );
+//MochiKit.Logging.logDebug("<<< RecordDetail.MainComponent.renderWithNoRecordAtAll");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'renderWithNoSelectedRecord': function() {
+//MochiKit.Logging.logDebug(">>> RecordDetail.MainComponent.renderWithNoSelectedRecord");
+ Clipperz.YUI.DomHelper.append(this.element().dom,
+ {tag:'form', cls:'noRecordSelectedFORM', children:[
+ {tag:'div', cls:'recordTitleBlock', children:[
+ {tag:'h2', id:'recordTitle', htmlString:Clipperz.PM.Strings['recordDetailNoRecordSelectedTitle']}
+ ]},
+ {tag:'table', border:'0', cellspacing:'0', cellpadding:'0', children:[
+ {tag:'tbody', children:[
+ {tag:'tr', children:[
+ {tag:'td', colspan:'5', children:[
+ {tag:'div', cls:'recordDetailDescriptionBox', htmlString:Clipperz.PM.Strings['recordDetailNoRecordSelectedDescription']}
+ ]}
+ ]},
+ {tag:'tr', colspan:'5', children:[
+ {tag:'td', colspan:'5', children:this.loginInfo()}
+ ]}
+ ]}
+ ]}
+ ]}
+ );
+//MochiKit.Logging.logDebug("--- RecordDetail.MainComponent.renderWithNoSelectedRecord - 1");
+
+ if (MochiKit.DOM.getElement('fullLoginHistoryLink') != null) {
+ MochiKit.Signal.connect('fullLoginHistoryLink', 'onclick', this, 'showLoginHistoryPanel');
+ }
+//MochiKit.Logging.logDebug("--- RecordDetail.MainComponent.renderWithNoSelectedRecord - 2");
+
+ if (MochiKit.DOM.getElement('offlineCopyDownloadWarningLink') != null) {
+ MochiKit.Signal.connect('offlineCopyDownloadWarningLink', 'onclick', this, 'showDownloadOfflineCopyPanel');
+ }
+//MochiKit.Logging.logDebug("<<< RecordDetail.MainComponent.renderWithNoSelectedRecord");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'renderWithSelectedRecord': function() {
+//MochiKit.Logging.logDebug(">>> RecordDetail.MainComponent.renderWithSelectedRecord");
+ if (this.record().shouldLoadData() === true) {
+// this.renderWithSelectedRecordLoading();
+//MochiKit.Logging.logDebug("--- RecordDetail.MainComponent.renderWithSelectedRecord - 1.1");
+ this.renderWhileProcessingWithMessage(Clipperz.PM.Strings['recordDetailLoadingRecordMessage']);
+//MochiKit.Logging.logDebug("--- RecordDetail.MainComponent.renderWithSelectedRecord - 1.2");
+ } else if (this.record().shouldDecryptData() === true) {
+// this.renderWithSelectedRecordDecrypting();
+//MochiKit.Logging.logDebug("--- RecordDetail.MainComponent.renderWithSelectedRecord - 2.1");
+ this.renderWhileProcessingWithMessage(Clipperz.PM.Strings['recordDetailDecryptingRecordMessage']);
+//MochiKit.Logging.logDebug("--- RecordDetail.MainComponent.renderWithSelectedRecord - 2.2");
+ } else if (this.record().currentVersion().shouldLoadData() === true) {
+//MochiKit.Logging.logDebug("--- RecordDetail.MainComponent.renderWithSelectedRecord - 3.1");
+ this.renderWhileProcessingWithMessage(Clipperz.PM.Strings['recordDetailLoadingRecordVersionMessage']);
+//MochiKit.Logging.logDebug("--- RecordDetail.MainComponent.renderWithSelectedRecord - 3.2");
+ } else if (this.record().currentVersion().shouldDecryptData() === true) {
+// this.renderWithSelectedRecordCurrentVersionDecrypting();
+//MochiKit.Logging.logDebug("--- RecordDetail.MainComponent.renderWithSelectedRecord - 4.1");
+ this.renderWhileProcessingWithMessage(Clipperz.PM.Strings['recordDetailDecryptingRecordVersionMessage']);
+//MochiKit.Logging.logDebug("--- RecordDetail.MainComponent.renderWithSelectedRecord - 4.2");
+ } else {
+//MochiKit.Logging.logDebug("--- RecordDetail.MainComponent.renderWithSelectedRecord - 5.1");
+ this.renderWithSelectedRecordData();
+//MochiKit.Logging.logDebug("--- RecordDetail.MainComponent.renderWithSelectedRecord - 5.2");
+ }
+//MochiKit.Logging.logDebug("<<< RecordDetail.MainComponent.renderWithSelectedRecord");
+ },
+
+ //.........................................................................
+
+ 'renderWhileProcessingWithMessage': function(aMessage) {
+//MochiKit.Logging.logDebug(">>> RecordDetail.MainComponent.renderWhileProcessingWithMessage");
+ Clipperz.YUI.DomHelper.append(this.element().dom,
+ {tag:'form', cls:'processingRecordFORM', children:[
+ {tag:'div', cls:'recordTitleBlock', children:[
+ {tag:'h2', id:'recordTitle', html:this.record().label()}
+ ]},
+ {tag:'table', border:'0', cellspacing:'0', cellpadding:'0', children:[
+ {tag:'tbody', children:[
+ {tag:'tr', cls:'recordTR', children:[
+ {tag:'td', colspan:'5', children:[
+ {tag:'div', cls:'recordDetailDescriptionBox', children:[
+ {tag:'h5', cls:'recordLoadingMessage', html:aMessage}
+ ]}
+ ]}
+ ]}
+ ]}
+ ]}
+ ]}
+ );
+//MochiKit.Logging.logDebug("<<< RecordDetail.MainComponent.renderWhileProcessingWithMessage");
+ },
+
+ //.........................................................................
+/*
+ 'renderWithSelectedRecordLoading': function() {
+ Clipperz.YUI.DomHelper.append(this.element().dom, {tag:'div', cls:'', style:'border:1px solid red; padding: 20px;', children:[
+ {tag:'div', cls:'Clipprez_RecordDetailTitle', children:[
+ {tag:'h3', html:this.record().label()},
+ {tag:'h3', html:"loading"}
+ ]}
+ ]});
+ },
+
+ //.........................................................................
+
+ 'renderWithSelectedRecordDecrypting': function() {
+ Clipperz.YUI.DomHelper.append(this.element().dom, {tag:'div', cls:'', style:'border:1px solid red; padding: 20px;', children:[
+ {tag:'div', cls:'Clipprez_RecordDetailTitle', children:[
+ {tag:'h3', html:this.record().label()},
+ {tag:'h3', html:"decrypting ... "}
+ ]}
+ ]});
+ },
+
+ //.........................................................................
+
+ 'renderWithSelectedRecordCurrentVersionDecrypting': function() {
+ Clipperz.YUI.DomHelper.append(this.element().dom, {tag:'div', cls:'', style:'border:1px solid red; padding: 20px;', children:[
+ {tag:'div', cls:'Clipprez_RecordDetailTitle', children:[
+ {tag:'h3', html:this.record().label()},
+ {tag:'h3', html:"decrypting version ... "}
+ ]}
+ ]});
+ },
+*/
+ //-------------------------------------------------------------------------
+
+ 'renderWithErrorMessage': function(anErrorMessage) {
+//MochiKit.Logging.logDebug(">>> RecordDetail.MainComponent.renderWithErrorMessage");
+ this.element().update("");
+
+//MochiKit.Logging.logDebug("--- RecordDetail.MainComponent.renderWithErrorMessage - 1");
+ Clipperz.YUI.DomHelper.append(this.element().dom,
+ {tag:'form', cls:'errorMessageFORM', children:[
+ {tag:'div', cls:'recordTitleBlock', children:[
+ {tag:'h2', id:'recordTitle', html:this.record().label()}
+ ]},
+ {tag:'table', border:'0', cellspacing:'0', cellpadding:'0', children:[
+ {tag:'tbody', children:[
+ {tag:'tr', cls:'recordTR', children:[
+ {tag:'td', colspan:'5', children:[
+ {tag:'div', cls:'recordDetailDescriptionBox loadingError', children:[
+ {tag:'h5', htmlString:Clipperz.PM.Strings['recordDetailLoadingErrorMessageTitle']},
+ {tag:'p', html:anErrorMessage.message}
+ ]}
+ ]}
+ ]}
+ ]}
+ ]}
+ ]}
+ );
+//MochiKit.Logging.logDebug("<<< RecordDetail.MainComponent.renderWithErrorMessage");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'renderWithSelectedRecordData': function() {
+ var columns;
+
+ this.resetEditComponents();
+
+ columns = [
+ {tag:'td', width:'25', html:'&#160'},
+ {tag:'td', width:'25%', htmlString:Clipperz.PM.Strings['recordDetailLabelFieldColumnLabel']},
+ {tag:'td', width:'3', html:'&#160'},
+ {tag:'td', /*width:'80%',*/ htmlString:Clipperz.PM.Strings['recordDetailDataFieldColumnLabel']}
+ ];
+
+ if (this.editMode() == 'EDIT') {
+ columns.push({tag:'td', /*width:'55',*/ htmlString:Clipperz.PM.Strings['recordDetailTypeFieldColumnLabel']})
+ }
+
+//MochiKit.Logging.logDebug(">>> RecordDetail.MainComponent.renderWithSelectedRecordData");
+ Clipperz.YUI.DomHelper.append(this.element().dom,
+ {tag:'form', cls:'recordDataFORM', children:[
+ {tag:'div', cls:'recordTitleBlock', id:this.getId('title')},
+ {tag:'div', id:'recordDetailDataBox', cls:'recordDetailDataBox', children:[
+
+{tag:'table', width:'100%', border:'0', cellspacing:'0', cellpadding:'0', children:[
+ {tag:'tbody', children:[
+ {tag:'tr', children:[
+ {tag:'td', width:'5', html:"&nbsp;"},
+ {tag:'td', children:[
+
+ {tag:'table', cls:'recordDetailDataBoxTABLE', border:'0', cellspacing:'0', cellpadding:'0', children:[
+ {tag:'tbody', id:this.getId('tbody'), children:[
+ {tag:'tr', /*cls:'recordNoteTR',*/ children:[
+ {tag:'td', colspan:'5', id:this.getId('notes')}
+ ]},
+ {tag:'tr', cls:'recordFieldsTR', children:columns /* [
+ {tag:'td', width:'25', html:'&#160'},
+ {tag:'td', width:'25%', htmlString:Clipperz.PM.Strings['recordDetailLabelFieldColumnLabel']},
+ {tag:'td', width:'3', html:'&#160'},
+ {tag:'td', / *width:'80%',* / htmlString:Clipperz.PM.Strings['recordDetailDataFieldColumnLabel']},
+ {tag:'td', / *width:'55',* / htmlString:Clipperz.PM.Strings['recordDetailTypeFieldColumnLabel']}
+ ] */ }
+ ]}
+ ]},
+ {tag:'div', cls:'addFieldButton', id:this.getId('addField'), children:[
+ {tag:'div', id:this.getId('addFieldButton')}
+ ]},
+ {tag:'div', id:this.getId('directLogins')},
+ {tag:'div', id:this.getId('footer')}
+
+ ]}
+ ]}
+ ]}
+]}
+
+ ]}
+ ]}
+ );
+
+//MochiKit.Logging.logDebug("--- RecordDetail.MainComponent.renderWithSelectedRecordData - 1");
+
+ new Clipperz.PM.Components.RecordDetail.TitleComponent(this.getElement('title'), {mainComponent:this});
+//MochiKit.Logging.logDebug("--- RecordDetail.MainComponent.renderWithSelectedRecordData - 2");
+ new Clipperz.PM.Components.RecordDetail.NotesComponent(this.getElement('notes'), {mainComponent:this});
+//MochiKit.Logging.logDebug("--- RecordDetail.MainComponent.renderWithSelectedRecordData - 3");
+ new Clipperz.PM.Components.RecordDetail.DirectLoginsComponent(this.getElement('directLogins'), {mainComponent:this});
+//MochiKit.Logging.logDebug("--- RecordDetail.MainComponent.renderWithSelectedRecordData - 4");
+ new Clipperz.PM.Components.RecordDetail.HeaderComponent(this.getElement('footer'), {mainComponent:this});
+//MochiKit.Logging.logDebug("--- RecordDetail.MainComponent.renderWithSelectedRecordData - 5");
+ MochiKit.Iter.forEach(MochiKit.Base.values(this.record().currentVersion().fields()), this.appendFieldComponent, this);
+//MochiKit.Logging.logDebug("--- RecordDetail.MainComponent.renderWithSelectedRecordData - 6");
+ this.setAddFieldButton(new YAHOO.ext.Button(this.getDom('addFieldButton'), {text:Clipperz.PM.Strings['recordDetailAddFieldButtonLabel'], handler:this.addNewRecordField, scope:this}));
+//MochiKit.Logging.logDebug("--- RecordDetail.MainComponent.renderWithSelectedRecordData - 7");
+
+ this.update();
+
+//MochiKit.Logging.logDebug("<<< RecordDetail.MainComponent.renderWithSelectedRecordData");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'editComponents': function() {
+ return this._editComponents;
+ },
+
+ 'resetEditComponents': function() {
+ this._editComponents = [];
+ },
+
+ 'addEditComponent': function(aValue) {
+ this.editComponents().push(aValue);
+ },
+
+ 'removeEditComponent': function(aValue) {
+ Clipperz.Base.removeFromArray(this.editComponents(), aValue);
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'record': function() {
+ return this._record;
+ },
+
+ 'setRecord': function(aValue) {
+ var result;
+
+//MochiKit.Logging.logDebug(">>> MainComponent.setRecord")
+ if (this._record != aValue) {
+ var deferredResult;
+
+ deferredResult = new MochiKit.Async.Deferred();
+
+ if ((this._record != null) && (this.editMode() == 'EDIT')) {
+ this.synchronizeComponentValues();
+ deferredResult.addCallback(MochiKit.Base.method(this._record, 'saveChanges'));
+ }
+
+ this._record = aValue;
+
+ if (aValue != null) {
+ this.setShouldShowLoginInfo(false);
+ deferredResult.addCallback(MochiKit.Base.method(this._record, 'deferredData'));
+ }
+ deferredResult.addCallbacks(
+ MochiKit.Base.method(this, 'render'),
+ MochiKit.Base.method(this, 'renderWithErrorMessage')
+ );
+ deferredResult.callback();
+ this.scrollToTop();
+
+ result = deferredResult;
+ } else {
+ result = MochiKit.Async.success();
+ }
+//MochiKit.Logging.logDebug("<<< MainComponent.setRecord")
+
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'saveCurrentRecordChanges': function(aButtonElement) {
+ var deferred;
+ var currentNumberOfRecords;
+
+ deferred = new MochiKit.Async.Deferred();
+ deferred.addCallback(MochiKit.Base.method(Clipperz.PM.Components.MessageBox(), 'deferredShow'),
+ {
+ title:Clipperz.PM.Strings['recordDetailSavingChangesMessagePanelInitialTitle'],
+ text:Clipperz.PM.Strings['recordDetailSavingChangesMessagePanelInitialText'],
+ width:240,
+ showProgressBar:true,
+ showCloseButton:false,
+ steps:6
+ },
+ aButtonElement.dom
+ );
+ deferred.addCallback(MochiKit.Base.method(this, 'exitModalView'));
+ deferred.addCallback(MochiKit.Base.method(this.record(), 'saveChanges'));
+ deferred.addCallback(Clipperz.NotificationCenter.deferredNotification, this.record(), 'recordUpdated');
+ deferred.addCallback(function(res) {
+ Clipperz.PM.Components.MessageBox().hide(YAHOO.ext.Element.get('main'));
+ return res;
+ });
+
+ currentNumberOfRecords = MochiKit.Base.keys(this.user().records()).length;
+ if ((this.record().isBrandNew()) && (this.user().preferences().shouldShowDonationPanel()) && (currentNumberOfRecords >= 5)) {
+ deferred.addCallback(Clipperz.PM.showDonationSplashScreen, this.user(), 'recordListAddRecordButton');
+ }
+
+ deferred.callback();
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'update': function(anEvent) {
+ if (this.editMode() == 'EDIT') {
+ this.updateEditMode();
+ } else if (this.editMode() == 'VIEW') {
+ this.updateViewMode();
+ }
+
+ MochiKit.Iter.forEach(this.editComponents(), MochiKit.Base.methodcaller('update'));
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'updateViewMode': function() {
+ this.addFieldButton().hide();
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'updateEditMode': function() {
+ this.addFieldButton().show();
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'appendFieldComponent': function(aRecordField) {
+//MochiKit.Logging.logDebug(">>> MainComponent.appendFieldComponent");
+ new Clipperz.PM.Components.RecordDetail.FieldComponent(
+ Clipperz.YUI.DomHelper.append(this.getDom('tbody'), {tag:'tr'}, true),
+ {recordField:aRecordField, mainComponent:this}
+ );
+//MochiKit.Logging.logDebug("<<< MainComponent.appendFieldComponent");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'removeField': function(aFieldComponent) {
+ var recordField;
+
+//MochiKit.Logging.logDebug(">>> MainComponent.removeField")
+ recordField = aFieldComponent.recordField();
+ this.removeEditComponent(aFieldComponent);
+ aFieldComponent.destroy();
+ this.record().removeField(recordField);
+
+ Clipperz.NotificationCenter.notify(this.record(), 'removedField');
+//MochiKit.Logging.logDebug("<<< MainComponent.removeField")
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'synchronizeComponentValues': function() {
+ MochiKit.Iter.forEach(this.editComponents(), MochiKit.Base.methodcaller('synchronizeComponentValues'));
+ },
+
+ //=========================================================================
+
+ 'addFieldButton': function() {
+ return this._addFieldButton;
+ },
+
+ 'setAddFieldButton': function(aValue) {
+ this._addFieldButton = aValue;
+ },
+
+ 'addNewRecordField': function() {
+ var newField;
+
+ newField = this.record().addNewField();
+ this.appendFieldComponent(newField);
+
+ Clipperz.NotificationCenter.notify(this.record(), 'addNewRecordField');
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'enterModalView': function() {
+/*
+ if (this.user().preferences().useSafeEditMode()) {
+ var headerMaskElement;
+ var verticalMaskElement;
+
+ headerMaskElement = YAHOO.ext.Element.get('recordDetailEditModeHeaderMask');
+ headerMaskElement.show().mask();
+
+ verticalMaskElement = YAHOO.ext.Element.get('recordDetailEditModeVerticalMask');
+ verticalMaskElement.show().mask();
+ }
+*/
+ this.mainPanel().enterModalView();
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'exitModalView': function() {
+/*
+ if (this.user().preferences().useSafeEditMode()) {
+ var headerMaskElement;
+ var verticalMaskElement;
+
+ headerMaskElement = YAHOO.ext.Element.get('recordDetailEditModeHeaderMask');
+ headerMaskElement.unmask();
+ headerMaskElement.hide();
+
+ verticalMaskElement = YAHOO.ext.Element.get('recordDetailEditModeVerticalMask');
+ verticalMaskElement.unmask();
+ verticalMaskElement.hide();
+ }
+*/
+ this.mainPanel().exitModalView();
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'enableSaveButton': function() {
+ return this._enableSaveButton;
+ },
+
+ 'setEnableSaveButton': function(aValue) {
+ this._enableSaveButton = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'scrollToTop': function() {
+ YAHOO.ext.Element.get('recordTitleTopBlock').scrollIntoView(document.body);
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'loginInfo': function() {
+ var result;
+
+ if (this.shouldShowLoginInfo() == true) {
+// && (typeof(this.user().loginInfo()['latest']) != 'undefined')) {
+ var imageExtension;
+ var currentConnectionText;
+ var currentIP;
+ var contentChildren;
+
+ result = [];
+ contentChildren = [];
+
+ imageExtension = (Clipperz_IEisBroken == true) ? 'gif': 'png';
+
+ contentChildren.push({tag:'h4', valign:'top', htmlString:Clipperz.PM.Strings['WELCOME_BACK']});
+
+ currentIP = (this.user().loginInfo()['current']['ip'].match(/^\d{1,3}(.\d{1,3}){3}$/)) ? this.user().loginInfo()['current']['ip'] : Clipperz.PM.Strings['unknown_ip'];
+ currentConnectionText = Clipperz.PM.Strings['currentConnectionText'];
+ currentConnectionText = currentConnectionText.replace(/__ip__/, "<b>" + Clipperz.Base.sanitizeString(this.user().loginInfo()['current']['ip']) + "</b>");
+ currentConnectionText = currentConnectionText.replace(/__country__/, "<b>" + Clipperz.PM.Strings['countries'][Clipperz.Base.sanitizeString(this.user().loginInfo()['current']['country'])] + "</b>");
+ currentConnectionText = currentConnectionText.replace(/__browser__/, "<b>" + Clipperz.PM.Strings['browsers'][Clipperz.Base.sanitizeString(this.user().loginInfo()['current']['browser'])] + "</b>");
+ currentConnectionText = currentConnectionText.replace(/__operatingSystem__/, "<b>" + Clipperz.PM.Strings['operatingSystems'][Clipperz.Base.sanitizeString(this.user().loginInfo()['current']['operatingSystem'])] + "</b>");
+
+ contentChildren.push(
+ {tag:'div', cls:'loginInfo_now', children:[
+ {tag:'div', cls:'text', htmlString:currentConnectionText},
+ {tag:'div', cls:'icons', children:[
+ {tag:'img', title:Clipperz.PM.Strings['countries'][Clipperz.Base.sanitizeString(this.user().loginInfo()['current']['country'])], cls:'flag', src:Clipperz.PM.Strings['icons_baseUrl'] + "/flags/" + Clipperz.Base.sanitizeString(this.user().loginInfo()['current']['country']).toLowerCase() + "." + imageExtension, width:'32', height:'32'},
+ {tag:'img', title:Clipperz.PM.Strings['browsers'][Clipperz.Base.sanitizeString(this.user().loginInfo()['current']['browser'])], src:Clipperz.PM.Strings['icons_baseUrl'] + "/browsers/" + Clipperz.Base.sanitizeString(this.user().loginInfo()['current']['browser']).toLowerCase() + "." + imageExtension, width:'32', height:'32'},
+ {tag:'img', title:Clipperz.PM.Strings['operatingSystems'][Clipperz.Base.sanitizeString(this.user().loginInfo()['current']['operatingSystem'])], src:Clipperz.PM.Strings['icons_baseUrl'] + "/operatingSystems/" + Clipperz.Base.sanitizeString(this.user().loginInfo()['current']['operatingSystem']).toLowerCase() + "." + imageExtension, width:'32', height:'32'}
+ ]}
+ ]}
+ );
+
+ if (typeof(this.user().loginInfo()['latest']) != 'undefined') {
+ var latestLoginDate;
+ var elapsedTimeDescription;
+ var latestIP;
+ var latestConnectionText;
+
+ latestLoginDate = Clipperz.PM.Date.parseDateWithUTCFormat(Clipperz.Base.sanitizeString(this.user().loginInfo()['latest']['date']));
+
+ elapsedTimeDescription = Clipperz.PM.Date.getElapsedTimeDescription(latestLoginDate);
+ latestIP = (this.user().loginInfo()['latest']['ip'].match(/^\d{1,3}(.\d{1,3}){3}$/)) ? this.user().loginInfo()['latest']['ip'] : Clipperz.PM.Strings['unknown_ip'];
+
+ latestConnectionText = Clipperz.PM.Strings['latestConnectionText'];
+ latestConnectionText = latestConnectionText.replace(/__elapsedTimeDescription__/, "<b>" + elapsedTimeDescription + "</b>");
+ latestConnectionText = latestConnectionText.replace(/__time__/, Clipperz.PM.Date.formatDateWithTemplate(latestLoginDate, Clipperz.PM.Strings['fullDate_format']));
+ latestConnectionText = latestConnectionText.replace(/__ip__/, "<b>" + Clipperz.Base.sanitizeString(this.user().loginInfo()['latest']['ip']) + "</b>");
+ latestConnectionText = latestConnectionText.replace(/__country__/, "<b>" + Clipperz.PM.Strings['countries'][Clipperz.Base.sanitizeString(this.user().loginInfo()['latest']['country'])] + "</b>");
+ latestConnectionText = latestConnectionText.replace(/__browser__/, "<b>" + Clipperz.PM.Strings['browsers'][Clipperz.Base.sanitizeString(this.user().loginInfo()['latest']['browser'])] + "</b>");
+ latestConnectionText = latestConnectionText.replace(/__operatingSystem__/, "<b>" + Clipperz.PM.Strings['operatingSystems'][Clipperz.Base.sanitizeString(this.user().loginInfo()['latest']['operatingSystem'])] + "</b>");
+
+
+ contentChildren.push(
+ {tag:'div', cls:'loginInfo_latest', children:[
+ {tag:'div', cls:'inner_header', html:'&nbsp;'},
+ {tag:'div', cls:'content', children:[
+ {tag:'div', cls:'text', htmlString:latestConnectionText},
+ {tag:'div', cls:'icons', children:[
+ {tag:'img', title:Clipperz.PM.Strings['countries'][Clipperz.Base.sanitizeString(this.user().loginInfo()['latest']['country'])], cls:'flag', src:Clipperz.PM.Strings['icons_baseUrl'] + "/flags/" + Clipperz.Base.sanitizeString(this.user().loginInfo()['latest']['country']).toLowerCase() + "." + imageExtension, width:'32', height:'32'},
+ {tag:'img', title:Clipperz.PM.Strings['browsers'][Clipperz.Base.sanitizeString(this.user().loginInfo()['latest']['browser'])], src:Clipperz.PM.Strings['icons_baseUrl'] + "/browsers/" + Clipperz.Base.sanitizeString(this.user().loginInfo()['latest']['browser']).toLowerCase() + "." + imageExtension, width:'32', height:'32'},
+ {tag:'img', title:Clipperz.PM.Strings['operatingSystems'][Clipperz.Base.sanitizeString(this.user().loginInfo()['latest']['operatingSystem'])], src:Clipperz.PM.Strings['icons_baseUrl'] + "/operatingSystems/" + Clipperz.Base.sanitizeString(this.user().loginInfo()['latest']['operatingSystem']).toLowerCase() + "." + imageExtension, width:'32', height:'32'}
+ ]}
+ ]},
+ {tag:'div', children:[
+ {tag:'a', href:'#', id:'fullLoginHistoryLink', htmlString:Clipperz.PM.Strings['fullLoginHistoryLinkLabel']}
+ ]},
+ {tag:'div', cls:'inner_footer', html:'&nbsp;'}
+ ]}
+ );
+ }
+
+ contentChildren.push(
+ {tag:'table', id:'shouldDownloadOfflineCopyWarningBox', children:[
+ {tag:'tbody', width:'100%', children:[
+ {tag:'tr', children:[
+ {tag:'td', cls:'offlineCopyDownloadWarningIconTD', valign:'top', align:'center', width:'50', children:(this.user().shouldDownloadOfflineCopy() ? [{tag:'img', src:Clipperz.PM.Strings['icons_baseUrl'] + "/misc/offlineCopyWarning.png" , width:'32', height:'32'}]: [])},
+ {tag:'td', children:[
+ {tag:'div', cls:'offlineCopyDownloadWarning', htmlString:(this.user().shouldDownloadOfflineCopy() ? Clipperz.PM.Strings['offlineCopyDownloadWarning']: Clipperz.PM.Strings['offlineCopyDownloadOk'])}
+ ]}
+ ]}
+ ]}
+ ]}
+ );
+
+
+ result = [{tag:'div', id:'loginInfoWrapper', children:[{tag:'div', id:'loginInfo', children:[
+ {tag:'div', cls:'header', html:'&nbsp;'},
+ {tag:'div', cls:'content', children:contentChildren},
+ {tag:'div', cls:'footer', html:'&nbsp;'}
+ ]}]}];
+
+// this.setShouldShowLoginInfo(false);
+ } else {
+ resut = [];
+ }
+
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'shouldShowLoginInfo': function() {
+ return this._shouldShowLoginInfo;
+ },
+
+ 'setShouldShowLoginInfo': function(aValue) {
+ this._shouldShowLoginInfo = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'showLoginHistoryPanel': function(anEvent) {
+ anEvent.stop();
+
+ Clipperz.NotificationCenter.notify(this, 'selectTab', 'mainTabPanel.accountTab', true);
+ Clipperz.NotificationCenter.notify(this, 'selectTab', 'accountTabPanel.loginHistoryTab', true);
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'showDownloadOfflineCopyPanel': function(anEvent) {
+ anEvent.stop();
+
+ Clipperz.NotificationCenter.notify(this, 'selectTab', 'mainTabPanel.dataTab', true);
+ Clipperz.NotificationCenter.notify(this, 'selectTab', 'dataTabPanel.offlineCopyTab', true);
+ },
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+});
+
diff --git a/frontend/beta/js/Clipperz/PM/Components/RecordDetail/NotesComponent.js b/frontend/beta/js/Clipperz/PM/Components/RecordDetail/NotesComponent.js
new file mode 100644
index 0000000..6f454fc
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Components/RecordDetail/NotesComponent.js
@@ -0,0 +1,240 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
+if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
+if (typeof(Clipperz.PM.Components) == 'undefined') { Clipperz.PM.Components = {}; }
+if (typeof(Clipperz.PM.Components.RecordDetail) == 'undefined') { Clipperz.PM.Components.RecordDetail = {}; }
+
+//#############################################################################
+
+
+
+Clipperz.PM.Components.RecordDetail.NotesComponent = function(anElement, args) {
+//MochiKit.Logging.logDebug(">>> new NotesComponent");
+ args = args || {};
+
+ Clipperz.PM.Components.RecordDetail.NotesComponent.superclass.constructor.call(this, anElement, args);
+
+ this.mainComponent().addEditComponent(this);
+
+ this._staticOffset = null;
+ this._componentHeight = 50;
+ this._mouseMoveIdentifier = null;
+ this._mouseUpIdentifier = null;
+
+ this.element().setVisibilityMode(YAHOO.ext.Element.DISPLAY);
+
+ this.render();
+//MochiKit.Logging.logDebug("<<< new NotesComponent");
+
+ return this;
+}
+
+//=============================================================================
+
+YAHOO.extendX(Clipperz.PM.Components.RecordDetail.NotesComponent, Clipperz.PM.Components.RecordDetail.AbstractComponent, {
+
+ 'toString': function() {
+ return "Clipperz.PM.Components.RecordDetail.NotesComponent component";
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'value': function() {
+ return this.record().notes();
+ },
+
+ 'setValue': function(aValue) {
+ this.record().setNotes(aValue);
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'render': function() {
+//MochiKit.Logging.logDebug(">>> NotesComponent.render");
+/*
+ Clipperz.YUI.DomHelper.append(this.element().dom, {tag:'td', colspan:'5', children:[
+ {tag:'span', cls:'noteFieldLabel', htmlString:Clipperz.PM.Strings['recordDetailNotesLabel']},
+ {tag:'div', cls:'noteFieldContent', id:this.getId('notes')}
+ ]});
+*/
+ Clipperz.YUI.DomHelper.append(this.element().dom, {tag:'span', cls:'noteFieldLabel', htmlString:Clipperz.PM.Strings['recordDetailNotesLabel']});
+ Clipperz.YUI.DomHelper.append(this.element().dom, {tag:'div', cls:'noteFieldContent', id:this.getId('notes'), children:[
+ {tag:'div', id:this.getId('resizableDiv'), cls:'resizable-textarea', children:[
+ {tag:'div', id:this.getId('contentView'), cls:'viewMode', html:""},
+ {tag:'div', id:this.getId('contentEdit'), children:[
+ {tag:'span', children:[
+ {tag:'textarea', id:this.getId('textarea'), html:""}
+ ]}
+ ]},
+ {tag:'div', id:this.getId('grippie'), cls:'grippie'}
+ ]}
+ ]});
+
+ this.getElement('contentView').setVisibilityMode(YAHOO.ext.Element.DISPLAY);
+ this.getElement('contentEdit').setVisibilityMode(YAHOO.ext.Element.DISPLAY);
+
+ MochiKit.Signal.connect(this.getId('grippie'), 'onmousedown', this, 'startResize');
+
+ this.update();
+//MochiKit.Logging.logDebug("<<< NotesComponent.render");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'updateViewMode': function() {
+//MochiKit.Logging.logDebug(">>> NotesComponent.updateViewMode");
+// this.getElement('notes').update(this.value().replace(/\n/g, '<br>'));
+
+ this.getElement('contentView').update(Clipperz.Base.sanitizeString(this.value()).replace(/\n/g, '<br>'));
+
+ if (this.isNoteEmpty()) {
+ this.element().hide();
+ } else {
+ this.getElement('contentView').show();
+ this.getElement('contentView').setHeight(this.componentHeight());
+ }
+ this.getElement('contentEdit').hide();
+
+//MochiKit.Logging.logDebug("<<< NotesComponent.updateViewMode");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'updateEditMode': function() {
+//MochiKit.Logging.logDebug(">>> NotesComponent.updateEditMode");
+ this.getDom('textarea').value = this.value().replace(/\n/g, Clipperz_normalizedNewLine);
+
+ this.getElement('contentView').hide();
+ this.getElement('contentEdit').show();
+
+ this.getElement('textarea').setHeight(this.componentHeight());
+//MochiKit.Logging.logDebug("<<< NotesComponent.updateEditMode");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'synchronizeComponentValues': function() {
+//MochiKit.Logging.logDebug(">>> NotesComponent.synchronizeComponentValues");
+ if (this.getElement('textarea') != null) {
+ this.setValue(this.getDom('textarea').value.replace(/(\x0a\x0d|\x0d\x0a)/g,'\n'));
+ }
+//MochiKit.Logging.logDebug("<<< NotesComponent.synchronizeComponentValues");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'componentHeight': function() {
+ return this._componentHeight;
+ },
+
+ 'setComponentHeight': function(aValue) {
+ this._componentHeight = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'isNoteEmpty': function() {
+ return !/[^ \n]/.test(this.value());
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'staticOffset': function() {
+ return this._staticOffset;
+ },
+
+ 'setStaticOffset': function(aValue) {
+ this._staticOffset = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'startResize': function(anEvent) {
+//MochiKit.Logging.logDebug(">>> startResize");
+ if (this.editMode() == 'VIEW') {
+ this.setStaticOffset(this.getElement('contentView').getHeight() - anEvent.mouse().page['y'])
+ } else {
+ this.setStaticOffset(this.getElement('textarea').getHeight() - anEvent.mouse().page['y'])
+// this.getElement('textarea').setStyle('opacity', 0.25);
+ }
+ this.setMouseMoveIdentifier(MochiKit.Signal.connect(MochiKit.DOM.currentDocument(), 'onmousemove', this, 'whileResizing'));
+ this.setMouseUpIdentifier(MochiKit.Signal.connect(MochiKit.DOM.currentDocument(), 'onmouseup', this, 'endResize'));
+ anEvent.stop();
+//MochiKit.Logging.logDebug("<<< startResize");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'whileResizing': function(anEvent) {
+//MochiKit.Logging.logDebug(">>> whileResizing");
+ this.getElement('textarea').setHeight(Math.max(32, this.staticOffset() + anEvent.mouse().page['y']) + 'px');
+ this.getElement('contentView').setHeight(Math.max(32, this.staticOffset() + anEvent.mouse().page['y']) + 'px');
+ anEvent.stop();
+//MochiKit.Logging.logDebug("<<< whileResizing");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'endResize': function(anEvent) {
+//MochiKit.Logging.logDebug(">>> endResize");
+ MochiKit.Signal.disconnect(this.mouseMoveIdentifier());
+ this.setMouseMoveIdentifier(null);
+ MochiKit.Signal.disconnect(this.mouseUpIdentifier());
+ this.setMouseUpIdentifier(null);
+// this.getElement('textarea').setStyle('opacity', 1);
+
+ this.setComponentHeight(this.getElement('textarea').getHeight());
+//MochiKit.Logging.logDebug("<<< endResize");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'mouseMoveIdentifier': function() {
+ return this._mouseMoveIdentifier;
+ },
+
+ 'setMouseMoveIdentifier': function(aValue) {
+ this._mouseMoveIdentifier = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'mouseUpIdentifier': function() {
+ return this._mouseUpIdentifier;
+ },
+
+ 'setMouseUpIdentifier': function(aValue) {
+ this._mouseUpIdentifier = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+});
+
diff --git a/frontend/beta/js/Clipperz/PM/Components/RecordDetail/TitleComponent.js b/frontend/beta/js/Clipperz/PM/Components/RecordDetail/TitleComponent.js
new file mode 100644
index 0000000..52e718c
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Components/RecordDetail/TitleComponent.js
@@ -0,0 +1,137 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
+if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
+if (typeof(Clipperz.PM.Components) == 'undefined') { Clipperz.PM.Components = {}; }
+if (typeof(Clipperz.PM.Components.RecordDetail) == 'undefined') { Clipperz.PM.Components.RecordDetail = {}; }
+
+//#############################################################################
+
+Clipperz.PM.Components.RecordDetail.TitleComponent = function(anElement, args) {
+ args = args || {};
+
+ Clipperz.PM.Components.RecordDetail.TitleComponent.superclass.constructor.call(this, anElement, args);
+
+// this._inputElement = null;
+
+ this.mainComponent().addEditComponent(this);
+
+ this.render();
+
+ return this;
+}
+
+//=============================================================================
+
+YAHOO.extendX(Clipperz.PM.Components.RecordDetail.TitleComponent, Clipperz.PM.Components.RecordDetail.AbstractComponent, {
+
+ 'toString': function() {
+ return "Clipperz.PM.Components.RecordDetail.TitleComponent component";
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'value': function() {
+ return this.record().label();
+ },
+
+ 'setValue': function(aValue) {
+ this.record().setLabel(aValue);
+ },
+
+ //-------------------------------------------------------------------------
+/*
+ 'inputElement': function() {
+ return this._inputElement;
+ },
+
+ 'setInputElement': function(aValue) {
+ this._inputElement = aValue;
+ },
+*/
+ //-------------------------------------------------------------------------
+
+ 'render': function() {
+// Clipperz.YUI.DomHelper.append(this.element().dom, {tag:'td', html:'&#160'});
+// Clipperz.YUI.DomHelper.append(this.element().dom, {tag:'td', colspan:"3", html:'&#160', children:[
+// {tag:'div', /*style:'border: 1px solid green;',*/ id:this.getId('title')}
+// ]});
+// Clipperz.YUI.DomHelper.append(this.element().dom, {tag:'td', html:'&#160'});
+//
+// this.setInputElement(new Clipperz.PM.Components.TextFormField(this.getElement('title'), {editMode:this.editMode(), value:this.value()}));
+
+ this.update();
+ },
+
+ //-------------------------------------------------------------------------
+/*
+ 'update': function() {
+ this.inputElement().update({value:this.value(), editMode:this.editMode()});
+ },
+*/
+ //-------------------------------------------------------------------------
+
+ 'updateViewMode': function() {
+ this.element().update("");
+ Clipperz.YUI.DomHelper.append(this.element().dom, {tag:'h2', html:this.value()});
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'updateEditMode': function() {
+//MochiKit.Logging.logDebug(">>> TitleComponent.updateEditMode");
+// this.getElement('title').update("");
+// Clipperz.YUI.DomHelper.append(this.getDom('title'), {tag:'div', id:this.getId('title_input')});
+// this.setInputElement(Clipperz.YUI.DomHelper.append(this.getDom('title_input'), {tag:'input', type:'text', value:this.value()}, true));
+
+ this.element().update("");
+ Clipperz.YUI.DomHelper.append(this.element().dom, {tag:'input', id:this.getId('titleField'), type:'text', value:"this.value()"});
+ this.getElement('titleField').dom.value = this.value();
+
+//MochiKit.Logging.logDebug("<<< TitleComponent.updateEditMode");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'synchronizeComponentValues': function() {
+ var inputElement;
+
+//MochiKit.Logging.logDebug(">>> TitleComponent.synchronizeComponentValues");
+ inputElement = this.element().getChildrenByTagName('input')[0];
+
+ if (inputElement != null) {
+ this.setValue(inputElement.dom.value);
+ }
+//MochiKit.Logging.logDebug("<<< TitleComponent.synchronizeComponentValues");
+ },
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+});
+
diff --git a/frontend/beta/js/Clipperz/PM/Components/TabPanel/TabPanelController.js b/frontend/beta/js/Clipperz/PM/Components/TabPanel/TabPanelController.js
new file mode 100644
index 0000000..c872462
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Components/TabPanel/TabPanelController.js
@@ -0,0 +1,158 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
+if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
+if (typeof(Clipperz.PM.Components) == 'undefined') { Clipperz.PM.Components = {}; }
+if (typeof(Clipperz.PM.Components.TabPanel) == 'undefined') { Clipperz.PM.Components.TabPanel = {}; }
+
+Clipperz.PM.Components.TabPanel.TabPanelController = function(args) {
+ args = args || {};
+
+ Clipperz.PM.Components.TabPanel.TabPanelController.superclass.constructor.call(this);
+
+ this._name = args.name || 'undefined';
+ this._config = args.config;
+ this._selectedTab = args.selectedTab || ((MochiKit.Base.keys(args.config).length > 0) ? MochiKit.Base.keys(args.config)[0] : null);
+
+ this._tabs = {};
+ this._panels = {};
+
+ Clipperz.NotificationCenter.register(null, 'selectTab', this, 'handleSelectTabNotification');
+ return this;
+}
+
+//=============================================================================
+
+YAHOO.extendX(Clipperz.PM.Components.TabPanel.TabPanelController, YAHOO.ext.util.Observable, {
+
+ //-------------------------------------------------------------------------
+
+ 'name': function() {
+ return this._name;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'tabs': function() {
+ return this._tabs;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'panels': function() {
+ return this._panels;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'config': function() {
+ return this._config;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'selectedTab': function() {
+ return this._selectedTab;
+ },
+
+ 'setSelectedTab': function(aValue) {
+ this._selectedTab = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'setUp': function() {
+ var tabId;
+
+//MochiKit.Logging.logDebug(">>> TabPanelController.setUp - config: " + Clipperz.Base.serializeJSON(this.config()));
+ for (tabId in this.config()) {
+ var tabElement;
+ var panelElement;
+
+//MochiKit.Logging.logDebug("--- TabPanelController.setUp - tabId: " + tabId);
+//MochiKit.Logging.logDebug("--- TabPanelController.setUp - panelId: " + this.config()[tabId]);
+ tabElement = YAHOO.ext.Element.get(tabId);
+ tabElement.addClassOnOver("hover");
+ MochiKit.Signal.connect(tabId, 'onclick', this, 'selectTabHandler');
+
+ panelElement = YAHOO.ext.Element.get(this.config()[tabId]);
+
+ this._tabs[tabId] = tabElement;
+ this._panels[tabId] = panelElement;
+
+ if (tabId == this.selectedTab()) {
+ tabElement.addClass('selectedTab');
+ panelElement.addClass('selectedPanel');
+ } else {
+ panelElement.addClass('hiddenPanel');
+ }
+ }
+//MochiKit.Logging.logDebug("<<< TabPanelController.setUp");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'selectTab': function(aTab) {
+ if (aTab != this.selectedTab()) {
+ this.tabs()[this.selectedTab()].removeClass('selectedTab');
+ this.panels()[this.selectedTab()].removeClass('selectedPanel').addClass('hiddenPanel');
+
+ this.tabs()[aTab].addClass('selectedTab');
+ this.panels()[aTab].addClass('selectedPanel').removeClass('hiddenPanel');
+
+ this.setSelectedTab(aTab);
+
+ Clipperz.NotificationCenter.notify(this, 'tabSelected', aTab);
+ }
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'selectTabHandler': function(anEvent) {
+ this.selectTab(anEvent.src().id);
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'handleSelectTabNotification': function(aNotificationEvent) {
+ var parameters;
+ var splittedParamters;
+ var targetTabPanel;
+
+ parameters = aNotificationEvent.parameters();
+ splittedParamters = parameters.split('.');
+ targetTabPanel = splittedParamters[0];
+ if (targetTabPanel == this.name()) {
+ this.selectTab(splittedParamters[1])
+ }
+ },
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+});
diff --git a/frontend/beta/js/Clipperz/PM/Components/TextFormField.js b/frontend/beta/js/Clipperz/PM/Components/TextFormField.js
new file mode 100644
index 0000000..cb4f06a
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Components/TextFormField.js
@@ -0,0 +1,310 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
+if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
+if (typeof(Clipperz.PM.Components) == 'undefined') { Clipperz.PM.Components = {}; }
+
+Clipperz.PM.Components.TextFormField = function(anElement, args) {
+ args = args || {};
+
+//MochiKit.Logging.logDebug(">>> new TextFormField");
+ Clipperz.PM.Components.TextFormField.superclass.constructor.call(this, args);
+
+ this._element = anElement;
+ this._editMode = args.editMode || 'VIEW';
+ this._value = args.value || "";
+ this._inputElement = null;
+ this._wrapper = null;
+ this._multiline = args.multiline || false;
+
+// this.multiline = args.multiline || true;
+// this.editing = true;
+// this.completeOnBlur = true;
+// this.autoSizeTask = new YAHOO.ext.util.DelayedTask(this.autoSize, this);
+// this.textSizeEl = Clipperz.YUI.DomHelper.append(document.body, {
+// tag: 'div',
+// cls: 'yinline-editor-sizer ' + (this.cls || '')
+// });
+
+ this.render();
+//MochiKit.Logging.logDebug("<<< new TextFormField");
+
+ return this;
+};
+
+YAHOO.extendX(Clipperz.PM.Components.TextFormField, Clipperz.PM.Components.BaseComponent, {
+
+ 'toString': function() {
+ return "Clipperz.PM.Components.TextFormField";
+ },
+
+ //-----------------------------------------------------
+
+ 'value': function() {
+ if (this.inputElement() != null) {
+ this._value = this.inputElement().dom.value;
+ }
+
+ return this._value;
+// return this.inlineEditor().getValue();
+ },
+
+ 'setValue': function(aValue) {
+ this._value = aValue;
+// this.getElement('viewComponent_Content').update(aValue);
+// this.inlineEditor().setValue(aValue);
+ },
+
+ //-----------------------------------------------------
+
+ 'multiline': function() {
+ return this._multiline;
+ },
+
+ //-----------------------------------------------------
+
+ 'editMode': function() {
+ return this._editMode;
+ },
+
+ 'setEditMode': function(aValue) {
+ this._editMode = aValue;
+ },
+
+ //-----------------------------------------------------
+
+ 'inputElement': function() {
+ return this._inputElement;
+ },
+
+ 'setInputElement': function(aValue) {
+ this._inputElement = aValue;
+ },
+
+ //-----------------------------------------------------
+
+ 'on': function(anEventName, anHandler, aScope, shouldOverride) {
+//MochiKit.Logging.logDebug(">>> TextFormField.on - inputElement: " + this.inputElement());
+ return this.inputElement().on(anEventName, anHandler, aScope, shouldOverride);
+//MochiKit.Logging.logDebug("<<< TextFormField.on - inputElement: " + this.inputElement());
+ },
+
+ //-----------------------------------------------------
+
+ 'wrapper': function() {
+ return this._wrapper;
+ },
+
+ //-----------------------------------------------------
+
+ 'render': function() {
+ var editModeConfiguration;
+ var viewModeConfiguration;
+
+ editModeConfiguration = {tag:'div', id:this.getId('editComponent'), children:[]};
+ if (this.multiline() == false) {
+ editModeConfiguration.children.push({tag:'input', type:'text', id:this.getId('editComponent_input'), value:"this.value(1)"});
+ } else {
+ editModeConfiguration.children.push({tag:'textarea', id:this.getId('editComponent_input'), html:"this.value(2)"});
+ }
+
+ viewModeConfiguration = {tag:'div', id:this.getId('viewComponent'), /*style:'border: 1px solid blue;',*/ children:[
+ {tag:'span', id:this.getId('viewComponent_Content'), html:this.value()}
+ ]}
+
+//MochiKit.Logging.logDebug(">>> TextFormField.render");
+ this._wrapper = Clipperz.YUI.DomHelper.append(this.element().dom, {tag:'div', id:this.getId('wrapper'), children:[
+ {tag:'div', id:this.getId('editModeBox'), children:[editModeConfiguration]},
+ {tag:'div', id:this.getId('viewModeBox'), children:[viewModeConfiguration]}
+ ]}, true);
+
+ this.getElement('editModeBox').setVisibilityMode(YAHOO.ext.Element.DISPLAY);
+ this.getElement('viewModeBox').setVisibilityMode(YAHOO.ext.Element.DISPLAY);
+
+ this.getElement('editComponent_input').dom.value = this.value();
+ this.setInputElement(this.getElement('editComponent_input'));
+
+ this.update();
+//MochiKit.Logging.logDebug("<<< TextFormField.render");
+ },
+
+ //-----------------------------------------------------
+
+ 'update': function(args) {
+ args = args || {};
+
+//MochiKit.Logging.logDebug(">>> TextFormField.update");
+ if (typeof(args.value) != 'undefined') {
+ this.setValue(args.value);
+ }
+ if (typeof(args.editMode) != 'undefined') {
+ this.setEditMode(args.editMode)
+ }
+
+ if (this.editMode() == 'VIEW') {
+ this.updateViewMode();
+ } else if (this.editMode() == 'EDIT') {
+ this.updateEditMode();
+ } else {
+ // ?????
+ }
+//MochiKit.Logging.logDebug("<<< TextFormField.update");
+ },
+
+ //-----------------------------------------------------
+
+ 'updateEditMode': function() {
+//MochiKit.Logging.logDebug(">>> TextFormField.updateEditMode");
+ this.getElement('viewModeBox').hide();
+ this.getElement('editModeBox').show();
+
+ if (this.multiline() == false) {
+ this.getElement('editComponent_input').dom.value = this.value();
+ } else {
+ this.getElement('editComponent_input').update(Clipperz.Base.sanitizeString(this.value()));
+ }
+//MochiKit.Logging.logDebug("<<< TextFormField.updateEditMode");
+ },
+
+ //-----------------------------------------------------
+
+ 'updateViewMode': function() {
+//MochiKit.Logging.logDebug(">>> TextFormField.updateViewMode");
+ this.getElement('editModeBox').hide();
+ this.getElement('viewModeBox').show();
+
+ this.getElement('viewComponent_Content').update(Clipperz.Base.sanitizeString(this.value()));
+//MochiKit.Logging.logDebug("<<< TextFormField.updateViewMode");
+ },
+
+ //#####################################################
+ //#####################################################
+ //#####################################################
+ //#####################################################
+/*
+ 'onEnter': function(k, e) {
+MochiKit.Logging.logDebug(">>> TextFormField.onEnter");
+ if (this.multiline && (e.ctrlKey || e.shiftKey)) {
+ return;
+ } else {
+ this.completeEdit();
+ e.stopEvent();
+ }
+MochiKit.Logging.logDebug("<<< TextFormField.onEnter");
+ },
+
+ //-----------------------------------------------------
+
+ 'onEsc': function() {
+MochiKit.Logging.logDebug(">>> TextFormField.onEsc");
+// if (this.ignoreNoChange) {
+// this.revert(true);
+// } else {
+ this.revert(false);
+ this.completeEdit();
+// }
+MochiKit.Logging.logDebug("<<< TextFormField.onEsc");
+ },
+
+ //-----------------------------------------------------
+
+ onBlur : function(){
+MochiKit.Logging.logDebug(">>> TextFormField.onBlur");
+ if (this.editing && this.completeOnBlur !== false) {
+ this.completeEdit();
+ }
+MochiKit.Logging.logDebug("<<< TextFormField.onBlur");
+ },
+
+ //-----------------------------------------------------
+
+ 'onKeyUp': function(e) {
+ var k = e.getKey();
+ if (this.editing && (k < 33 || k > 40) && k != 27) {
+ this.autoSizeTask.delay(50);
+ }
+ },
+
+ //-----------------------------------------------------
+
+ 'autoSize': function() {
+ var el = this.inputElement();
+ var wrap = this.getElement('editComponent');
+ var v = el.dom.value;
+ var ts = this.textSizeEl;
+
+ if (v.length < 1) {
+ ts.innerHTML = "&#160;&#160;";
+ } else {
+ v = v.replace(/[<> ]/g, '&#160;');
+ if (this.multiline) {
+ v = v.replace(/\n/g, '<br />&#160;');
+ }
+ ts.innerHTML = v;
+ }
+
+ var ww = wrap.dom.offsetWidth;
+ var wh = wrap.dom.offsetHeight;
+ var w = ts.offsetWidth;
+ var h = ts.offsetHeight;
+ // lots of magic numbers in this block - wtf?
+ // the logic is to prevent the scrollbars from flashing
+ // in firefox. Updates the right element first
+ // so there's never overflow.
+ if (ww > w+4) {
+ el.setWidth(w+4);
+ wrap.setWidth(w+8);
+ } else {
+ wrap.setWidth(w+8);
+ el.setWidth(w+4);
+ }
+ if (wh > h+4) {
+ el.setHeight(h);
+ wrap.setHeight(h+4);
+ } else {
+ wrap.setHeight(h+4);
+ el.setHeight(h);
+ }
+ },
+
+ //-----------------------------------------------------
+
+ 'completeEdit': function() {
+MochiKit.Logging.logDebug(">>> TextFormField.completeEdit");
+
+ },
+
+ 'revert': function() {
+MochiKit.Logging.logDebug(">>> TextFormField.revert");
+
+ },
+*/
+ //-----------------------------------------------------
+ __syntaxFix__: '__syntaxFix__'
+});
diff --git a/frontend/beta/js/Clipperz/PM/Connection.js b/frontend/beta/js/Clipperz/PM/Connection.js
new file mode 100644
index 0000000..cf37ccc
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Connection.js
@@ -0,0 +1,584 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. 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._user = args.user;
+ this._clipperz_pm_crypto_version = null;
+ this._connectionId = null;
+ this._oneTimePassword = null;
+
+ return this;
+}
+
+Clipperz.PM.Connection.prototype = MochiKit.Base.update(null, {
+
+ 'user': function() {
+ return this._user;
+ },
+
+ 'toString': function() {
+ return "Connection [" + this.version() + "] - user: " + this.user();
+ },
+
+ //=========================================================================
+
+ '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.Crypto.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) {
+MochiKit.Logging.logError("### Connection.defaultErrorHandler: " + anErrorString + " (" + anException + ")");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'login': function(someArguments, aCallback) {
+ throw Clipperz.Base.exception.AbstractMethod;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'message': function(someArguments, aCallback) {
+ throw Clipperz.Base.exception.AbstractMethod;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'sharedSecret': function() {
+ throw Clipperz.Base.exception.AbstractMethod;
+ },
+
+ 'serverSideUserCredentials': function() {
+ throw Clipperz.Base.exception.AbstractMethod;
+ },
+
+ //=========================================================================
+
+ 'connectionId': function() {
+ return this._connectionId;
+ },
+
+ 'setConnectionId': function(aValue) {
+ this._connectionId = aValue;
+ },
+
+ //=========================================================================
+
+ 'oneTimePassword': function() {
+ return this._oneTimePassword;
+ },
+
+ 'setOneTimePassword': function(aValue) {
+ this._oneTimePassword = aValue;
+ },
+
+ //=========================================================================
+ __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) {
+ args = args || {};
+ Clipperz.PM.Connection.call(this, args);
+
+ this._C = null;
+ this._P = null;
+ this._srpConnection = null;
+
+ return this;
+}
+
+Clipperz.PM.Connection.SRP['1.0'].prototype = MochiKit.Base.update(new Clipperz.PM.Connection(), {
+
+ 'version': function() {
+ return '1.0';
+ },
+
+ //=========================================================================
+
+ 'register': function(anInvitationCode) {
+ var deferredResult;
+ var parameters;
+
+//MochiKit.Logging.logError(">>> Connection.register: " + this);
+ parameters = {};
+ deferredResult = new MochiKit.Async.Deferred();
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Connection.register - 1: " + res); return res;});
+ deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', 'registration_verify');
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Connection.register - 2: " + res); return res;});
+ deferredResult.addCallback(function(aConnection, anInvitationCode) {
+ var args;
+
+ args = {};
+ args.message = 'register';
+ args.version = aConnection.clipperz_pm_crypto_version();
+ args.invitationCode = anInvitationCode;
+
+ return args;
+ }, this);
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Connection.register - 3: " + res); return res;});
+ deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', 'registration_sendingCredentials');
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Connection.register - 4: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(this.user(), 'encryptedData'));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Connection.register - 5: " + res); return res;});
+ deferredResult.addCallback(function(someParameters, anUser, anEncryptedData) {
+ var currentVersionConnection;
+ var args;
+
+ currentVersionConnection = new Clipperz.PM.Crypto.communicationProtocol.versions['current']({user:anUser});
+
+ args = someParameters
+ args.credentials = currentVersionConnection.serverSideUserCredentials();
+ args.user = anEncryptedData;
+ args.version = args.credentials.version;
+ args.message = "completeRegistration";
+
+ return args;
+ }, parameters, this.user());
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Connection.register - 6: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(Clipperz.PM.Proxy.defaultProxy, 'registration'));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Connection.register - 7: " + Clipperz.Base.serializeJSON(res)); return res;});
+ deferredResult.addCallback(MochiKit.Base.bind(function(res) {
+ this.user().setLock(res['lock']);
+
+ return res;
+ }, this));
+ deferredResult.callback(anInvitationCode);
+//MochiKit.Logging.logError("<<< Connection.register");
+
+ return deferredResult;
+ },
+
+ //=========================================================================
+
+ 'login': function(isReconnecting) {
+ var deferredResult;
+
+//MochiKit.Logging.logDebug(">>> Connection.login: "/* + this*/);
+//MochiKit.Logging.logDebug("--- Connection.login - isReconnecting: " + (isReconnecting == true));
+ deferredResult = new MochiKit.Async.Deferred();
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("1.3.1 - Connection.login - 1: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+ deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', 'connection_sendingCredentials');
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("1.3.2 - Connection.login - 2: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+ deferredResult.addCallback(function(aConnection) {
+ var args;
+
+ args = {};
+ args.message = 'connect';
+ args.version = aConnection.clipperz_pm_crypto_version();
+ args.parameters = {};
+//MochiKit.Logging.logDebug("=== Connection.login - username: " + aConnection.srpConnection().C());
+ args.parameters['C'] = aConnection.srpConnection().C();
+ args.parameters['A'] = aConnection.srpConnection().A().asString(16);
+
+ if (isReconnecting == true) {
+//MochiKit.Logging.logDebug("--- Connection.login - reconnecting");
+//# args.parameters['reconnecting'] = "yes";
+ args.parameters['reconnecting'] = aConnection.connectionId();
+ }
+//MochiKit.Logging.logDebug("--- Connection.login - args: " + Clipperz.Base.serializeJSON(args));
+//MochiKit.Logging.logDebug("--- Connection.login - srp.a: " + aConnection.srpConnection().a().asString(16));
+
+ return args;
+ });
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("1.3.3 - Connection.login - 3: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(Clipperz.PM.Proxy.defaultProxy, 'handshake'));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("1.3.4 - Connection.login - 4: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+ deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', 'connection_credentialVerification');
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("1.3.5 - Connection.login - 5: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+deferredResult.addErrback(MochiKit.Base.bind(function(res) {MochiKit.Logging.logDebug("ERROR - c: " + this.srpConnection().C() + " # version: " + this.clipperz_pm_crypto_version()); return res;}, this));
+ deferredResult.addCallback(MochiKit.Base.bind(function(someParameters) {
+ var args;
+
+ this.srpConnection().set_s(new Clipperz.Crypto.BigInt(someParameters['s'], 16));
+ this.srpConnection().set_B(new Clipperz.Crypto.BigInt(someParameters['B'], 16));
+
+ if (typeof(someParameters['oneTimePassword']) != 'undefined') {
+ this.setOneTimePassword(someParameters['oneTimePassword']);
+ }
+
+ args = {};
+ args.message = 'credentialCheck';
+ args.version = this.clipperz_pm_crypto_version();
+ args.parameters = {};
+ args.parameters['M1'] = this.srpConnection().M1();
+
+ return args;
+ }, this));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("1.3.6 - Connection.login - 6: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(Clipperz.PM.Proxy.defaultProxy, 'handshake'));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("1.3.7 - Connection.login - 7: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+//# deferredResult.addCallback(MochiKit.Base.method(this, 'loginDone'));
+ deferredResult.addCallback(MochiKit.Base.bind(function(someParameters) {
+ var result;
+
+//MochiKit.Logging.logDebug(">>> Connection.loginDone: " + this + " (M2: " + this.srpConnection().M2() + ")");
+ if (someParameters['M2'] == this.srpConnection().M2()) {
+ result = new MochiKit.Async.Deferred();
+
+//MochiKit.Logging.logDebug("--- Connection.loginDone - someParameters: " + Clipperz.Base.serializeJSON(someParameters));
+ this.setConnectionId(someParameters['connectionId']);
+ this.user().setLoginInfo(someParameters['loginInfo']);
+ this.user().setShouldDownloadOfflineCopy(someParameters['offlineCopyNeeded']);
+ this.user().setLock(someParameters['lock']);
+
+ if (this.oneTimePassword() != null) {
+ result.addCallback(MochiKit.Base.method(this.user().oneTimePasswordManager(), 'archiveOneTimePassword', this.oneTimePassword()));
+ }
+ result.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', 'connection_loggedIn');
+ result.addCallback(MochiKit.Async.succeed, someParameters);
+
+ result.callback();
+//MochiKit.Logging.logDebug("--- Connection.loginDone - 1 - result: "/* + Clipperz.Base.serializeJSON(result)*/);
+ } else {
+//MochiKit.Logging.logDebug("--- Connection.loginDone - 2 - ERROR");
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+ result = MochiKit.Async.fail(Clipperz.PM.Connection.exception.WrongChecksum);
+ }
+//MochiKit.Logging.logDebug("<<< Connection.loginDone - result: " + Clipperz.Base.serializeJSON(result));
+
+ return result;
+ }, this));
+
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("1.3.8 - Connection.login - 8: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+ deferredResult.callback(this);
+//MochiKit.Logging.logDebug("<<< Connection.login");
+
+ return deferredResult;
+ },
+
+ //=========================================================================
+
+ 'logout': function() {
+ var deferredResult;
+
+//MochiKit.Logging.logDebug(">>> Connection.logout: " + this);
+ deferredResult = new MochiKit.Async.Deferred();
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Connection.logout - 1: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(Clipperz.PM.Proxy.defaultProxy, 'logout'), {});
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Connection.logout - 2: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(this, 'resetSrpConnection'));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Connection.logout - 3: " + res); return res;});
+ deferredResult.callback();
+//MochiKit.Logging.logDebug("<<< Connection.logout");
+
+ return deferredResult;
+ },
+
+ //=========================================================================
+
+ 'message': function(aMessageName, someParameters) {
+ var args;
+ var deferredResult;
+
+//MochiKit.Logging.logDebug(">>> Connection.message: " + this);
+ args = {}
+ args['message'] = aMessageName;
+ args['srpSharedSecret'] = this.srpConnection().K();
+// args['lock'] = this.user().lock();
+
+ if (someParameters != null) {
+ args['parameters'] = someParameters;
+ } else {
+ args['parameters'] = {};
+ }
+//MochiKit.Logging.logDebug("--- Connection.message - args: " + Clipperz.Base.serializeJSON(args));
+
+// deferredResult = new MochiKit.Async.Deferred(); // ### ?????????????
+
+ return this.sendMessage(args);
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'sendMessage': function(someArguments) {
+ var deferredResult;
+
+//MochiKit.Logging.logDebug(">>> Connection.sendMessage: " + this);
+ deferredResult = new MochiKit.Async.Deferred();
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Connection.sendMessage - 1: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(Clipperz.PM.Proxy.defaultProxy, 'message'), someArguments);
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Connection.sendMessage - 2: " + res); return res;});
+
+ deferredResult.addCallback(MochiKit.Base.bind(function(res) {
+ if (typeof(res['lock']) != 'undefined') {
+ this.user().setLock(res['lock']);
+ }
+ return res;
+ }, this));
+
+ deferredResult.addErrback(MochiKit.Base.method(this, 'messageExceptionHandler'), someArguments);
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Connection.sendMessage - 3: " + res); return res;});
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Connection.sendMessage - 3: " + Clipperz.Base.serializeJSON(res)); return res;});
+ deferredResult.callback();
+//MochiKit.Logging.logDebug("<<< Connection.sendMessage");
+
+ return deferredResult
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'messageExceptionHandler': function(anOriginalMessageArguments, anError) {
+ var result;
+
+//MochiKit.Logging.logDebug(">>> Connection.messageExceptionHandler - this: " + this + ", anError: " + anError);
+ if (anError instanceof MochiKit.Async.CancelledError) {
+//MochiKit.Logging.logDebug("--- Connection.messageExceptionHandler - 1");
+ result = anError;
+//MochiKit.Logging.logDebug("--- Connection.messageExceptionHandler - 2");
+ } else {
+//MochiKit.Logging.logDebug("--- Connection.messageExceptionHandler - 3 - anError.name: " + anError.name + ", message: " + anError.message);
+ if ((anError.message == 'Trying to communicate without an active connection') ||
+ (anError.message == 'No tollManager available for current session')
+ ) {
+//MochiKit.Logging.logDebug("--- Connection.messageExceptionHandler - 4");
+ result = this.reestablishConnection(anOriginalMessageArguments);
+//MochiKit.Logging.logDebug("--- Connection.messageExceptionHandler - 5");
+ } else if (anError.message == 'Session with stale data') {
+//MochiKit.Logging.logDebug("--- Connection.messageExceptionHandler - 5.1");
+ Clipperz.NotificationCenter.notify(this, 'EXCEPTION');
+//MochiKit.Logging.logDebug("--- Connection.messageExceptionHandler - 5.2");
+ } else {
+//MochiKit.Logging.logDebug("--- Connection.messageExceptionHandler - 6");
+ result = anError;
+//MochiKit.Logging.logDebug("--- Connection.messageExceptionHandler - 7");
+ }
+//MochiKit.Logging.logDebug("--- Connection.messageExceptionHandler - 8");
+ }
+//MochiKit.Logging.logDebug("<<< Connection.messageExceptionHandler");
+
+ return result;;
+ },
+
+ //=========================================================================
+
+ 'reestablishConnection': function(anOriginalMessageArguments) {
+ var deferredResult;
+
+//MochiKit.Logging.logDebug("+++ Connection.reestablishConnection: " + Clipperz.Base.serializeJSON(anOriginalMessageArguments));
+
+//MochiKit.Logging.logDebug(">>> Connection.reestablishConnection: " + this);
+ deferredResult = new MochiKit.Async.Deferred();
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Connection.reestablishConnection 1: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(this, 'resetSrpConnection'));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Connection.reestablishConnection 2: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(this, 'login'), true);
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Connection.reestablishConnection 3: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.bind(function(aMessage) {
+ aMessage['srpSharedSecret'] = this.srpConnection().K();
+ return aMessage;
+ }, this), anOriginalMessageArguments);
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Connection.reestablishConnection 4: " + Clipperz.Base.serializeJSON(res)); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(this, 'sendMessage'));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Connection.reestablishConnection 5: " + res); return res;});
+ deferredResult.addErrback(Clipperz.NotificationCenter.deferredNotification, this, 'EXCEPTION', null);
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Connection.reestablishConnection 6: " + res); return res;});
+ deferredResult.callback();
+//MochiKit.Logging.logDebug("<<< Connection.reestablishConnection");
+
+ return deferredResult;
+ },
+
+ //=========================================================================
+
+ 'sharedSecret': function() {
+ return this.srpConnection().K();
+ },
+
+ //=========================================================================
+
+ 'serverSideUserCredentials': function() {
+ var result;
+ var newSrpConnection;
+
+//MochiKit.Logging.logDebug(">>> Connection.serverSideUserCredentials");
+ newSrpConnection = new Clipperz.Crypto.SRP.Connection({ C:this.C(), P:this.P(), hash:this.hash() });
+ result = newSrpConnection.serverSideCredentials();
+ result['version'] = this.clipperz_pm_crypto_version();
+
+//MochiKit.Logging.logDebug("<<< Connection.serverSideUserCredentials - result: " + Clipperz.Base.serializeJSON(result));
+ return result;
+ },
+
+ //=========================================================================
+
+ 'C': function() {
+ if (this._C == null) {
+ this._C = this.hash()(new Clipperz.ByteArray(this.user().username())).toHexString().substring(2);
+ }
+
+ return this._C;
+ },
+
+ //-----------------------------------------------------------------------------
+
+ 'P': function() {
+ if (this._P == null) {
+ this._P = this.hash()(new Clipperz.ByteArray(this.user().passphrase() + this.user().username())).toHexString().substring(2);
+ }
+
+ return this._P;
+ },
+
+ //-----------------------------------------------------------------------------
+
+ 'hash': function() {
+ return Clipperz.PM.Crypto.encryptingFunctions.versions['0.1'].hash;
+ },
+
+ //-----------------------------------------------------------------------------
+
+ 'srpConnection': function() {
+ if (this._srpConnection == null) {
+ this._srpConnection = new Clipperz.Crypto.SRP.Connection({ C:this.C(), P:this.P(), hash:this.hash() });
+ }
+
+ return this._srpConnection;
+ },
+
+ 'resetSrpConnection': function() {
+ this._C = null;
+ this._P = null;
+ this._srpConnection = null;
+ },
+
+ //-----------------------------------------------------------------------------
+ __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) {
+ args = 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';
+ },
+
+ //-----------------------------------------------------------------------------
+
+ 'C': function() {
+ if (this._C == null) {
+ this._C = this.hash()(new Clipperz.ByteArray(this.user().username() + this.user().passphrase())).toHexString().substring(2);
+ }
+
+ return this._C;
+ },
+
+ //-----------------------------------------------------------------------------
+
+ 'P': function() {
+ if (this._P == null) {
+ this._P = this.hash()(new Clipperz.ByteArray(this.user().passphrase() + this.user().username())).toHexString().substring(2);
+ }
+
+ return this._P;
+ },
+
+ //-----------------------------------------------------------------------------
+
+ '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")
+};
diff --git a/frontend/beta/js/Clipperz/PM/Crypto.js b/frontend/beta/js/Clipperz/PM/Crypto.js
new file mode 100644
index 0000000..7636822
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Crypto.js
@@ -0,0 +1,503 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. 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";
+
+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.3',
+ '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 MochiKit.Async.Deferred();
+ 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 MochiKit.Async.Deferred();
+ 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;
+ }
+ },
+
+ //#####################################################################
+
+ '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 MochiKit.Async.Deferred()
+ 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 decryptedData;
+
+ key = Clipperz.Crypto.SHA.sha_d256(new Clipperz.ByteArray(aKey));
+ value = new Clipperz.ByteArray().appendBase64String(aValue);
+
+ decryptedData = Clipperz.Crypto.AES.decrypt(key, value);
+ decryptedData = decryptedData.split((256/8));
+
+ try {
+ result = Clipperz.Base.evalJSON(decryptedData.asString());
+ } catch (exception) {
+ MochiKit.Logging.logError("Error while decrypting data");
+ 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;
+
+ result = new MochiKit.Async.Deferred();
+
+ key = Clipperz.Crypto.SHA.sha_d256(new Clipperz.ByteArray(aKey));
+ value = new Clipperz.ByteArray().appendBase64String(aValue);
+
+
+ deferredResult = new MochiKit.Async.Deferred()
+ 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) {
+ MochiKit.Logging.logError("Error while decrypting data");
+ 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
+ },
+
+ //#####################################################################
+
+ '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 MochiKit.Async.Deferred()
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Clipperz.PM.Crypto.deferredEncrypt - 1: " + res); return res;});
+ deferredResult.addCallback(Clipperz.Crypto.AES.deferredEncrypt, key, data, aNonce);
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Clipperz.PM.Crypto.deferredEncrypt - 2: " + res); return res;});
+ deferredResult.addCallback(function(aResult) {
+ return aResult.toBase64String();
+ })
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Clipperz.PM.Crypto.deferredEncrypt - 3: " + res); return res;});
+ 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);
+
+ value = decryptedData.asString();
+ try {
+ result = Clipperz.Base.evalJSON(value);
+ } catch (exception) {
+ MochiKit.Logging.logError("Error while decrypting data");
+ throw Clipperz.Crypto.Base.exception.CorruptedMessage;
+ }
+ } else {
+ result = null;
+ }
+
+ return result;
+ },
+
+ 'deferredDecrypt': function(aKey, aValue) {
+ var deferredResult;
+// var now;
+
+ deferredResult = new MochiKit.Async.Deferred();
+ now = new Date;
+
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("[" + (new Date() - now) + "] Clipperz.PM.Crypto.deferredDecrypt - 1: " + res); return res;});
+ if (aValue != null) {
+ var key, value;
+ var decryptedData;
+ var decryptedValue;
+
+ key = Clipperz.Crypto.SHA.sha_d256(new Clipperz.ByteArray(aKey));
+//MochiKit.Logging.logDebug("[" + (new Date() - now) + "] computed key");
+ value = new Clipperz.ByteArray().appendBase64String(aValue);
+//MochiKit.Logging.logDebug("[" + (new Date() - now) + "] appendedBase64String");
+
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("[" + (new Date() - now) + "] Clipperz.PM.Crypto.deferredDecrypt - 1.1: " /* + res*/); return res;});
+ deferredResult.addCallback(Clipperz.Crypto.AES.deferredDecrypt, key, value);
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("[" + (new Date() - now) + "] Clipperz.PM.Crypto.deferredDecrypt - 2: " /* + res*/); return res;});
+ deferredResult.addCallback(MochiKit.Async.wait, 0.1);
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("[" + (new Date() - now) + "] Clipperz.PM.Crypto.deferredDecrypt - 3: " /* + res*/); return res;});
+ deferredResult.addCallback(function(aResult) {
+ return aResult.asString();
+ });
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("[" + (new Date() - now) + "] Clipperz.PM.Crypto.deferredDecrypt - 4: " /* + res*/); return res;});
+ deferredResult.addCallback(MochiKit.Async.wait, 0.1);
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("[" + (new Date() - now) + "] Clipperz.PM.Crypto.deferredDecrypt - 5: " /* + res*/); return res;});
+ deferredResult.addCallback(Clipperz.Base.evalJSON);
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("[" + (new Date() - now) + "] Clipperz.PM.Crypto.deferredDecrypt - 6: " /* + res*/); return res;});
+ deferredResult.addErrback(function(anError) {
+ MochiKit.Logging.logError("Error while decrypting data");
+ throw Clipperz.Crypto.Base.exception.CorruptedMessage;
+ })
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("[" + (new Date() - now) + "] Clipperz.PM.Crypto.deferredDecrypt - 7: " /* + res*/); return res;});
+ } else {
+ deferredResult.addCallback(function() {
+ return null;
+ });
+ }
+ deferredResult.callback();
+
+ return deferredResult;
+ },
+
+ 'hash': Clipperz.Crypto.SHA.sha_d256
+ },
+
+ //#####################################################################
+/*
+ '0.4': {
+ 'encrypt': function(aKey, aValue, aNonce) {
+ var result;
+ var key, value;
+ var data;
+ var dataToEncrypt;
+ var encryptedData;
+
+//MochiKit.Logging.logDebug(">>> [" + (new Date()).valueOf() + "] Clipperz.PM.Crypto.versions[0.3].encrypt");
+ key = Clipperz.Crypto.SHA.sha_d256(new Clipperz.ByteArray(aKey));
+//MochiKit.Logging.logDebug("--- [" + (new Date()).valueOf() + "] Clipperz.PM.Crypto.versions[0.3].encrypt - 1");
+ value = Clipperz.Base.serializeJSON(aValue);
+//MochiKit.Logging.logDebug("--- [" + (new Date()).valueOf() + "] Clipperz.PM.Crypto.versions[0.3].encrypt - 2");
+/ *
+//MochiKit.Logging.logDebug("--> encrypt.fullSize: " + value.length);
+ value = value.replace(/":{"label":"/g, '":{l:"');
+ value = value.replace(/":{"key":"/g, '":{k:"');
+ value = value.replace(/":{"notes":"/g, '":{n:"');
+ value = value.replace(/":{"record":"/g, '":{r:"');
+ value = value.replace(/", "label":"/g, '",l:"');
+ value = value.replace(/", "favicon":"/g, '",f:"');
+//MochiKit.Logging.logDebug("<-- encrypt.compressed: " + value.length);
+* /
+ data = new Clipperz.ByteArray(value);
+//MochiKit.Logging.logDebug("--- [" + (new Date()).valueOf() + "] Clipperz.PM.Crypto.versions[0.3].encrypt - 3");
+ encryptedData = Clipperz.Crypto.AES.encrypt(key, data, aNonce);
+//MochiKit.Logging.logDebug("--- [" + (new Date()).valueOf() + "] Clipperz.PM.Crypto.versions[0.3].encrypt - 4");
+ result = encryptedData.toBase64String();
+//MochiKit.Logging.logDebug("<<< [" + (new Date()).valueOf() + "] Clipperz.PM.Crypto.versions[0.3].encrypt");
+
+ return result;
+ },
+
+ '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);
+
+ value = decryptedData.asString();
+/ *
+ value = value.replace(/":{l:"/g, '":{"label":"');
+ value = value.replace(/":{k:"/g, '":{"key":"');
+ value = value.replace(/":{n:"/g, '":{"notes":"');
+ value = value.replace(/":{r:"/g, '":{"record":"');
+ value = value.replace(/",l:"/g, '", "label":"');
+ value = value.replace(/",f:"/g, '", "favicon":"');
+* /
+ try {
+ result = Clipperz.Base.evalJSON(value);
+ } catch (exception) {
+ MochiKit.Logging.logError("Error while decrypting data");
+ throw Clipperz.Crypto.Base.exception.CorruptedMessage;
+ }
+
+
+ } else {
+ result = null;
+ }
+
+ return result;
+ },
+
+ 'hash': Clipperz.Crypto.SHA.sha_d256
+ },
+*/
+ //#####################################################################
+ __syntaxFix__: "syntax fix"
+ }
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'encrypt': function(aKey, aValue, aVersion) {
+ return Clipperz.PM.Crypto.encryptingFunctions.versions[aVersion].encrypt(aKey, aValue);
+ },
+
+ 'deferredEncrypt': function(aKey, aValue, aVersion) {
+ return Clipperz.PM.Crypto.encryptingFunctions.versions[aVersion].deferredEncrypt(aKey, aValue);
+ },
+
+ 'encryptWithCurrentVersion': function(aKey, aValue) {
+ return Clipperz.PM.Crypto.encrypt(aKey, aValue, Clipperz.PM.Crypto.encryptingFunctions.currentVersion);
+ },
+
+ 'deferredEncryptWithCurrentVersion': function(aKey, aValue) {
+ return Clipperz.PM.Crypto.deferredEncrypt(aKey, aValue, Clipperz.PM.Crypto.encryptingFunctions.currentVersion);
+ },
+
+ //.........................................................................
+
+ 'decrypt': function(aKey, aValue, aVersion) {
+ return Clipperz.PM.Crypto.encryptingFunctions.versions[aVersion].decrypt(aKey, aValue);
+ },
+
+ 'deferredDecrypt': function(aKey, aValue, aVersion) {
+ return Clipperz.PM.Crypto.encryptingFunctions.versions[aVersion].deferredDecrypt(aKey, aValue);
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'randomKey': function() {
+ return Clipperz.Crypto.PRNG.defaultRandomGenerator().getRandomBytes(32).toHexString().substring(2);
+ },
+
+ //-------------------------------------------------------------------------
+
+ '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 ++;
+ }
+//MochiKit.Logging.logDebug("--- bitPerChar: " + bitPerChar);
+
+ result = aValue.length * bitPerChar;
+
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'nullValue': "####",
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+
+});
+
+//*****************************************************************************
+
+MochiKit.Base.update(Clipperz.PM.Crypto.communicationProtocol.versions, {
+ 'current': Clipperz.PM.Crypto.communicationProtocol.versions[Clipperz.PM.Crypto.communicationProtocol.currentVersion]
+});
+
+MochiKit.Base.update(Clipperz.PM.Crypto.encryptingFunctions.versions, {
+ 'current': Clipperz.PM.Crypto.encryptingFunctions.versions[Clipperz.PM.Crypto.encryptingFunctions.currentVersion]
+});
+
+//*****************************************************************************
diff --git a/frontend/beta/js/Clipperz/PM/DataModel/DirectLogin.js b/frontend/beta/js/Clipperz/PM/DataModel/DirectLogin.js
new file mode 100644
index 0000000..3ebc208
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/DataModel/DirectLogin.js
@@ -0,0 +1,536 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. 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.DirectLogin = function(args) {
+//MochiKit.Logging.logDebug(">>> new Clipperz.PM.DataModel.DirectLogin");
+//console.log(">>> new Clipperz.PM.DataModel.DirectLogin - args: %o", args);
+//console.log("--- formData: %s", Clipperz.Base.serializeJSON(args.formData));
+ args = args || {};
+
+//MochiKit.Logging.logDebug("--- new Clipperz.PM.DataModel.DirectLogin - args: " + Clipperz.Base.serializeJSON(MochiKit.Base.keys(args)));
+ this._record = args.record || null;
+ this._label = args.label || "unnamed record"
+ this._reference = args.reference || Clipperz.PM.Crypto.randomKey();
+ this._favicon = args.favicon || null;
+ this._bookmarkletVersion = args.bookmarkletVersion || "0.1";
+
+ this._directLoginInputs = null;
+
+ this._formValues = args.formValues || {};
+ this.setFormData(args.formData || null);
+//console.log("=== formData: %o", this.formData());
+
+ if (args.legacyBindingData == null) {
+ this.setBindingData(args.bindingData || null);
+ } else {
+ this.setLegacyBindingData(args.legacyBindingData);
+ }
+
+ this._fixedFavicon = null;
+
+// this._formValues = args.formValues || (this.hasValuesToSet() ? {} : null);
+//MochiKit.Logging.logDebug("<<< new Clipperz.PM.DataModel.DirectLogin");
+
+ return this;
+}
+
+Clipperz.PM.DataModel.DirectLogin.prototype = MochiKit.Base.update(null, {
+
+ 'remove': function() {
+ this.record().removeDirectLogin(this);
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'record': function() {
+ return this._record;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'user': function() {
+ return this.record().user();
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'reference': function() {
+ return this._reference;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'label': function() {
+ return this._label;
+ },
+
+ 'setLabel': function(aValue) {
+ this._label = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'favicon': function() {
+ if (this._favicon == null) {
+ var actionUrl;
+ var hostname;
+
+ actionUrl = this.formData()['attributes']['action'];
+ hostname = actionUrl.replace(/^https?:\/\/([^\/]*)\/.*/, '$1');
+ this._favicon = "http://" + hostname + "/favicon.ico";
+ }
+
+ return this._favicon;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'fixedFavicon': function() {
+ var result;
+
+ if (this._fixedFavicon == null) {
+ result = this.favicon();
+
+ if (Clipperz_IEisBroken) {
+ if (this.user().preferences().disableUnsecureFaviconLoadingForIE()) {
+ if (result.indexOf('https://') != 0) {
+ result = Clipperz.PM.Strings['defaultFaviconUrl_IE'];
+ this.setFixedFavicon(result);
+ }
+ }
+ }
+ } else {
+ result = this._fixedFavicon;
+ }
+
+ return result;
+ },
+
+ 'setFixedFavicon': function(aValue) {
+ this._fixedFavicon = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'bookmarkletVersion': function() {
+ return this._bookmarkletVersion;
+ },
+
+ 'setBookmarkletVersion': function(aValue) {
+ this._bookmarkletVersion = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'formData': function() {
+ return this._formData;
+ },
+
+ 'setFormData': function(aValue) {
+ var formData;
+
+//MochiKit.Logging.logDebug(">>> DirectLogin.setFormData - " + Clipperz.Base.serializeJSON(aValue));
+ switch (this.bookmarkletVersion()) {
+ case "0.2":
+ formData = aValue;
+ break;
+ case "0.1":
+//MochiKit.Logging.logDebug("--- DirectLogin.setFormData - fixing form data from bookmarklet version 0.1");
+ formData = this.fixFormDataFromBookmarkletVersion_0_1(aValue);
+ break;
+ }
+
+ this._formData = aValue;
+ this.setBookmarkletVersion("0.2");
+
+//MochiKit.Logging.logDebug("--- DirectLogin.setFormData - formData: " + Clipperz.Base.serializeJSON(formData));
+ if (formData != null) {
+ var i,c;
+
+ this._directLoginInputs = [];
+ c = formData['inputs'].length;
+ for (i=0; i<c; i++) {
+ var directLoginInput;
+
+ directLoginInput = new Clipperz.PM.DataModel.DirectLoginInput(this, formData['inputs'][i]);
+ this._directLoginInputs.push(directLoginInput);
+ }
+ }
+//MochiKit.Logging.logDebug("<<< DirectLogin.setFormData");
+ },
+
+ 'fixFormDataFromBookmarkletVersion_0_1': function(aValue) {
+//{"type":"radio", "name":"action", "value":"new-user", "checked":false }, { "type":"radio", "name":"action", "value":"sign-in", "checked":true }
+// ||
+// \ /
+// \/
+//{"name":"dominio", "type":"radio", "options":[{"value":"@alice.it", "checked":true}, {"value":"@tin.it", "checked":false}, {"value":"@virgilio.it", "checked":false}, {"value":"@tim.it", "checked":false}]}
+ var result;
+ var inputs;
+ var updatedInputs;
+ var radios;
+
+//MochiKit.Logging.logDebug(">>> DirectLogin.fixFormDataFromBookmarkletVersion_0_1");
+ result = aValue;
+ inputs = aValue['inputs'];
+
+ updatedInputs = MochiKit.Base.filter(function(anInput) {
+ var result;
+ var type;
+
+ type = anInput['type'] || 'text';
+ result = type.toLowerCase() != 'radio';
+
+ return result;
+ }, inputs);
+ radios = MochiKit.Base.filter(function(anInput) {
+ var result;
+ var type;
+
+ type = anInput['type'] || 'text';
+ result = type.toLowerCase() == 'radio';
+
+ return result;
+ }, inputs);
+
+ if (radios.length > 0) {
+ var updatedRadios;
+
+ updatedRadios = {};
+ MochiKit.Iter.forEach(radios, MochiKit.Base.bind(function(aRadio) {
+ var radioConfiguration;
+
+ radioConfiguration = updatedRadios[aRadio['name']];
+ if (radioConfiguration == null) {
+ radioConfiguration = {type:'radio', name:aRadio['name'], options:[]};
+ updatedRadios[aRadio['name']] = radioConfiguration;
+ }
+
+// TODO: remove the value: field and replace it with element.dom.value = <some value>
+ radioConfiguration.options.push({value:aRadio['value'], checked:aRadio['checked']});
+
+ if ((aRadio['checked'] == true) && (this.formValues()[aRadio['name']] == null)) {
+//MochiKit.Logging.logDebug("+++ setting value '" + aRadio['value'] + "' for key: '" + aRadio['name'] + "'");
+ this.formValues()[aRadio['name']] = aRadio['value'];
+ }
+ }, this))
+
+ updatedInputs = MochiKit.Base.concat(updatedInputs, MochiKit.Base.values(updatedRadios));
+ }
+
+ delete result.inputs;
+ result.inputs = updatedInputs;
+//MochiKit.Logging.logDebug("<<< DirectLogin.fixFormDataFromBookmarkletVersion_0_1");
+
+ return result;
+ },
+
+ //.........................................................................
+
+ 'directLoginInputs': function() {
+ return this._directLoginInputs;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'formValues': function() {
+ return this._formValues;
+ },
+
+ 'hasValuesToSet': function() {
+ var result;
+
+//MochiKit.Logging.logDebug(">>> DirectLogin.hasValuesToSet");
+ if (this.directLoginInputs() != null) {
+ result = MochiKit.Iter.some(this.directLoginInputs(), MochiKit.Base.methodcaller('shouldSetValue'));
+ } else {
+ result = false;
+ }
+//MochiKit.Logging.logDebug("<<< DirectLogin.hasValuesToSet");
+
+ return result;
+ },
+
+// 'additionalValues': function() {
+ 'inputsRequiringAdditionalValues': function() {
+ var result;
+ var inputs;
+
+//MochiKit.Logging.logDebug(">>> DirectLogin.additionalValues");
+ result = {};
+ if (this.directLoginInputs() != null) {
+ inputs = MochiKit.Base.filter(MochiKit.Base.methodcaller('shouldSetValue'), this.directLoginInputs());
+ MochiKit.Iter.forEach(inputs, function(anInput) {
+ result[anInput.name()] = anInput;
+ })
+ }
+//MochiKit.Logging.logDebug("<<< DirectLogin.additionalValues");
+
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'bindingData': function() {
+ return this._bindingData;
+ },
+
+ 'setBindingData': function(aValue) {
+//MochiKit.Logging.logDebug(">>> DirectLogin.setBindingData");
+ if (aValue != null) {
+ var bindingKey;
+
+ this._bindingData = aValue;
+ this._bindings = {};
+
+ for (bindingKey in aValue) {
+ var directLoginBinding;
+
+ directLoginBinding = new Clipperz.PM.DataModel.DirectLoginBinding(this, bindingKey, {fieldKey:aValue[bindingKey]});
+ this._bindings[bindingKey] = directLoginBinding;
+ }
+ } else {
+ var editableFields;
+ var bindings;
+
+ bindings = {};
+
+ 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.formData().inputs);
+
+ MochiKit.Iter.forEach(editableFields, function(anEditableField) {
+ bindings[anEditableField['name']] = new Clipperz.PM.DataModel.DirectLoginBinding(this, anEditableField['name']);
+ }, this);
+
+ this._bindings = bindings;
+ }
+//MochiKit.Logging.logDebug("<<< DirectLogin.setBindingData");
+ },
+
+ 'setLegacyBindingData': function(aValue) {
+//MochiKit.Logging.logDebug(">>> DirectLogin.setLegacyBindingData");
+ var bindingKey;
+
+ this._bindingData = aValue;
+ this._bindings = {};
+
+ for (bindingKey in aValue) {
+ var directLoginBinding;
+
+ directLoginBinding = new Clipperz.PM.DataModel.DirectLoginBinding(this, bindingKey, {fieldName:aValue[bindingKey]});
+ this._bindings[bindingKey] = directLoginBinding;
+ }
+//MochiKit.Logging.logDebug("<<< DirectLogin.setLegacyBindingData");
+ },
+
+ //.........................................................................
+
+ 'bindings': function() {
+ return this._bindings;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'serializedData': function() {
+ var result;
+ var bindingKey;
+
+ result = {};
+// result.reference = this.reference();
+ result.label = this.label();
+ result.favicon = this.favicon() || "";
+ result.bookmarkletVersion = this.bookmarkletVersion();
+ result.formData = this.formData();
+ if (this.hasValuesToSet) {
+ result.formValues = this.formValues();
+ }
+ result.bindingData = {};
+
+ for (bindingKey in this.bindings()) {
+ result.bindingData[bindingKey] = this.bindings()[bindingKey].serializedData();
+ }
+
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'handleMissingFaviconImage': function(anEvent) {
+ anEvent.stop();
+ MochiKit.Signal.disconnectAll(anEvent.src());
+ this.setFixedFavicon(Clipperz.PM.Strings['defaultFaviconUrl']);
+ anEvent.src().src = this.fixedFavicon();
+ },
+
+ //=========================================================================
+
+ 'runHttpAuthDirectLogin': function(aWindow) {
+ MochiKit.DOM.withWindow(aWindow, MochiKit.Base.bind(function() {
+ var completeUrl;
+ var url;
+
+ url = this.bindings()['url'].field().value();
+
+ if (/^https?\:\/\//.test(url) == false) {
+ url = 'http://' + url;
+ }
+
+ if (Clipperz_IEisBroken === true) {
+ completeUrl = url;
+ } else {
+ var username;
+ var password;
+
+ username = this.bindings()['username'].field().value();
+ password = this.bindings()['password'].field().value();
+
+ /(^https?\:\/\/)?(.*)/.test(url);
+
+ completeUrl = RegExp.$1 + username + ':' + password + '@' + RegExp.$2;
+ }
+
+ MochiKit.DOM.currentWindow().location.href = completeUrl;
+ }, this));
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'runSubmitFormDirectLogin': function(aWindow) {
+ MochiKit.DOM.withWindow(aWindow, MochiKit.Base.bind(function() {
+ var formElement;
+ var formSubmitFunction;
+ var submitButtons;
+
+//MochiKit.Logging.logDebug("### runDirectLogin - 3");
+// MochiKit.DOM.currentDocument().write('<html><head><title>' + this.label() + '</title><META http-equiv="Content-Type" content="text/html; charset=utf-8" /></head><body></body></html>')
+//MochiKit.Logging.logDebug("### runDirectLogin - 3.1");
+ MochiKit.DOM.appendChildNodes(MochiKit.DOM.currentDocument().body, MochiKit.DOM.H3(null, "Loading " + this.label() + " ..."));
+//MochiKit.Logging.logDebug("### runDirectLogin - 4");
+//console.log(this.formData()['attributes']);
+ formElement = MochiKit.DOM.FORM(MochiKit.Base.update({id:'directLoginForm'}, { 'method':this.formData()['attributes']['method'],
+ 'action':this.formData()['attributes']['action']}));
+//MochiKit.Logging.logDebug("### runDirectLogin - 5");
+ formSubmitFunction = MochiKit.Base.method(formElement, 'submit');
+//MochiKit.Logging.logDebug("### runDirectLogin - 6");
+
+ MochiKit.DOM.appendChildNodes(MochiKit.DOM.currentDocument().body,
+ MochiKit.DOM.DIV({style:'display:none; visibility:hidden;'}, formElement)
+ );
+//MochiKit.Logging.logDebug("### runDirectLogin - 7");
+ MochiKit.DOM.appendChildNodes(formElement, MochiKit.Base.map( MochiKit.Base.methodcaller("formConfiguration"),
+ this.directLoginInputs()));
+//MochiKit.Logging.logDebug("### runDirectLogin - 8");
+
+ submitButtons = MochiKit.Base.filter(function(anInputElement) {
+//MochiKit.Logging.logDebug("### runDirectLogin - 8.1 - " + anInputElement);
+//MochiKit.Logging.logDebug("### runDirectLogin - 8.2 - " + anInputElement.tagName);
+//MochiKit.Logging.logDebug("### runDirectLogin - 8.3 - " + anInputElement.getAttribute('type'));
+ return ((anInputElement.tagName.toLowerCase() == 'input') && (anInputElement.getAttribute('type').toLowerCase() == 'submit'));
+ }, formElement.elements)
+//MochiKit.Logging.logDebug("### runDirectLogin - 9");
+
+ if (submitButtons.length == 0) {
+//MochiKit.Logging.logDebug("### OLD submit")
+ if (Clipperz_IEisBroken == true) {
+//MochiKit.Logging.logDebug("### runDirectLogin - 10");
+ formElement.submit();
+ } else {
+//MochiKit.Logging.logDebug("### runDirectLogin - 11");
+ formSubmitFunction();
+ }
+ } else {
+//MochiKit.Logging.logDebug("### NEW submit")
+ submitButtons[0].click();
+ }
+
+ }, this));
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'runDirectLogin': function(aNewWindow) {
+ var newWindow;
+
+//console.log("formData.attributes", this.formData()['attributes']);
+// if (/^javascript/.test(this.formData()['attributes']['action'])) {
+ if ((/^(https?|webdav|ftp)\:/.test(this.formData()['attributes']['action']) == false) &&
+ (this.formData()['attributes']['type'] != 'http_auth'))
+ {
+ var messageBoxConfiguration;
+
+ if (typeof(aNewWindow) != 'undefined') {
+ aNewWindow.close();
+ }
+
+ messageBoxConfiguration = {};
+ messageBoxConfiguration.title = Clipperz.PM.Strings['VulnerabilityWarning_Panel_title'];
+ messageBoxConfiguration.msg = Clipperz.PM.Strings['VulnerabilityWarning_Panel_message'];
+ messageBoxConfiguration.animEl = YAHOO.ext.Element.get("mainDiv");
+ messageBoxConfiguration.progress = false;
+ messageBoxConfiguration.closable = false;
+ messageBoxConfiguration.buttons = {'cancel': Clipperz.PM.Strings['VulnerabilityWarning_Panel_buttonLabel']};
+
+ Clipperz.YUI.MessageBox.show(messageBoxConfiguration);
+
+ throw Clipperz.Base.exception.VulnerabilityIssue;
+ }
+
+//MochiKit.Logging.logDebug("### runDirectLogin - 1 : " + Clipperz.Base.serializeJSON(this.serializedData()));
+ if (typeof(aNewWindow) == 'undefined') {
+ newWindow = window.open(Clipperz.PM.Strings['directLoginJumpPageUrl'], "");
+ } else {
+ newWindow = aNewWindow;
+ }
+//MochiKit.Logging.logDebug("### runDirectLogin - 2");
+
+ if (this.formData()['attributes']['type'] == 'http_auth') {
+ this.runHttpAuthDirectLogin(newWindow);
+ } else {
+ this.runSubmitFormDirectLogin(newWindow)
+ }
+ },
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+
+});
+
diff --git a/frontend/beta/js/Clipperz/PM/DataModel/DirectLoginBinding.js b/frontend/beta/js/Clipperz/PM/DataModel/DirectLoginBinding.js
new file mode 100644
index 0000000..19aa9cb
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/DataModel/DirectLoginBinding.js
@@ -0,0 +1,113 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. 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, aKey, args) {
+//MochiKit.Logging.logDebug(">>> new DirectLoginBinding")
+ args = args || {};
+//MochiKit.Logging.logDebug("--- new DirectLoginBinding - args: " + Clipperz.Base.serializeJSON(args));
+
+ this._directLogin = aDirectLogin || args.directLogin || null;
+ this._key = aKey;
+
+ this._fieldKey = args.fieldKey || null;
+ this._fieldName = args.fieldName || null;
+//MochiKit.Logging.logDebug("<<< new DirectLoginBinding")
+
+ return this;
+}
+
+Clipperz.PM.DataModel.DirectLoginBinding.prototype = MochiKit.Base.update(null, {
+
+ 'directLogin': function() {
+ return this._directLogin;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'key': function() {
+ return this._key;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'fieldKey': function() {
+//MochiKit.Logging.logDebug("=== Clipperz.PM.DataModel.DirectLoginBinding.fieldKey");
+//MochiKit.Logging.logDebug("=== Clipperz.PM.DataModel.DirectLoginBinding.fieldKey - " + this._fieldKey);
+ return this._fieldKey;
+ },
+
+ 'setFieldKey': function(aValue) {
+ this._fieldKey = aValue;
+ },
+
+ 'fieldName': function() {
+ return this._fieldName;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'field': function() {
+ var result;
+
+//MochiKit.Logging.logDebug(">>> Clipperz.PM.DataModel.DirectLoginBinding.field")
+//MochiKit.Logging.logDebug("--- Clipperz.PM.DataModel.DirectLoginBinding.field - 1 - this.fieldKey(): " + this.fieldKey());
+//MochiKit.Logging.logDebug("--- Clipperz.PM.DataModel.DirectLoginBinding.field - 2 - this.fieldName(): " + this.fieldName());
+ if (this.fieldKey() != null) {
+ result = this.directLogin().record().currentVersion().fields()[this.fieldKey()];
+//MochiKit.Logging.logDebug("--- Clipperz.PM.DataModel.DirectLoginBinding.field - 3 - result: " + result);
+ } else if (this.fieldName() != null) {
+ result = this.directLogin().record().currentVersion().fieldWithName(this.fieldName());
+//MochiKit.Logging.logDebug("--- Clipperz.PM.DataModel.DirectLoginBinding.field - 4 - result: " + result);
+
+ this.setFieldKey(result.key());
+ } else {
+ result = null;
+ }
+//MochiKit.Logging.logDebug("<<< Clipperz.PM.DataModel.DirectLoginBinding.field")
+
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'serializedData': function() {
+ return this.fieldKey();
+ },
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+
+});
+
diff --git a/frontend/beta/js/Clipperz/PM/DataModel/DirectLoginInput.js b/frontend/beta/js/Clipperz/PM/DataModel/DirectLoginInput.js
new file mode 100644
index 0000000..3302ed6
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/DataModel/DirectLoginInput.js
@@ -0,0 +1,229 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. 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(aDirectLogin, args) {
+ args = args || {};
+
+//console.log(">>> new DirectLoginInput - args: %o" + args);
+ this._directLogin = aDirectLogin;
+ this._args = args;
+
+ return this;
+}
+
+Clipperz.PM.DataModel.DirectLoginInput.prototype = MochiKit.Base.update(null, {
+
+ 'directLogin': function() {
+ return this._directLogin;
+ },
+
+ //-------------------------------------------------------------------------
+
+ '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;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'value': function() {
+ return this.args()['value'];
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'formConfiguration': function() {
+ var result;
+
+//MochiKit.Logging.logDebug(">>> DirectLoginInput.formConfiguration - " + this.name());
+ if (this.shouldSetValue()) {
+//MochiKit.Logging.logDebug("--- DirectLoginInput.formConfiguration - 1");
+ switch (this.type()) {
+ case 'select':
+ var currentValue;
+ var options;
+
+//MochiKit.Logging.logDebug("--- DirectLoginInput.formConfiguration - 2");
+ currentValue = this.directLogin().formValues()[this.name()];
+//MochiKit.Logging.logDebug("--- DirectLoginInput.formConfiguration - 2.1");
+ options = this.args()['options'];
+//MochiKit.Logging.logDebug("--- DirectLoginInput.formConfiguration - 2.2");
+
+ result = MochiKit.DOM.SELECT({name:this.name()},
+ MochiKit.Base.map(function(anOption) {
+ var options;
+
+//MochiKit.Logging.logDebug("--- DirectLoginInput.formConfiguration - 2.3");
+// TODO: remove the value: field and replace it with element.dom.value = <some value>
+ options = {value:anOption['value']};
+//MochiKit.Logging.logDebug("--- DirectLoginInput.formConfiguration - 2.4");
+ if (currentValue == anOption['value']) {
+//MochiKit.Logging.logDebug("--- DirectLoginInput.formConfiguration - 2.5");
+ options.selected = true;
+//MochiKit.Logging.logDebug("--- DirectLoginInput.formConfiguration - 2.6");
+ }
+//MochiKit.Logging.logDebug("--- DirectLoginInput.formConfiguration - 2.7");
+
+ return MochiKit.DOM.OPTION(options, anOption['label'])
+ }, options)
+ )
+//MochiKit.Logging.logDebug("--- DirectLoginInput.formConfiguration - 2.8");
+ break;
+ case 'checkbox':
+ var options;
+
+//MochiKit.Logging.logDebug("--- DirectLoginInput.formConfiguration - 3");
+ options = {type:'checkbox', name: this.name()};
+ if (this.directLogin().formValues()[this.name()] == true) {
+ options['checked'] = true;
+ };
+
+ result = MochiKit.DOM.INPUT(options, null);
+ break;
+ case 'radio':
+ var currentName;
+ var currentValue;
+ var options;
+
+//MochiKit.Logging.logDebug("--- DirectLoginInput.formConfiguration - 4");
+ currentName = this.name();
+//MochiKit.Logging.logDebug("--- DirectLoginInput.formConfiguration - 4.1");
+ currentValue = this.directLogin().formValues()[this.name()];
+//MochiKit.Logging.logDebug("--- DirectLoginInput.formConfiguration - 4.2");
+ options = this.args()['options'];
+//MochiKit.Logging.logDebug("--- DirectLoginInput.formConfiguration - 4.3");
+
+ result = MochiKit.DOM.DIV(null,
+ MochiKit.Base.map(function(anOption) {
+ var options;
+ var isChecked;
+ var inputNode;
+ var divNode;
+
+//MochiKit.Logging.logDebug("--- DirectLoginInput.formConfiguration - 4.4");
+// TODO: remove the value: field and replace it with element.dom.value = <some value>
+ options = {type:'radio', name:currentName, value:anOption['value']}
+ isChecked = (currentValue == anOption['value']);
+//MochiKit.Logging.logDebug("--- DirectLoginInput.formConfiguration - 4.5");
+ if (isChecked) {
+//MochiKit.Logging.logDebug("--- DirectLoginInput.formConfiguration - 4.6");
+ options.checked = true;
+//MochiKit.Logging.logDebug("--- DirectLoginInput.formConfiguration - 4.7");
+ }
+//MochiKit.Logging.logDebug("--- DirectLoginInput.formConfiguration - 4.8 - options: " + Clipperz.Base.serializeJSON(options));
+//MochiKit.Logging.logDebug("--- DirectLoginInput.formConfiguration - 4.8 - value: " + anOption['value']);
+
+ if (Clipperz_IEisBroken == true) {
+ var checkedValue;
+
+//MochiKit.Logging.logDebug("--- DirectLoginInput.formConfiguration - 4.8.1");
+ checkedValue = (isChecked ? " CHECKED" : "");
+//MochiKit.Logging.logDebug("--- DirectLoginInput.formConfiguration - 4.8.2");
+ inputNode = MochiKit.DOM.currentDocument().createElement("<INPUT TYPE='RADIO' NAME='" + currentName + "' VALUE='" + anOption['value'] + "'" + checkedValue + ">");
+//MochiKit.Logging.logDebug("--- DirectLoginInput.formConfiguration - 4.8.3");
+ } else {
+//MochiKit.Logging.logDebug("--- DirectLoginInput.formConfiguration - 4.8.4");
+ inputNode = MochiKit.DOM.INPUT(options, anOption['value']);
+//MochiKit.Logging.logDebug("--- DirectLoginInput.formConfiguration - 4.8.5");
+ }
+//MochiKit.Logging.logDebug("--- DirectLoginInput.formConfiguration - 4.9");
+ divNode = MochiKit.DOM.DIV(null, inputNode);
+//MochiKit.Logging.logDebug("--- DirectLoginInput.formConfiguration - 4.10");
+
+ return divNode;
+// return MochiKit.DOM.DIV(null, MochiKit.DOM.INPUT(options, anOption['value']));
+ }, options)
+ );
+//MochiKit.Logging.logDebug("--- DirectLoginInput.formConfiguration - 4.9");
+ break;
+ }
+ } else {
+ var binding;
+//MochiKit.Logging.logDebug("--- DirectLoginInput.formConfiguration - 5");
+ binding = this.directLogin().bindings()[this.name()];
+
+//MochiKit.Logging.logDebug("--- DirectLoginInput.formConfiguration - 6");
+// TODO: remove the value: field and replace it with element.dom.value = <some value>
+ result = MochiKit.DOM.INPUT({
+ type:((this.type() != 'password') ? this.type() : 'text'),
+// type:(((this.type() != 'password') && (this.type() != 'submit')) ? this.type() : 'text'),
+ name:this.name(),
+ value:((binding != null)? binding.field().value() : this.value())
+ }, null);
+//MochiKit.Logging.logDebug("--- DirectLoginInput.formConfiguration - 7");
+ }
+
+//MochiKit.Logging.logDebug("<<< DirectLoginInput.formConfiguration: ");
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'shouldSetValue': function() {
+ var type;
+ var result;
+
+//MochiKit.Logging.logDebug(">>> DirectLoginInput.shouldSetValue");
+ type = this.type();
+ result = ((type == 'checkbox') || (type == 'radio') || (type == 'select'));
+//if (result == true) {
+// MochiKit.Logging.logDebug("DIRECT LOGIN INPUT need value: " + Clipperz.Base.serializeJSON(this.args()));
+//}
+//MochiKit.Logging.logDebug("<<< DirectLoginInput.shouldSetValue");
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+
+});
+
diff --git a/frontend/beta/js/Clipperz/PM/DataModel/DirectLoginReference.js b/frontend/beta/js/Clipperz/PM/DataModel/DirectLoginReference.js
new file mode 100644
index 0000000..b067a21
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/DataModel/DirectLoginReference.js
@@ -0,0 +1,192 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. 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.DirectLoginReference = function(args) {
+ args = args || {};
+
+//MochiKit.Logging.logDebug(">>> new DirectLoginReference: " + Clipperz.Base.serializeJSON(MochiKit.Base.keys(args)));
+//MochiKit.Logging.logDebug(">>> new DirectLoginReference - record: " + args.record);
+ this._user = args.user;
+
+ if (args.directLogin != null) {
+ this._reference = args.directLogin.reference();
+ this._recordReference = args.directLogin.record().reference();
+ this._label = args.directLogin.label();
+ this._favicon = args.directLogin.favicon() || null;
+
+ this._directLogin = args.directLogin;
+ this._record = args.directLogin.record();
+ } else {
+ this._reference = args.reference;
+ this._recordReference = args.record;
+ this._label = args.label;
+ this._favicon = args.favicon || null;
+
+ this._directLogin = null;
+ this._record = null;
+ }
+
+ this._fixedFavicon = null;
+
+ return this;
+}
+
+Clipperz.PM.DataModel.DirectLoginReference.prototype = MochiKit.Base.update(null, {
+
+ 'user': function() {
+ return this._user;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'reference': function() {
+ return this._reference;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'synchronizeValues': function(aDirectLogin) {
+ this._label = aDirectLogin.label();
+ this._favicon = aDirectLogin.favicon();
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'label': function() {
+ return this._label;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'recordReference': function() {
+ return this._recordReference;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'record': function() {
+//MochiKit.Logging.logDebug(">>> DirectLoginReference.record");
+ if (this._record == null) {
+ this._record = this.user().records()[this.recordReference()];
+ }
+
+//MochiKit.Logging.logDebug("<<< DirectLoginReference.record");
+ return this._record;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'favicon': function() {
+ return this._favicon;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'fixedFavicon': function() {
+ var result;
+
+ if (this._fixedFavicon == null) {
+ result = this.favicon();
+
+ if (Clipperz_IEisBroken && (this.user().preferences().disableUnsecureFaviconLoadingForIE()) && (result.indexOf('https://') != 0)) {
+ result = Clipperz.PM.Strings['defaultFaviconUrl_IE'];
+ this.setFixedFavicon(result);
+ }
+ } else {
+ result = this._fixedFavicon;
+ }
+
+ return result;
+ },
+
+ 'setFixedFavicon': function(aValue) {
+ this._fixedFavicon = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'setupJumpPageWindow': function(aWindow) {
+//MochiKit.Logging.logDebug(">>> DirectLoginReference.setupJumpPageWindow - " + aWindow);
+ try {
+ MochiKit.DOM.withWindow(aWindow, MochiKit.Base.bind(function() {
+ MochiKit.DOM.appendChildNodes(MochiKit.DOM.currentDocument().body,
+ MochiKit.DOM.H1(null, "Loading " + this.label())
+ );
+ }, this));
+ } catch(e) {
+ MochiKit.Logging.logDebug("EXCEPTION: " + e);
+ }
+//MochiKit.Logging.logDebug("<<< DirectLoginReference.setupJumpPageWindow");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'deferredDirectLogin': function() {
+ var deferredResult;
+
+//MochiKit.Logging.logDebug(">>> DirectLoginReference.deferredDirectLogin - " + this);
+ deferredResult = new MochiKit.Async.Deferred();
+//MochiKit.Logging.logDebug("--- DirectLoginReference.deferredDirectLogin - 1");
+ deferredResult.addCallback(MochiKit.Base.method(this.record(), 'deferredData'));
+//MochiKit.Logging.logDebug("--- DirectLoginReference.deferredDirectLogin - 2");
+ deferredResult.addCallback(function(aRecord, aDirectLoginReference) {
+ return aRecord.directLogins()[aDirectLoginReference];
+ }, this.record(), this.reference());
+//MochiKit.Logging.logDebug("--- DirectLoginReference.deferredDirectLogin - 3");
+ deferredResult.callback();
+//MochiKit.Logging.logDebug("<<< DirectLoginReference.deferredDirectLogin");
+
+ return deferredResult;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'handleMissingFaviconImage': function(anEvent) {
+//MochiKit.Logging.logDebug(">>> DirectLoginReference.handleMissingFaviconImage");
+ anEvent.stop();
+ MochiKit.Signal.disconnectAll(anEvent.src());
+ this.setFixedFavicon(Clipperz.PM.Strings['defaultFaviconUrl']);
+//MochiKit.Logging.logDebug("--- DirectLoginReference.handleMissingFaviconImage - fixedFavicon: " + this.fixedFavicon());
+//MochiKit.Logging.logDebug("--- DirectLoginReference.handleMissingFaviconImage - anEvent.src().src: " + anEvent.src().src);
+// MochiKit.DOM.swapDOM(anEvent.src(), MochiKit.DOM.IMG({src:'this.fixedFavicon()'}));
+ anEvent.src().src = this.fixedFavicon();
+//MochiKit.Logging.logDebug("<<< DirectLoginReference.handleMissingFaviconImage");
+ },
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+
+});
+
diff --git a/frontend/beta/js/Clipperz/PM/DataModel/Header.js b/frontend/beta/js/Clipperz/PM/DataModel/Header.js
new file mode 100644
index 0000000..ef34732
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/DataModel/Header.js
@@ -0,0 +1,751 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. 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.Header = function(args) {
+ args = args || {};
+
+ this._user = args.user;
+
+ this._serverData = null;
+ this._serverDataVersion = null;
+ this._jsonEvaledServerData = null;
+
+ this._decryptedLegacyServerData = null;
+ this._isDecryptingLegacyServerData = false;
+ this._decryptingLegacyServerDataPendingQueue = [];
+
+ this.resetUpdatedSections();
+
+ this._shouldLoadSections = {};
+
+ Clipperz.NotificationCenter.register(this.user(), 'updatedSection', this, 'updatedSectionHandler');
+
+ return this;
+}
+
+Clipperz.PM.DataModel.Header.prototype = MochiKit.Base.update(null, {
+
+ //-------------------------------------------------------------------------
+
+ 'user': function() {
+ return this._user;
+ },
+
+ //-------------------------------------------------------------------------
+ //-------------------------------------------------------------------------
+ //-------------------------------------------------------------------------
+ //-------------------------------------------------------------------------
+ //-------------------------------------------------------------------------
+ //-------------------------------------------------------------------------
+ //-------------------------------------------------------------------------
+ //-------------------------------------------------------------------------
+ //-------------------------------------------------------------------------
+
+ 'updatedSections': function() {
+ return this._updatedSections;
+ },
+
+ 'markSectionAsUpdated': function(aSectionName) {
+ this.updatedSections().push(aSectionName);
+ },
+
+ 'resetUpdatedSections': function() {
+ this._updatedSections = []
+ },
+
+ 'hasSectionBeenUpdated': function(aSectionName) {
+ return (this.updatedSections().join().indexOf(aSectionName) != -1);
+ },
+
+ 'cachedServerDataSection': function(aSectionName) {
+ return (this.hasSectionBeenUpdated(aSectionName)) ? {} : this.jsonEvaledServerData()[aSectionName];
+ },
+
+ 'updateAllSections': function() {
+ this.resetUpdatedSections();
+ this.markSectionAsUpdated('records');
+ this.markSectionAsUpdated('directLogins');
+ this.markSectionAsUpdated('preferences');
+ this.markSectionAsUpdated('oneTimePasswords');
+
+ return MochiKit.Async.succeed(this);
+ },
+
+ 'updatedSectionHandler': function(anEvent) {
+ this.markSectionAsUpdated(anEvent.parameters());
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'getObjectKeyIndex': function(anObject) {
+ var result;
+ var itemReference;
+ var index;
+
+ result = {};
+ index = 0;
+
+ for (itemReference in anObject) {
+ result[itemReference] = index.toString();
+ index ++;
+ }
+
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'serializedDataWithRecordAndDirectLoginIndexes': function(aRecordIndexes, aDirectLoginIndexs) {
+ var result;
+ var records;
+ var recordReference;
+
+//MochiKit.Logging.logDebug(">>> Header.serializedData");
+ result = {
+ 'records': {},
+ 'directLogins': {}
+ };
+
+ records = this.user().records();
+ for (recordReference in records) {
+ result['records'][aRecordIndexes[recordReference]] = this.user().records()[recordReference].headerData();
+ }
+
+ for (directLoginReference in this.user().directLoginReferences()) {
+ var currentDirectLogin;
+ var directLoginData;
+
+ currentDirectLogin = this.user().directLoginReferences()[directLoginReference];
+ if (aRecordIndexes[currentDirectLogin.recordReference()] != null) {
+ directLoginData = {
+// reference: currentDirectLogin.reference(),
+ record: aRecordIndexes[currentDirectLogin.recordReference()].toString(),
+ label: currentDirectLogin.label(),
+ favicon: currentDirectLogin.favicon() || ""
+ }
+
+ result['directLogins'][aDirectLoginIndexs[directLoginReference]] = directLoginData;
+ }
+
+ }
+//MochiKit.Logging.logDebug("<<< Header.serializedData - result: " + Clipperz.Base.serializeJSON(result));
+//MochiKit.Logging.logDebug("<<< Header.serializedData");
+
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'encryptedData': function() {
+ var deferredResult;
+ var recordIndex;
+ var directLoginIndex;
+ var serializedData;
+ var result;
+
+//MochiKit.Logging.logDebug(">>> [" + (new Date()).valueOf() + "] Header.encryptedData");
+//MochiKit.Logging.logDebug("### Header.encryptedData - " + Clipperz.Base.serializeJSON(this.updatedSections()));
+ result = {
+ 'records': this.cachedServerDataSection('records'),
+ 'directLogins': this.cachedServerDataSection('directLogins'),
+ 'preferences': this.cachedServerDataSection('preferences'),
+ 'oneTimePasswords': this.cachedServerDataSection('oneTimePasswords'),
+ 'version': '0.1'
+ };
+
+ if (this.hasSectionBeenUpdated('records')) {
+ recordIndex = this.getObjectKeyIndex(this.user().records());
+ result['records']['index'] = recordIndex;
+ } else {
+ recordIndex = result['records']['index'];
+ }
+
+ if (this.hasSectionBeenUpdated('directLogins')) {
+ directLoginIndex = this.getObjectKeyIndex(this.user().directLoginReferences());
+ result['directLogins']['index'] = directLoginIndex;
+ } else {
+ directLoginIndex = result['directLogins']['index'];
+ }
+
+ if (this.hasSectionBeenUpdated('records') || this.hasSectionBeenUpdated('directLogins')) {
+ serializedData = this.serializedDataWithRecordAndDirectLoginIndexes(recordIndex, directLoginIndex);
+ }
+
+ deferredResult = new MochiKit.Async.Deferred();
+
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.encryptedData - 1: " + res); return res;});
+ if (this.hasSectionBeenUpdated('records')) {
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.encryptedData - 1.1: " + res); return res;});
+ deferredResult.addCallback(function(anHeader, aResult, aSerializedData, aValue) {
+ return Clipperz.PM.Crypto.deferredEncryptWithCurrentVersion(anHeader.user().passphrase(), aSerializedData['records']);
+ }, this, result, serializedData);
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.encryptedData - 1.2: " + res); return res;});
+ deferredResult.addCallback(function(anHeader, aResult, aValue) {
+ aResult['records']['data'] = aValue;
+ }, this, result);
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.encryptedData - 1.3: " + res); return res;});
+ }
+
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.encryptedData - 2: " + res); return res;});
+ if (this.hasSectionBeenUpdated('directLogins')) {
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.encryptedData - 2.1: " + res); return res;});
+ deferredResult.addCallback(function(anHeader, aResult, aSerializedData, aValue) {
+ return Clipperz.PM.Crypto.deferredEncryptWithCurrentVersion(anHeader.user().passphrase(), aSerializedData['directLogins']);
+ }, this, result, serializedData);
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.encryptedData - 2.2: " + res); return res;});
+ deferredResult.addCallback(function(anHeader, aResult, aValue) {
+ aResult['directLogins']['data'] = aValue;
+ }, this, result);
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.encryptedData - 2.3: " + res); return res;});
+ }
+
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.encryptedData - 3: " + res); return res;});
+ if (this.hasSectionBeenUpdated('preferences')) {
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.encryptedData - 3.1: " + res); return res;});
+ deferredResult.addCallback(function(anHeader, aResult, aValue) {
+ return Clipperz.PM.Crypto.deferredEncryptWithCurrentVersion(anHeader.user().passphrase(), anHeader.user().preferences().serializedData());
+ }, this, result);
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.encryptedData - 3.2: " + res); return res;});
+ deferredResult.addCallback(function(anHeader, aResult, aValue) {
+ aResult['preferences']['data'] = aValue;
+ }, this, result);
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.encryptedData - 3.3: " + res); return res;});
+ }
+
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.encryptedData - 4: " + res); return res;});
+ if (this.hasSectionBeenUpdated('oneTimePasswords')) {
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.encryptedData - 4.1: " + res); return res;});
+// deferredResult.addCallback(MochiKit.Base.method(this, 'loadOneTimePasswords'));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.encryptedData - 4.2: " + res); return res;});
+ deferredResult.addCallback(function(anHeader, aResult, aValue) {
+ return Clipperz.PM.Crypto.deferredEncryptWithCurrentVersion(anHeader.user().passphrase(), anHeader.user().oneTimePasswordManager().serializedData());
+ }, this, result);
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.encryptedData - 4.3: " + res); return res;});
+ deferredResult.addCallback(function(anHeader, aResult, aValue) {
+ aResult['oneTimePasswords']['data'] = aValue;
+ }, this, result);
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.encryptedData - 4.4: " + res); return res;});
+ }
+
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.encryptedData - 5: " + res); return res;});
+ deferredResult.addCallback(function(anHeader, aResult, aValue) {
+ var serverData;
+
+ serverData = Clipperz.Base.serializeJSON(aResult);
+ anHeader.setServerData(serverData);
+
+ return serverData;
+ }, this, result);
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.encryptedData - 6: " + res); return res;});
+
+ deferredResult.callback();
+//MochiKit.Logging.logDebug("<<< [" + (new Date()).valueOf() + "] Header.encryptedData");
+
+ return deferredResult;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'serverData': function() {
+ return this._serverData;
+ },
+
+ 'setServerData': function(aValue) {
+//MochiKit.Logging.logDebug(">>> Header.setServerData");
+//MochiKit.Logging.logDebug("[start]=============================================");
+//MochiKit.Logging.logDebug("SERVER_DATA: " + aValue);
+//MochiKit.Logging.logDebug("[end]===============================================");
+ this._serverData = aValue;
+//MochiKit.Logging.logDebug("--- Header.setServerData - 1");
+ this.resetUpdatedSections();
+//MochiKit.Logging.logDebug("--- Header.setServerData - 2");
+ this.resetJsonEvaledServerData();
+//MochiKit.Logging.logDebug("<<< Header.setServerData");
+ },
+
+ 'jsonEvaledServerData': function() {
+ if (this._jsonEvaledServerData == null) {
+ this._jsonEvaledServerData = Clipperz.Base.evalJSON(this.serverData());
+ }
+
+ return this._jsonEvaledServerData;
+ },
+
+ 'resetJsonEvaledServerData': function() {
+ this._jsonEvaledServerData = null;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'serverDataVersion': function() {
+ return this._serverDataVersion;
+ },
+
+ 'setServerDataVersion': function(aValue) {
+ this._serverDataVersion = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'decryptedLegacyServerData': function() {
+ var deferredResult;
+
+//MochiKit.Logging.logDebug(">>> Header.decryptedLegacyServerData");
+ deferredResult = new MochiKit.Async.Deferred();
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.decryptedLegacyServerData 1: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(this, 'updateAllSections'));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.decryptedLegacyServerData 2: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+ if (this._decryptedLegacyServerData == null) {
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.decryptedLegacyServerData 3: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+ deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', 'connection_decryptingUserData');
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.decryptedLegacyServerData 4: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+ deferredResult.addCallback(Clipperz.PM.Crypto.deferredDecrypt, this.user().passphrase(), this.serverData(), this.serverDataVersion());
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.decryptedLegacyServerData 5: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+ deferredResult.addCallback(function(anHeader, aValue) {
+ anHeader._decryptedLegacyServerData = aValue;
+ }, this);
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.decryptedLegacyServerData 6: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+ };
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.decryptedLegacyServerData 7: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+
+ deferredResult.addCallback(function(anHeader) {
+ return anHeader._decryptedLegacyServerData;
+ }, this);
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.decryptedLegacyServerData 8: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+ deferredResult.callback();
+//MochiKit.Logging.logDebug("<<< Header.decryptedLegacyServerData");
+
+ return deferredResult;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'serverDataFormat': function() {
+ var result;
+
+//MochiKit.Logging.logDebug(">>> Header.serverDataFormat");
+ if (this.serverData().charAt(0) == '{') {
+ var serverData;
+
+ serverData = Clipperz.Base.evalJSON(this.serverData());
+ result = serverData['version'];
+ } else {
+ result = 'LEGACY';
+ }
+//MochiKit.Logging.logDebug("<<< Header.serverDataFormat");
+
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'extractHeaderDataFromUserDetails': function(someUserDetails) {
+ if (this.serverData() == null) {
+ this.setServerData(someUserDetails['header']);
+ this.setServerDataVersion(someUserDetails['version'])
+ }
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'extractDataWithKey': function(aKey) {
+ var deferredResult;
+
+//MochiKit.Logging.logDebug(">>> Header.extractDataWithKey");
+ deferredResult = new MochiKit.Async.Deferred();
+
+ switch (this.serverDataFormat()) {
+ case 'LEGACY':
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.extractDataWithKey 1: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(this, 'decryptedLegacyServerData'));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.extractDataWithKey 2: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+ deferredResult.addCallback(function(someDecryptedValues) {
+ return someDecryptedValues[aKey] || {};
+ })
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.extractDataWithKey 3: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+ break;
+ case '0.1':
+ var data;
+
+//# data = Clipperz.Base.evalJSON(this.serverData());
+ data = this.jsonEvaledServerData();
+ if (typeof(data[aKey]) != 'undefined') {
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.extractDataWithKey 4: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+ deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', 'connection_decryptingUserData');
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.extractDataWithKey 5: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+ deferredResult.addCallback(Clipperz.PM.Crypto.deferredDecrypt, this.user().passphrase(), data[aKey]['data'], this.serverDataVersion());
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.extractDataWithKey 6: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+ deferredResult.addCallback(function(/*anHeader,*/ aKey, aData, aRecordIndex, aValue) {
+ var result;
+//MochiKit.Logging.logDebug(">>> [start] ===============================================");
+//MochiKit.Logging.logDebug("--- extractDataWithKey - 0 [" + aKey + "]: " + Clipperz.Base.serializeJSON(aValue));
+//MochiKit.Logging.logDebug("<<< [end] =================================================");
+ if (aKey == 'records') {
+ var recordKey;
+
+ result = {};
+ for (recordKey in aData['index']) {
+ result[recordKey] = aValue[aData['index'][recordKey]];
+ }
+ } else if (aKey == 'directLogins') {
+ var recordKeyReversedIndex;
+ var recordKey;
+ var directLoginKey;
+
+ result = {};
+ recordKeyReversedIndex = {};
+
+ for (recordKey in aRecordIndex) {
+ recordKeyReversedIndex[aRecordIndex[recordKey]] = recordKey;
+ }
+
+//MochiKit.Logging.logDebug("--- extractDataWithKey - 1 - aData['index']: " + Clipperz.Base.serializeJSON(aData['index']));
+ for (directLoginKey in aData['index']) {
+try {
+ if ((aData['index'][directLoginKey] != null) && (aValue[aData['index'][directLoginKey]] != null)) {
+ result[directLoginKey] = aValue[aData['index'][directLoginKey]];
+ result[directLoginKey]['record'] = recordKeyReversedIndex[result[directLoginKey]['record']];
+ }
+} catch(exception) {
+ // result[directLoginKey] has no properties
+ MochiKit.Logging.logDebug("[Header 391] EXCEPTION: " + exception);
+ throw exception;
+}
+ }
+//MochiKit.Logging.logDebug("--- extractDataWithKey - 2");
+ } else {
+ result = aValue;
+ }
+
+ return result;
+ }, /*this,*/ aKey, data[aKey], data['records']['index']);
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.extractDataWithKey 6: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+ } else {
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.extractDataWithKey 7: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Async.succeed, {});
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.extractDataWithKey 8: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+ }
+ break;
+ }
+
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.extractDataWithKey 9: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+ deferredResult.callback();
+//MochiKit.Logging.logDebug("<<< Header.extractDataWithKey");
+
+ return deferredResult;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'processRecordData': function(someRecordData) {
+ var records;
+ var recordReference;
+
+//console.log("HeaderRecordData parameters", someRecordData);
+//MochiKit.Logging.logDebug(">>> Header.processRecordData");
+ records = someRecordData;
+//MochiKit.Logging.logDebug("--- Header.processRecordData - 1");
+ if (records != null) {
+//MochiKit.Logging.logDebug("--- Header.processRecordData - records: " + Clipperz.Base.serializeJSON(records));
+ for (recordReference in records) {
+ var newRecord;
+ var parameters;
+
+//MochiKit.Logging.logDebug("--- Header.processRecordData - 2 - recordReference: " + recordReference);
+ if (recordReference != "stacktrace") {
+ parameters = records[recordReference]; //.slice();
+//MochiKit.Logging.logDebug("--- Header.processRecordData - 3");
+ if (typeof(parameters['notes']) != 'undefined') {
+//MochiKit.Logging.logDebug("--- Header.processRecordData - 4");
+ if (parameters['notes'] != "") {
+//MochiKit.Logging.logDebug("--- Header.processRecordData - 5");
+ parameters['headerNotes'] = parameters['notes'];
+//MochiKit.Logging.logDebug("--- Header.processRecordData - 6");
+ }
+//MochiKit.Logging.logDebug("--- Header.processRecordData - 7");
+ delete parameters['notes'];
+//MochiKit.Logging.logDebug("--- Header.processRecordData - 8");
+ }
+//MochiKit.Logging.logDebug("--- Header.processRecordData - 9");
+ parameters['reference'] = recordReference;
+//MochiKit.Logging.logDebug("--- Header.processRecordData - 10");
+ parameters['user'] = this.user();
+//MochiKit.Logging.logDebug("--- Header.processRecordData - 11");
+
+ newRecord = new Clipperz.PM.DataModel.Record(parameters);
+//MochiKit.Logging.logDebug("--- Header.processRecordData - 12");
+ this.user().addRecord(newRecord, true);
+//MochiKit.Logging.logDebug("--- Header.processRecordData - 13");
+ }
+ }
+
+//MochiKit.Logging.logDebug("--- Header.processRecordData - 14");
+ Clipperz.NotificationCenter.notify(null, 'recordAdded', null, true);
+//MochiKit.Logging.logDebug("--- Header.processRecordData - 15");
+ }
+//MochiKit.Logging.logDebug("<<< Header.processRecordData");
+
+ return this.user().records();
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'processDirectLoginData': function(someDirectLoginData) {
+ var directLogins;
+ var directLoginReference;
+
+//MochiKit.Logging.logDebug(">>> Header.processDirectLoginData");
+ directLogins = someDirectLoginData;
+ if (directLogins != null) {
+ for (directLoginReference in directLogins) {
+ var directLoginReference;
+ var parameters;
+
+ parameters = directLogins[directLoginReference]; //.slice();
+ parameters.user = this.user();
+ parameters.reference = directLoginReference;
+ directLoginReference = new Clipperz.PM.DataModel.DirectLoginReference(parameters);
+ if (directLoginReference.record() != null) {
+ this.user().addDirectLoginReference(directLoginReference, true);
+ }
+ }
+ }
+
+ Clipperz.NotificationCenter.notify(null, 'directLoginAdded', null, true);
+//MochiKit.Logging.logDebug("<<< Header.processDirectLoginData");
+
+ return this.user().directLoginReferences();
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'shouldLoadSections': function() {
+ return this._shouldLoadSections;
+ },
+
+ 'shouldLoadSection': function(aSectionName) {
+ var result;
+
+ if (typeof(this.shouldLoadSections()[aSectionName]) != 'undefined') {
+ result = this.shouldLoadSections()[aSectionName];
+ } else {
+ result = true;
+ }
+
+ return result;
+ },
+
+ 'setShouldLoadSection': function(aSectionName, aValue) {
+ this.shouldLoadSections()[aSectionName] = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'loadRecords': function() {
+ var deferredResult;
+
+ if (this.shouldLoadSection('records') == true) {
+ this.setShouldLoadSection('records', false);
+
+ deferredResult = new MochiKit.Async.Deferred();
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.loadRecords 1: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(this.user(), 'getUserDetails'));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.loadRecords 2: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(this, 'extractHeaderDataFromUserDetails'));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.loadRecords 3: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(this, 'extractDataWithKey', 'records'));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.loadRecords 4: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(this, 'processRecordData'));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.loadRecords 5: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+ deferredResult.callback();
+ } else {
+ deferredResult = MochiKit.Async.succeed(this.user().records());
+ }
+
+ return deferredResult;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'loadDirectLogins': function() {
+ var deferredResult;
+
+ if (this.shouldLoadSection('directLogins') == true) {
+ this.setShouldLoadSection('directLogins', false);
+
+ deferredResult = new MochiKit.Async.Deferred();
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.loadDirectLogins - 1: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(this.user(), 'getUserDetails'));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.loadDirectLogins - 2: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(this, 'extractHeaderDataFromUserDetails'));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.loadDirectLogins - 3: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(this, 'extractDataWithKey', 'directLogins'));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.loadDirectLogins - 4: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(this, 'processDirectLoginData'));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.loadDirectLogins - 5: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+ deferredResult.callback();
+ } else {
+ deferredResult = MochiKit.Async.succeed(this.user().directLoginReferences());
+ }
+
+ return deferredResult;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'loadPreferences': function() {
+ var deferredResult;
+
+ if (this.shouldLoadSection('preferences') == true) {
+ this.setShouldLoadSection('preferences', false);
+
+ deferredResult = new MochiKit.Async.Deferred();
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.loadPreferences - 1: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(this.user(), 'getUserDetails'));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.loadPreferences - 2: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(this, 'extractHeaderDataFromUserDetails'));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.loadPreferences - 3: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(this, 'extractDataWithKey', 'preferences'));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.loadPreferences - 4: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(this.user().preferences(), 'updateWithData'));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.loadPreferences - 5: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+ deferredResult.callback();
+ } else {
+ deferredResult = MochiKit.Async.succeed(this.user().preferences());
+ }
+
+ return deferredResult;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'loadOneTimePasswords': function() {
+ var deferredResult;
+
+ if (this.shouldLoadSection('oneTimePasswords') == true) {
+ this.setShouldLoadSection('oneTimePasswords', false);
+
+ deferredResult = new MochiKit.Async.Deferred();
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.loadOneTimePasswords - 1: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(this.user(), 'getUserDetails'));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.loadOneTimePasswords - 2: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(this, 'extractHeaderDataFromUserDetails'));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.loadOneTimePasswords - 3: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(this, 'extractDataWithKey', 'oneTimePasswords'));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.loadOneTimePasswords - 4: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(this.user().oneTimePasswordManager(), 'updateWithData'));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.loadOneTimePasswords - 5: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(this.user().connection(), 'message'), 'getOneTimePasswordsDetails', {});
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.loadOneTimePasswords - 6: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(this.user().oneTimePasswordManager(), 'updateWithServerData'));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.loadOneTimePasswords - 7: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+ deferredResult.callback();
+ } else {
+ deferredResult = MochiKit.Async.succeed(this.user().oneTimePasswordManager());
+ }
+
+ return deferredResult;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'loadAllSections': function() {
+ var deferredResult;
+
+ deferredResult = new MochiKit.Async.Deferred();
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.loadAllSections - 1: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(this, 'loadRecords'));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.loadAllSections - 2: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(this, 'loadDirectLogins'));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.loadAllSections - 3: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(this, 'loadPreferences'));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.loadAllSections - 4: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(this, 'loadOneTimePasswords'));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Header.loadAllSections - 5: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+ deferredResult.callback();
+
+ return deferredResult;
+ },
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+
+});
+
diff --git a/frontend/beta/js/Clipperz/PM/DataModel/OneTimePassword.js b/frontend/beta/js/Clipperz/PM/DataModel/OneTimePassword.js
new file mode 100644
index 0000000..dd8d5c9
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/DataModel/OneTimePassword.js
@@ -0,0 +1,333 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. 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 || {};
+
+//console.log("new OneTimePassword", args);
+//MochiKit.Logging.logDebug("---");
+ this._user = args['user'];
+ this._password = args['password'];
+ this._passwordValue = Clipperz.PM.DataModel.OneTimePassword.normalizedOneTimePassword(args['password']);
+ this._reference = args['reference'] || Clipperz.PM.Crypto.randomKey();
+ 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';
+ 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();
+//MochiKit.Logging.logDebug("--- encodedPassphrase.length: " + encodedPassphrase.length);
+ prefixPadding = getRandomBytes(getRandomBytes(1).byteAtIndex(0)).toBase64String();
+//MochiKit.Logging.logDebug("--- prefixPadding.length: " + prefixPadding.length);
+ suffixPadding = getRandomBytes((500 - prefixPadding.length - encodedPassphrase.length) * 6 / 8).toBase64String();
+//MochiKit.Logging.logDebug("--- suffixPadding.length: " + suffixPadding.length);
+//MochiKit.Logging.logDebug("--- total.length: " + (prefixPadding.length + encodedPassphrase.length + suffixPadding.length));
+
+ packedPassphrase = {
+ 'prefix': prefixPadding,
+ 'passphrase': encodedPassphrase,
+ 'suffix': suffixPadding
+ };
+
+// result = Clipperz.Base.serializeJSON(packedPassphrase);
+ result = packedPassphrase;
+//MochiKit.Logging.logDebug("===== OTP packedPassprase: [" + result.length + "]" + result);
+//MochiKit.Logging.logDebug("<<< OneTimePassword.packedPassphrase");
+
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'encryptedPackedPassphrase': function() {
+ return Clipperz.PM.Crypto.deferredEncryptWithCurrentVersion(this.passwordValue(), this.packedPassphrase())
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'encryptedData': function() {
+ var deferredResult;
+ var result;
+
+//MochiKit.Logging.logDebug(">>> OneTimePassword.encryptedData");
+//MochiKit.Logging.logDebug("--- OneTimePassword.encryptedData - id: " + this.reference());
+ result = {
+ 'reference': this.reference(),
+ 'key': this.key(),
+ 'keyChecksum': this.keyChecksum(),
+ 'data': "",
+ 'version': Clipperz.PM.Crypto.encryptingFunctions.currentVersion
+ }
+//MochiKit.Logging.logDebug("--- OneTimePassword.encryptedData - 2: " + Clipperz.Base.serializeJSON(result));
+ deferredResult = new MochiKit.Async.Deferred();
+//MochiKit.Logging.logDebug("--- OneTimePassword.encryptedData - 3");
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("OneTimePassword.encryptedData - 1: " + res); return res;});
+//# deferredResult.addCallback(Clipperz.PM.Crypto.deferredEncryptWithCurrentVersion, this.passwordValue(), this.packedPassphrase());
+ deferredResult.addCallback(MochiKit.Base.method(this, 'encryptedPackedPassphrase'));
+//MochiKit.Logging.logDebug("--- OneTimePassword.encryptedData - 4");
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("OneTimePassword.encryptedData - 2: [" + res.length + "]" + res); return res;});
+ deferredResult.addCallback(function(aResult, res) {
+ aResult['data'] = res;
+ return aResult;
+ }, result);
+//MochiKit.Logging.logDebug("--- OneTimePassword.encryptedData - 5");
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("OneTimePassword.encryptedData - 3: " + Clipperz.Base.serializeJSON(res)); return res;});
+ deferredResult.callback();
+//MochiKit.Logging.logDebug("--- OneTimePassword.encryptedData - 6");
+
+ return deferredResult;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'saveChanges': function() {
+ var deferredResult;
+ var result;
+
+//MochiKit.Logging.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) {MochiKit.Logging.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) {MochiKit.Logging.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) {MochiKit.Logging.logDebug("OneTimePassword.saveChanges - 2: " + res); return res;});
+ deferredResult.callback();
+//MochiKit.Logging.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.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;
+}
+
+//=============================================================================
diff --git a/frontend/beta/js/Clipperz/PM/DataModel/OneTimePasswordManager.js b/frontend/beta/js/Clipperz/PM/DataModel/OneTimePasswordManager.js
new file mode 100644
index 0000000..d90100a
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/DataModel/OneTimePasswordManager.js
@@ -0,0 +1,280 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. 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.OneTimePasswordManager = function(anUser, args) {
+ args = args || {};
+
+ this._user = anUser;
+ this._oneTimePasswords = {};
+
+ this.updateWithData(args);
+
+ Clipperz.NotificationCenter.notify(null, 'oneTimePasswordAdded', null, true);
+
+ return this;
+}
+
+Clipperz.PM.DataModel.OneTimePasswordManager.prototype = MochiKit.Base.update(null, {
+
+ 'toString': function() {
+ return "Clipperz.PM.DataModel.OneTimePasswordManager";
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'updateWithData': function(someValues) {
+ var otpReference;
+
+//console.log("OneTimePasswordManager.updateWithData", someValues);
+//MochiKit.Logging.logDebug("OneTimePasswordManager.updateWithData: " + Clipperz.Base.serializeJSON(someValues));
+ for (otpReference in someValues) {
+ var otp;
+ var otpConfiguration;
+
+ otpConfiguration = someValues[otpReference];
+ otpConfiguration['user'] = this.user();
+ otpConfiguration['reference'] = otpReference;
+ otp = new Clipperz.PM.DataModel.OneTimePassword(otpConfiguration);
+ this._oneTimePasswords[otpReference] = otp;
+ }
+
+ return this;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'updateWithServerData': function(someValues) {
+ var deferredResult;
+ var oneTimePasswordReference;
+ var wereChangesApplied;
+
+//MochiKit.Logging.logDebug(">>> OneTimePasswordManager.updateWithServerData");
+ deferredResult = new MochiKit.Async.Deferred();
+ wereChangesApplied = false;
+
+ for (oneTimePasswordReference in someValues) {
+ var oneTimePassword;
+
+ oneTimePassword = this.oneTimePasswordWithReference(oneTimePasswordReference);
+ if (oneTimePassword != null) {
+ var oneTimePasswordHasBeenUpdated;
+
+ oneTimePasswordHasBeenUpdated = oneTimePassword.updateStatusWithValues(someValues[oneTimePasswordReference]);
+ wereChangesApplied = oneTimePasswordHasBeenUpdated || wereChangesApplied;
+ } else {
+
+ }
+ }
+
+ if (wereChangesApplied == true) {
+ this.user().header().markSectionAsUpdated('oneTimePasswords');
+ }
+
+ for (oneTimePasswordReference in this.oneTimePasswords()) {
+ if (typeof(someValues[oneTimePasswordReference]) == 'undefind') {
+ deferredResult.addCallback(MochiKit.Base.method(this.oneTimePasswordWithReference(oneTimePasswordReference), 'saveChanges'));
+ }
+ }
+
+ deferredResult.addCallback(MochiKit.Async.succeed, this);
+
+ deferredResult.callback();
+//MochiKit.Logging.logDebug("<<< OneTimePasswordManager.updateWithServerData");
+
+ return deferredResult;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'user': function() {
+ return this._user;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'addOneTimePassword': function(aOneTimePassword, isBatchUpdate) {
+ this.oneTimePasswords()[aOneTimePassword.reference()] = aOneTimePassword;
+
+ if (isBatchUpdate != true) {
+ Clipperz.NotificationCenter.notify(aOneTimePassword, 'oneTimePasswordAdded');
+ Clipperz.NotificationCenter.notify(this.user(), 'updatedSection', 'oneTimePasswords', true);
+ }
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'archiveOneTimePassword': function(aOneTimePasswordReference) {
+ var deferredResult;
+
+//MochiKit.Logging.logDebug(">>> OneTimePasswordManager.archiveOneTimePassword");
+//MochiKit.Logging.logDebug("--- OneTimePasswordManager.archiveOneTimePassword - 0 otp.reference: " + aOneTimePasswordReference);
+ deferredResult = new MochiKit.Async.Deferred();
+ deferredResult.addCallback(MochiKit.Base.method(this.user(), 'loadOneTimePasswords'));
+ deferredResult.addCallback(MochiKit.Base.bind(function(aOneTimePasswordReference) {
+ var oneTimePassword;
+
+//MochiKit.Logging.logDebug("--- OneTimePasswordManager.archiveOneTimePassword - 1 serializedData: " + Clipperz.Base.serializeJSON(this.serializedData()));
+ oneTimePassword = this.oneTimePasswords()[aOneTimePasswordReference];
+
+ if (oneTimePassword != null) {
+ oneTimePassword.setUsageDate(new Date());
+
+// while (this.usedOneTimePasswords().length > 10) {
+// var referenceOfOneTimePasswordToRemove;
+//
+// referenceOfOneTimePasswordToRemove = this.usedOneTimePasswords()[0];
+// delete this.oneTimePasswords()[referenceOfOneTimePasswordToRemove];
+// this.usedOneTimePasswords().shift();
+// }
+
+ Clipperz.NotificationCenter.notify(this.user(), 'updatedSection', 'oneTimePasswords', true);
+ } else {
+ MochiKit.Logging.logError("### OneTimePasswordManager.archiveOneTimePassword - the used OneTimePassword has not been found on the index-card. :-(");
+ }
+
+//MochiKit.Logging.logDebug("--- OneTimePasswordManager.archiveOneTimePassword - 2 serializedData: " + Clipperz.Base.serializeJSON(this.serializedData()));
+ }, this), aOneTimePasswordReference);
+ deferredResult.addCallback(MochiKit.Base.method(this, 'saveChanges'));
+ deferredResult.callback();
+//MochiKit.Logging.logDebug("<<< OneTimePasswordManager.archiveOneTimePassword");
+
+ return deferredResult;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'serializedData': function() {
+ var result;
+ var key;
+
+ result = {};
+
+ for (key in this.oneTimePasswords()) {
+ result[key] = this.oneTimePasswords()[key].serializedData();
+ }
+
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'oneTimePasswords': function() {
+ return this._oneTimePasswords;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'oneTimePasswordWithReference': function(aOneTimePasswordReference) {
+ return this.oneTimePasswords()[aOneTimePasswordReference];
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'deleteOneTimePasswordWithReference': function(aOneTimePasswordReference) {
+ delete(this.oneTimePasswords()[aOneTimePasswordReference]);
+ Clipperz.NotificationCenter.notify(this.user(), 'updatedSection', 'oneTimePasswords', true);
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'encryptedData': function() {
+ var deferredResult;
+ var oneTimePasswordReferences;
+ var result;
+ var i, c;
+
+ result = {};
+ deferredResult = new MochiKit.Async.Deferred();
+ deferredResult.addCallback(MochiKit.Async.succeed);
+
+ oneTimePasswordReferences = MochiKit.Base.keys(this.oneTimePasswords());
+ c = oneTimePasswordReferences.length;
+ for (i=0; i<c; i++) {
+ var currentOneTimePassword;
+
+ currentOneTimePassword = this.oneTimePasswords()[oneTimePasswordReferences[i]];
+ deferredResult.addCallback(MochiKit.Base.method(currentOneTimePassword, 'encryptedPackedPassphrase'));
+ deferredResult.addCallback(function(aResult, aOneTimePasswordReference, anEncryptedPackedPassphrase) {
+ aResult[aOneTimePasswordReference] = anEncryptedPackedPassphrase;
+ return aResult;
+ }, result, oneTimePasswordReferences[i]);
+ }
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("OneTimePasswordManager.encryptedData: " + res); return res;});
+
+ deferredResult.callback(result);
+
+ return deferredResult;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'saveChanges': function() {
+ var deferredResult;
+ var result;
+
+//MochiKit.Logging.logDebug(">>> OneTimePasswordManager.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.bind(function(res) {
+ res['oneTimePasswords'] = MochiKit.Base.keys(this.oneTimePasswords());
+ return res;
+ }, this));
+
+ deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', 'saveOTP_sendingData');
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("OneTimePasswordManager.saveChanges - 1: " + Clipperz.Base.serializeJSON(res)); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(this.user().connection(), 'message'), 'updateOneTimePasswords');
+
+ deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', 'saveOTP_updatingInterface');
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("OneTimePasswordManager.saveChanges - 2: " + res); return res;});
+ deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'notify', 'OTPUpdated');
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("OneTimePasswordManager.saveChanges - 3: " + res); return res;});
+ deferredResult.callback();
+//MochiKit.Logging.logDebug("<<< OneTimePasswordManager.saveChanges");
+
+ return deferredResult;
+ },
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+});
+
diff --git a/frontend/beta/js/Clipperz/PM/DataModel/Record.js b/frontend/beta/js/Clipperz/PM/DataModel/Record.js
new file mode 100644
index 0000000..b4b5023
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/DataModel/Record.js
@@ -0,0 +1,759 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. 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) {
+ args = args || {};
+
+ this._user = args['user'] || null;
+ this._reference = args['reference'] || Clipperz.PM.Crypto.randomKey();
+ this._version = args['version'] || Clipperz.PM.Crypto.encryptingFunctions.currentVersion;
+ this._key = args['key'] || Clipperz.PM.Crypto.randomKey();
+
+ this.setLabel(args['label'] || Clipperz.PM.Strings['newRecordTitleLabel']);
+
+ this.setHeaderNotes(args['headerNotes'] || null);
+ this.setNotes(args['notes'] || args['headerNotes'] || "");
+//MochiKit.Logging.logDebug("--- new Record ('" + this._label + "')- _headerNotes: '" + this._headerNotes + "'");
+//MochiKit.Logging.logDebug("--- new Record ('" + this._label + "')- _notes: '" + this._notes + "'");
+// this._notes = args.notes || "";
+
+ this._versions = {};
+ this._directLogins = {};
+ this._removedDirectLogins = [];
+
+ this.setIsBrandNew(args['reference'] == null);
+
+ this.setShouldLoadData(this.isBrandNew() ? false: true);
+ this.setShouldDecryptData(this.isBrandNew() ? false: true);
+ this.setShouldProcessData(this.isBrandNew() ? false: true);
+
+ this.setCurrentVersion(this.isBrandNew() ? new Clipperz.PM.DataModel.RecordVersion(this, null): null);
+ this.setCurrentVersionKey(null);
+
+ this._serverData = null;
+ this._decryptedData = null;
+ this._cachedData = null;
+
+ return this;
+}
+
+Clipperz.PM.DataModel.Record.prototype = MochiKit.Base.update(null, {
+
+ 'toString': function() {
+ return "Record (" + this.label() + ")";
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'isBrandNew': function() {
+ return this._isBrandNew;
+ },
+
+ 'setIsBrandNew': function(aValue) {
+ this._isBrandNew = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+/*
+ 'shouldRunTheRecordCreationWizard': function() {
+ return (this.isBrandNew() && (MochiKit.Base.keys(this.currentVersion().fields()).length == 0));
+ },
+*/
+ //-------------------------------------------------------------------------
+
+ 'user': function() {
+ return this._user;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'reference': function() {
+ return this._reference;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'key': function() {
+ return this._key;
+ },
+
+ 'updateKey': function() {
+ this._key = Clipperz.PM.Crypto.randomKey();
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'label': function() {
+ return this._label;
+ },
+
+ 'setLabel': function(aValue) {
+ this._label = aValue;
+ },
+
+ 'lowerCaseLabel': function() {
+ return this.label().toLowerCase();
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'versions': function() {
+ return this._versions;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'currentVersion': function() {
+ return this._currentVersion;
+ },
+
+ 'setCurrentVersion': function(aValue) {
+ this._currentVersion = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'currentVersionKey': function() {
+ return this._currentVersionKey;
+ },
+
+ 'setCurrentVersionKey': function(aValue) {
+ this._currentVersionKey = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'deferredData': function() {
+ var deferredResult;
+
+//MochiKit.Logging.logDebug(">>> [" + (new Date()).valueOf() + "] Record.deferredData - this: " + this);
+ deferredResult = new MochiKit.Async.Deferred();
+ deferredResult.addCallback(MochiKit.Base.method(this, 'loadData'));
+ deferredResult.addCallback(MochiKit.Base.method(this, 'decryptData'));
+ deferredResult.addCallback(MochiKit.Base.method(this, 'processData'));
+ deferredResult.addCallback(function(aRecord) {
+ return aRecord.currentVersion().deferredData();
+ });
+ deferredResult.addCallback(MochiKit.Base.method(this, 'takeSnapshotOfCurrentData'));
+ deferredResult.addCallback(MochiKit.Async.succeed, this);
+ deferredResult.callback();
+//MochiKit.Logging.logDebug("<<< [" + (new Date()).valueOf() + "] Record.deferredData");
+
+ return deferredResult;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'exportedData': function() {
+ var result;
+
+ result = {};
+ result['label'] = this.label();
+ result['data'] = this.serializedData();
+ result['currentVersion'] = this.currentVersion().serializedData();
+ result['currentVersion']['reference'] = this.currentVersion().reference();
+// result['versions'] = MochiKit.Base.map(MochiKit.Base.methodcaller("serializedData"), MochiKit.Base.values(this.versions()));
+
+ return Clipperz.Base.serializeJSON(result);
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'shouldLoadData': function() {
+ return this._shouldLoadData;
+ },
+
+ 'setShouldLoadData': function(aValue) {
+ this._shouldLoadData = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'shouldDecryptData': function() {
+ return this._shouldDecryptData;
+ },
+
+ 'setShouldDecryptData': function(aValue) {
+ this._shouldDecryptData = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'shouldProcessData': function() {
+ return this._shouldProcessData;
+ },
+
+ 'setShouldProcessData': function(aValue) {
+ this._shouldProcessData = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'loadData': function() {
+ var result;
+
+//MochiKit.Logging.logDebug(">>> [" + (new Date()).valueOf() + "] Record.loadData - this: " + this);
+ if (this.shouldLoadData()) {
+ var deferredResult;
+
+ deferredResult = new MochiKit.Async.Deferred();
+ deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'notify', 'loadingRecordData');
+ deferredResult.addCallback(MochiKit.Base.method(this.user().connection(), 'message'), 'getRecordDetail', {reference: this.reference()});
+ deferredResult.addCallback(MochiKit.Base.method(this,'setServerData'));
+ deferredResult.callback();
+ result = deferredResult;
+ } else {
+ result = MochiKit.Async.succeed(this.serverData());
+ }
+//MochiKit.Logging.logDebug("<<< [" + (new Date()).valueOf() + "] Record.loadData");
+
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'decryptData': function(anEncryptedData) {
+ var result;
+
+//MochiKit.Logging.logDebug(">>> [" + (new Date()).valueOf() + "] Record.decryptData - this: " + this + " (" + anEncryptedData + ")");
+ if (this.shouldDecryptData()) {
+ var deferredResult;
+
+ deferredResult = new MochiKit.Async.Deferred();
+ deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'notify', 'decryptingRecordData');
+ deferredResult.addCallback(Clipperz.PM.Crypto.deferredDecrypt, this.key(), anEncryptedData['data'], anEncryptedData['version']);
+ deferredResult.addCallback(function(anEncryptedData, someDecryptedValues) {
+ var result;
+
+ result = anEncryptedData;
+ result['data'] = someDecryptedValues;
+
+ return result;
+ }, anEncryptedData);
+ deferredResult.addCallback(MochiKit.Base.method(this, 'setDecryptedData'));
+ deferredResult.callback();
+
+ result = deferredResult;
+ } else {
+ result = MochiKit.Async.succeed(this.decryptedData());
+ }
+//MochiKit.Logging.logDebug("<<< [" + (new Date()).valueOf() + "] Record.decryptData");
+
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'processData': function(someValues) {
+//MochiKit.Logging.logDebug(">>> [" + (new Date()).valueOf() + "] Record.processData");
+//MochiKit.Logging.logDebug("--- Record.processData: " + Clipperz.Base.serializeJSON(someValues));
+ if (this.shouldProcessData()) {
+ var currentVersionParameters;
+
+ this.processDataToExtractLegacyValues(someValues['data']);
+
+ if (typeof(someValues['data']['notes']) != 'undefined') {
+ this.setNotes(someValues['data']['notes']);
+ }
+ if (someValues['data']['currentVersionKey'] != null) {
+ this.setCurrentVersionKey(someValues['data']['currentVersionKey']);
+ } else {
+ this.setCurrentVersionKey(this.key());
+ }
+
+ currentVersionParameters = someValues['currentVersion'];
+ currentVersionParameters['key'] = this.currentVersionKey();
+ this.setCurrentVersion(new Clipperz.PM.DataModel.RecordVersion(this, currentVersionParameters));
+
+ if (someValues['data']['directLogins'] != null) {
+ var directLoginReference;
+
+ for (directLoginReference in someValues['data']['directLogins']) {
+ var directLogin;
+ var directLoginParameters;
+
+ directLoginParameters = someValues['data']['directLogins'][directLoginReference];
+ directLoginParameters.record = this;
+ directLoginParameters.reference = directLoginReference;
+
+ directLogin = new Clipperz.PM.DataModel.DirectLogin(directLoginParameters);
+ this.addDirectLogin(directLogin, true);
+ }
+ }
+ this.setShouldProcessData(false);
+ }
+
+ Clipperz.NotificationCenter.notify(this, 'recordDataReady');
+//MochiKit.Logging.logDebug("<<< [" + (new Date()).valueOf() + "] Record.processData");
+//MochiKit.Logging.logDebug("<<< Record.processData");
+
+ return this;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'processDataToExtractLegacyValues': function(someValues) {
+//MochiKit.Logging.logDebug(">>> Record.processDataToExtractLegacyValues");
+ if (someValues['data'] != null) {
+ this.setNotes(someValues['data']);
+ }
+
+ if (
+ (typeof(someValues['loginFormData']) != "undefined")
+ && (typeof(someValues['loginBindings'] != "undefined"))
+ && (someValues['loginFormData'] != "")
+ && (someValues['loginBindings'] != "")
+ ) {
+ var directLogin;
+
+ directLogin = new Clipperz.PM.DataModel.DirectLogin({
+ record:this,
+ label:this.label() + Clipperz.PM.Strings['newDirectLoginLabelSuffix'],
+ reference:Clipperz.Crypto.SHA.sha256(new Clipperz.ByteArray(this.label() +
+ someValues['loginFormData'] +
+ someValues['loginBindings'])).toHexString().substring(2),
+ formData:Clipperz.Base.evalJSON(someValues['loginFormData']),
+ legacyBindingData:Clipperz.Base.evalJSON(someValues['loginBindings']),
+ bookmarkletVersion:'0.1'
+ });
+ this.addDirectLogin(directLogin, true);
+ }
+//MochiKit.Logging.logDebug("<<< Record.processDataToExtractLegacyValues");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'getReadyBeforeUpdatingVersionValues': function() {
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'addNewField': function() {
+ var newField;
+
+//MochiKit.Logging.logDebug(">>> Record.addNewField - " + this);
+ this.getReadyBeforeUpdatingVersionValues();
+ newField = this.currentVersion().addNewField();
+ Clipperz.NotificationCenter.notify(this, 'recordUpdated');
+//MochiKit.Logging.logDebug("<<< Record.addNewField");
+
+ return newField;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'removeField': function(aField) {
+ this.getReadyBeforeUpdatingVersionValues();
+ this.currentVersion().removeField(aField);
+ Clipperz.NotificationCenter.notify(this, 'recordUpdated');
+ },
+
+ 'removeEmptyFields': function() {
+ MochiKit.Iter.forEach(MochiKit.Base.values(this.currentVersion().fields()), MochiKit.Base.bind(function(aField) {
+ if (aField.isEmpty()) {
+ this.removeField(aField);
+// this.currentVersion().removeField(aField);
+ }
+ }, this));
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'notes': function() {
+ return this._notes;
+ },
+
+ 'setNotes': function(aValue) {
+ this._notes = aValue;
+ this.setHeaderNotes(null);
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'headerNotes': function() {
+ return this._headerNotes;
+ },
+
+ 'setHeaderNotes': function(aValue) {
+ this._headerNotes = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'remove': function() {
+//MochiKit.Logging.logDebug(">>> Record.remove - " + this);
+ MochiKit.Iter.forEach(MochiKit.Base.values(this.directLogins()), MochiKit.Base.method(this, 'removeDirectLogin'));
+
+ this.syncDirectLoginReferenceValues();
+ this.user().removeRecord(this);
+//MochiKit.Logging.logDebug("<<< Record.remove");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'directLogins': function() {
+ return this._directLogins;
+ },
+
+ 'addDirectLogin': function(aDirectLogin, shouldUpdateUser) {
+ this.directLogins()[aDirectLogin.reference()] = aDirectLogin;
+ if (shouldUpdateUser == true) {
+ this.user().addDirectLogin(aDirectLogin);
+ }
+ },
+
+ 'removeDirectLogin': function(aDirectLogin) {
+ this.removedDirectLogins().push(aDirectLogin);
+ delete this.directLogins()[aDirectLogin.reference()];
+// this.user().removeDirectLogin(aDirectLogin);
+ },
+
+ 'resetDirectLogins': function() {
+ this._directLogins = {};
+ },
+
+ 'removedDirectLogins': function() {
+ return this._removedDirectLogins;
+ },
+
+ 'resetRemovedDirectLogins': function() {
+ this._removedDirectLogins = [];
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'serverData': function() {
+ return this._serverData;
+ },
+
+ 'setServerData': function(aValue) {
+ this._serverData = aValue;
+ this.setShouldLoadData(false);
+ return aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'decryptedData': function() {
+ return this._decryptedData;
+ },
+
+ 'setDecryptedData': function(aValue) {
+ this._decryptedData = aValue;
+ this.setShouldDecryptData(false);
+ return aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'cachedData': function() {
+ return this._cachedData;
+ },
+
+ 'setCachedData': function(aValue) {
+//MochiKit.Logging.logDebug(">>> Record.setCachedData");
+//MochiKit.Logging.logDebug("--- Record.setCachedData - aValue: " + Clipperz.Base.serializeJSON(aValue));
+ this._cachedData = aValue;
+ this.setShouldProcessData(false);
+//MochiKit.Logging.logDebug("<<< Record.setCachedData");
+
+ return aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'hasPendingChanges': function() {
+ var result;
+
+//MochiKit.Logging.logDebug(">>> [" + (new Date()).valueOf() + "] Record.hasPendingChanges");
+//MochiKit.Logging.logDebug(">>> Record.hasPendingChanges - cachedData: " + this.cachedData());
+//MochiKit.Logging.logDebug(">>> Record.hasPendingChanges - cachedData: " + Clipperz.Base.serializeJSON(this.cachedData()));
+//MochiKit.Logging.logDebug(">>> Record.hasPendingChanges - currentSnapshot: " + this.currentDataSnapshot());
+//MochiKit.Logging.logDebug(">>> Record.hasPendingChanges - currentSnapshot: " + Clipperz.Base.serializeJSON(this.currentDataSnapshot()));
+//console.log(">>> Record.hasPendingChanges - cachedData: %o", this.cachedData());
+//console.log(">>> Record.hasPendingChanges - currentSnapshot: %o", this.currentDataSnapshot());
+ result = (MochiKit.Base.compare(this.cachedData(), this.currentDataSnapshot()) != 0);
+//MochiKit.Logging.logDebug("<<< Record.hasPendingChanges - " + result);
+
+ if ((result == false) && this.isBrandNew() && (this.label() != Clipperz.PM.Strings['newRecordTitleLabel'])) {
+ result = true;
+ }
+//MochiKit.Logging.logDebug("<<< [" + (new Date()).valueOf() + "] Record.hasPendingChanges");
+
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'currentDataSnapshot': function() {
+ var result;
+
+//MochiKit.Logging.logDebug(">>> [" + (new Date()).valueOf() + "] Record.currentDataSnapshot");
+ result = {
+ 'label': this.label(),
+ 'data': this.serializedData(),
+ 'currentVersion': this.currentVersion().currentDataSnapshot()
+ };
+
+// result['data']['data'] = this.notes();
+ result = Clipperz.Base.serializeJSON(result);
+
+//MochiKit.Logging.logDebug("<<< [" + (new Date()).valueOf() + "] Record.currentDataSnapshot");
+//MochiKit.Logging.logDebug("<<< Record.currentDataSnapshot");
+
+ return result;
+ },
+
+ //.........................................................................
+
+ 'takeSnapshotOfCurrentData': function() {
+ this.setCachedData(this.currentDataSnapshot());
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'headerData': function() {
+ var result;
+
+ result = {
+ 'label': this.label(),
+ 'key': this.key()
+ };
+
+ if (this.headerNotes() != null) {
+ result['headerNotes'] = this.headerNotes();
+ }
+
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'serializedData': function() {
+ var result;
+ var directLoginReference;
+
+ result = {};
+ result['currentVersionKey'] = this.currentVersion().key();
+
+ result['directLogins'] = {};
+ for (directLoginReference in this.directLogins()) {
+ result['directLogins'][directLoginReference] = this.directLogins()[directLoginReference].serializedData();
+ }
+ result['notes'] = this.notes();
+
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'encryptedData': function() {
+ var deferredResult;
+ var result;
+
+//MochiKit.Logging.logDebug(">>> [" + (new Date()).valueOf() + "] Record.encryptedData");
+ result = {}
+//MochiKit.Logging.logDebug("--- Record.encryptedData - 1");
+ deferredResult = new MochiKit.Async.Deferred();
+//MochiKit.Logging.logDebug("--- Record.encryptedData - 2");
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Record.encryptedData - 1: " + res); return res;});
+ deferredResult.addCallback(function(aResult, aRecord) {
+ aResult['reference'] = aRecord.reference();
+ return aResult;
+ }, result, this);
+//MochiKit.Logging.logDebug("--- Record.encryptedData - 3");
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Record.encryptedData - 2: " + res); return res;});
+ deferredResult.addCallback(Clipperz.PM.Crypto.deferredEncryptWithCurrentVersion, this.key(), this.serializedData());
+//MochiKit.Logging.logDebug("--- Record.encryptedData - 4");
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Record.encryptedData - 3: " + res); return res;});
+ deferredResult.addCallback(function(aResult, res) {
+ aResult['data'] = res;
+ return aResult;
+ }, result);
+//MochiKit.Logging.logDebug("--- Record.encryptedData - 5");
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Record.encryptedData - 4: " + res); return res;});
+ deferredResult.addCallback(function(aResult) {
+ aResult['version'] = Clipperz.PM.Crypto.encryptingFunctions.currentVersion;
+ return aResult;
+ }, result);
+//MochiKit.Logging.logDebug("--- Record.encryptedData - 6");
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Record.encryptedData - 5: " + res); return res;});
+ deferredResult.callback();
+//MochiKit.Logging.logDebug("<<< [" + (new Date()).valueOf() + "] Record.encryptedData");
+
+ return deferredResult;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'syncDirectLoginReferenceValues': function() {
+//MochiKit.Logging.logDebug(">>> Record.syncDirectLoginReferenceValues");
+ MochiKit.Iter.forEach(MochiKit.Base.values(this.directLogins()), function(aDirectLogin) {
+ aDirectLogin.record().user().synchronizeDirectLogin(aDirectLogin);
+ });
+
+ MochiKit.Iter.forEach(this.removedDirectLogins(), function(aDirectLogin) {
+ aDirectLogin.record().user().removeDirectLogin(aDirectLogin);
+ });
+
+ this.resetRemovedDirectLogins();
+//MochiKit.Logging.logDebug("<<< Record.syncDirectLoginReferenceValues");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'saveChanges': function() {
+ var result;
+
+ if (this.isBrandNew() == false) {
+ result = this.user().saveRecords([this], 'updateData');
+ } else {
+ result = this.user().saveRecords([this], 'addNewRecords');
+ }
+
+ return result;
+ },
+
+/*
+ 'saveChanges': function() {
+ var deferredResult;
+ var result;
+
+ Clipperz.NotificationCenter.notify(this.user(), 'updatedSection', 'records', true);
+//MochiKit.Logging.logDebug(">>> Record.saveChanges");
+//MochiKit.Logging.logDebug(">>> [" + (new Date()).valueOf() + "] Record.saveChanges");
+ if (this.headerNotes() != null) {
+ this.setNotes(this.headerNotes());
+ }
+ this.syncDirectLoginReferenceValues();
+ this.currentVersion().createNewVersion();
+
+ result = {'records': [{}]};
+
+ deferredResult = new MochiKit.Async.Deferred();
+ deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', 'saveCard_collectRecordInfo');
+ deferredResult.addCallback(MochiKit.Base.method(this, 'updateKey'));
+
+ deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', 'saveCard_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', 'saveCard_encryptRecordData');
+ deferredResult.addCallback(MochiKit.Base.method(this, 'encryptedData'));
+ deferredResult.addCallback(function(aResult, res) {
+//# aResult['record'] = res;
+ aResult['records'][0]['record'] = res;
+ return aResult;
+ }, result);
+
+ deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', 'saveCard_encryptRecordVersions');
+ deferredResult.addCallback(MochiKit.Base.method(this.currentVersion(), 'encryptedData'));
+ deferredResult.addCallback(function(aResult, res) {
+// aResult['currentRecordVersion'] = res;
+ aResult['records'][0]['currentRecordVersion'] = res;
+ return aResult;
+ }, result);
+
+ deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', 'saveCard_sendingData');
+ if (this.isBrandNew() == false) {
+ deferredResult.addCallback(MochiKit.Base.method(this.user().connection(), 'message'), 'updateData');
+ } else {
+//# deferredResult.addCallback(MochiKit.Base.method(this.user().connection(), 'message'), 'addNewRecord');
+ deferredResult.addCallback(MochiKit.Base.method(this.user().connection(), 'message'), 'addNewRecords');
+ }
+
+ deferredResult.addCallback(MochiKit.Base.method(this, 'takeSnapshotOfCurrentData'));
+ deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', 'saveCard_updatingInterface');
+ deferredResult.addCallback(MochiKit.Base.method(this, 'setIsBrandNew'), false);
+ deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'notify', 'recordUpdated');
+ deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'notify', 'directLoginUpdated');
+ deferredResult.callback();
+
+ return deferredResult;
+ },
+*/
+ //-------------------------------------------------------------------------
+
+ 'cancelChanges': function() {
+//MochiKit.Logging.logDebug(">>> Record.cancelChanges");
+//MochiKit.Logging.logDebug("--- Record.cancelChanges - cachedData: " + Clipperz.Base.serializeJSON(this.cachedData()));
+ if (this.isBrandNew()) {
+ this.user().removeRecord(this);
+ } else {
+ this.restoreValuesFromSnapshot(this.cachedData());
+ }
+//MochiKit.Logging.logDebug("<<< Record.cancelChanges");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'restoreValuesFromSnapshot': function(someSnapshotData) {
+ var snapshotData;
+
+//MochiKit.Logging.logDebug(">>> [" + (new Date()).valueOf() + "] Record.restoreValuesFromSnapshot");
+ snapshotData = Clipperz.Base.evalJSON(someSnapshotData);
+//MochiKit.Logging.logDebug("--- Record.restoreValuesFromSnapshot - someSnapshotData (1): " + Clipperz.Base.serializeJSON(someSnapshotData));
+ this.setLabel(snapshotData['label']);
+ this.resetDirectLogins();
+ this.setShouldProcessData(true);
+ this.processData(snapshotData);
+//MochiKit.Logging.logDebug("--- Record.restoreValuesFromSnapshot - snapshotData: (2)" + Clipperz.Base.serializeJSON(snapshotData));
+
+ this.resetRemovedDirectLogins();
+
+ {
+ var currentSnapshot;
+ var comparisonResult;
+
+ currentSnapshot = this.currentDataSnapshot();
+//MochiKit.Logging.logDebug("--- Record.restoreValuesFromSnapshot - 1");
+//console.log("snapshot data: %o", someSnapshotData.currentVersion);
+//console.log("current data: %o", currentSnapshot.currentVersion);
+//MochiKit.Logging.logDebug("--- Record.restoreValuesFromSnapshot - someSnapshotData: " + Clipperz.Base.serializeJSON(someSnapshotData.currentVersion));
+//MochiKit.Logging.logDebug("--- Record.restoreValuesFromSnapshot - currentSnapshot: " + Clipperz.Base.serializeJSON(currentSnapshot.currentVersion));
+ comparisonResult = MochiKit.Base.compare(someSnapshotData.currentVersion, currentSnapshot.currentVersion);
+//MochiKit.Logging.logDebug("--- Record.restoreValuesFromSnapshot - " + comparisonResult);
+ }
+//MochiKit.Logging.logDebug("<<< [" + (new Date()).valueOf() + "] Record.restoreValuesFromSnapshot");
+ },
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+});
+
+
diff --git a/frontend/beta/js/Clipperz/PM/DataModel/RecordField.js b/frontend/beta/js/Clipperz/PM/DataModel/RecordField.js
new file mode 100644
index 0000000..2063825
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/DataModel/RecordField.js
@@ -0,0 +1,220 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. 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.RecordField = function(args) {
+ args = args || {};
+
+ this._recordVersion = args.recordVersion || null;
+ this._key = args.key || Clipperz.PM.Crypto.randomKey();
+ this.setLabel(args.label || '');
+ this.setValue(args.value || '');
+ this.setType(args.type || 'TXT'); // valid types: 'TXT', 'PWD', 'URL', 'DATE', 'ADDR', 'CHECK', 'RADIO', ('NOTE' probably not), ...
+ this._hidden = args.hidden || (args.type == 'PWD') || false;
+
+ return this;
+}
+
+Clipperz.PM.DataModel.RecordField.prototype = MochiKit.Base.update(null, {
+
+ 'toString': function() {
+ return "Clipperz.PM.DataModel.RecordField - " + this.label() + " (" + this.key() + ")";
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'recordVersion': function() {
+ return this._recordVersion;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'key': function() {
+ return this._key;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'label': function() {
+ return this._label;
+ },
+
+ 'setLabel': function(aValue) {
+ this._label = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'value': function() {
+ return this._value;
+ },
+
+ 'setValue': function(aValue) {
+ this._value = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'type': function() {
+ return this._type;
+ },
+
+ 'setType': function(aValue) {
+ this._type = aValue;
+
+ if (aValue == 'PWD') {
+ this.setHidden(true);
+ } else {
+ this.setHidden(false);
+ }
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'serializeData': function() {
+ var result;
+
+//MochiKit.Logging.logDebug(">>> RecordField.serializeData - " + this);
+ result = {
+ label: this.label(),
+ value: this.value(),
+ type: this.type(),
+ hidden: this.hidden()
+ };
+//MochiKit.Logging.logDebug("<<< RecordField.serializeData");
+
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'typeShortDescription': function() {
+// return Clipperz.PM.DataModel.RecordField.TypeDescriptions[this.type()]['shortDescription'];
+ return Clipperz.PM.Strings['recordFieldTypologies'][this.type()]['shortDescription'];
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'hidden': function() {
+ return this._hidden;
+ },
+
+ 'setHidden': function(aValue) {
+ this._hidden = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'clone': function(aRecordVersion) {
+ var result;
+
+ result = new Clipperz.PM.DataModel.RecordField({
+ recordVersion:aRecordVersion,
+ label:this.label(),
+ value:this.value(),
+ type:this.type(),
+ hidden:this.hidden()
+ });
+
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'isEmpty': function() {
+ var result;
+
+ if ((this.label() == "") && (this.value() == "") && (this.type() == 'TXT')) {
+ result = true;
+ } else {
+ result = false;
+ }
+
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+
+});
+
+//#############################################################################
+/*
+Clipperz.PM.DataModel.RecordField.TypeDescriptions = {
+ 'TXT': {
+ description: 'simple text field',
+ shortDescription: 'txt'
+ },
+ 'PWD': {
+ description: 'simple text field, with default status set to hidden',
+ shortDescription: 'pwd'
+ },
+ 'URL': {
+ description: 'simple text field in edit mode, that became an active url in view mode',
+ shortDescription: 'url'
+ },
+ 'DATE': {
+ description: 'a value set with a calendar helper',
+ shortDescription: 'date'
+ },
+ 'ADDR': {
+ description: 'just like the URL, but the active link points to Google Maps (or similar service) passing the address value as argument',
+ shortDescription: 'addr'
+ },
+ 'CHECK': {
+ description: 'check description',
+ shortDescription: 'check'
+ },
+ 'RADIO': {
+ description: 'radio description',
+ shortDescription: 'radio'
+ },
+ 'SELECT': {
+ description: 'select description',
+ shortDescription: 'select'
+ }
+
+// 'NOTE': {
+// description: 'a simple text field, but with a bigger component dimension; possibly with "smart edit components"',
+// shortDescription: 'note'
+// }
+};
+
+Clipperz.PM.DataModel.RecordField.InputTypeToRecordFieldType = {
+ 'text': 'TXT',
+ 'password': 'PWD',
+ 'checkbox': 'CHECK',
+ 'radio': 'RADIO',
+ 'select': 'SELECT'
+};
+*/
diff --git a/frontend/beta/js/Clipperz/PM/DataModel/RecordVersion.js b/frontend/beta/js/Clipperz/PM/DataModel/RecordVersion.js
new file mode 100644
index 0000000..d2b3e12
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/DataModel/RecordVersion.js
@@ -0,0 +1,535 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. 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.RecordVersion = function(aRecord, args) {
+ args = args || {};
+
+ this._record = aRecord;
+
+ this._reference = args.reference || Clipperz.PM.Crypto.randomKey();
+ this._version = args.version || Clipperz.PM.Crypto.encryptingFunctions.currentVersion;
+ this._key = args.key || Clipperz.PM.Crypto.randomKey();;
+
+ this._previousVersion = args.previousVersion || null;
+ this._previousVersionKey = args.previousVersionKey || null;
+
+ this.setIsBrandNew(args.reference == null);
+
+ if (this.isBrandNew()) {
+ this._fields = {};
+
+ this.setShouldLoadData(false);
+ this.setShouldDecryptData(false);
+ this.setShouldProcessData(false);
+ } else {
+ if (typeof(args.fields) != 'undefined') {
+ this.processFieldData(args.fields);
+
+ this.setShouldLoadData(false);
+ this.setShouldDecryptData(false);
+ this.setShouldProcessData(false);
+ } else {
+ if (typeof(args.data) != 'undefined') {
+ this.setShouldLoadData(false);
+ } else {
+ this.setShouldLoadData(true);
+ }
+ this.setShouldDecryptData(true);
+ this.setShouldProcessData(true);
+ }
+ }
+
+ this._serverData = args.data;
+ this._decryptedData = null;
+
+ return this;
+}
+
+Clipperz.PM.DataModel.RecordVersion.prototype = MochiKit.Base.update(null, {
+
+ 'toString': function() {
+ return "RecordVersion";
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'record': function() {
+ return this._record;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'reference': function() {
+ return this._reference;
+ },
+
+ 'setReference': function(aValue) {
+ this._reference = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'key': function() {
+//MochiKit.Logging.logDebug(">>> RecordVersion.key");
+//MochiKit.Logging.logDebug("--- RecordVersion.key - " + this._key);
+ return this._key;
+ },
+
+ 'setKey': function(aValue) {
+ this._key = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'serverData': function() {
+ return this._serverData;
+ },
+
+ 'setServerData': function(aValue) {
+ this._serverData = aValue;
+ this.setShouldLoadData(false);
+ return aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'decryptedData': function() {
+//MochiKit.Logging.logDebug(">>> RecordVersion.decryptedData: " + (this._decryptedData ? Clipperz.Base.serializeJSON(aValue) : "null"));
+ return this._decryptedData;
+ },
+
+ 'setDecryptedData': function(aValue) {
+//MochiKit.Logging.logDebug(">>> RecordVersion.setDecryptedData: " + Clipperz.Base.serializeJSON(aValue));
+ this._decryptedData = aValue;
+ this.setShouldDecryptData(false);
+ return aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'version': function() {
+ return this._version;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'isBrandNew': function() {
+ return this._isBrandNew;
+ },
+
+ 'setIsBrandNew': function(aValue) {
+ this._isBrandNew = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'fields': function() {
+ return this._fields;
+ },
+
+ 'addField': function(aField) {
+ this.fields()[aField.key()] = aField;
+ },
+
+ 'addNewField': function() {
+ var newRecordField;
+
+ newRecordField = new Clipperz.PM.DataModel.RecordField({recordVersion:this});
+ this.addField(newRecordField);
+
+ return newRecordField;
+ },
+
+ 'fieldWithName': function(aValue) {
+ var result;
+ var fieldValues;
+ var i,c;
+
+ result = null;
+ fieldValues = MochiKit.Base.values(this.fields());
+ c = fieldValues.length;
+ for (i=0; (i<c) && (result == null); i++) {
+ var currentField;
+
+ currentField = fieldValues[i];
+ if (currentField.label() == aValue) {
+ result = currentField;
+ }
+ }
+
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'shouldLoadData': function() {
+ return this._shouldLoadData;
+ },
+
+ 'setShouldLoadData': function(aValue) {
+ this._shouldLoadData = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'shouldDecryptData': function() {
+ return this._shouldDecryptData;
+ },
+
+ 'setShouldDecryptData': function(aValue) {
+ this._shouldDecryptData = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'shouldProcessData': function() {
+ return this._shouldProcessData;
+ },
+
+ 'setShouldProcessData': function(aValue) {
+ this._shouldProcessData = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'deferredData': function() {
+ var deferredResult;
+
+//MochiKit.Logging.logDebug(">>> RecordVersion.deferredData - this: " + this);
+ deferredResult = new MochiKit.Async.Deferred();
+ deferredResult.addCallback(MochiKit.Base.method(this, 'loadData'));
+ deferredResult.addCallback(MochiKit.Base.method(this, 'decryptData'));
+ deferredResult.addCallback(MochiKit.Base.method(this, 'processData'));
+ deferredResult.callback();
+//MochiKit.Logging.logDebug("<<< RecordVersion.deferredData");
+
+ return deferredResult;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'loadData': function() {
+ var result;
+
+//MochiKit.Logging.logDebug(">>> RecordVersion.loadData - this: " + this);
+ if (this.shouldLoadData()) {
+ var deferredResult;
+
+ alert("ERROR: this should have not happened yet!");
+//MochiKit.Logging.logDebug("--- RecordVersion.loadData - 1");
+ deferredResult = new MochiKit.Async.Deferred();
+//MochiKit.Logging.logDebug("--- RecordVersion.loadData - 2");
+ deferredResult.addCallback(MochiKit.Base.method(this, 'notify'), 'loadingRecordVersionData');
+//MochiKit.Logging.logDebug("--- RecordVersion.loadData - 3");
+ deferredResult.addCallback(MochiKit.Base.method(this.user().connection(), 'message'), 'getRecordVersionDetail', {reference: this.reference()});
+//MochiKit.Logging.logDebug("--- RecordVersion.loadData - 4");
+ deferredResult.addCallback(MochiKit.Base.method(this, 'setServerData'));
+//MochiKit.Logging.logDebug("--- RecordVersion.loadData - 5");
+ deferredResult.callback();
+//MochiKit.Logging.logDebug("--- RecordVersion.loadData - 6");
+ result = deferredResult;
+//MochiKit.Logging.logDebug("--- RecordVersion.loadData - 7");
+ } else {
+//MochiKit.Logging.logDebug("--- RecordVersion.loadData - 8");
+ result = MochiKit.Async.succeed(this.serverData());
+//MochiKit.Logging.logDebug("--- RecordVersion.loadData - 9");
+ }
+//MochiKit.Logging.logDebug("<<< RecordVersion.loadData");
+
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'decryptData': function(anEncryptedData) {
+ var result;
+
+//MochiKit.Logging.logDebug(">>> RecordVersion.decryptData - this: " + this + " (" + anEncryptedData + ")");
+ if (this.shouldDecryptData()) {
+ var deferredResult;
+
+//MochiKit.Logging.logDebug("--- RecordVersion.decryptData - 1");
+ deferredResult = new MochiKit.Async.Deferred();
+//MochiKit.Logging.logDebug("--- RecordVersion.decryptData - 2");
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("RecordVersion.decryptData 1: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(this, 'notify'), 'decryptingRecordVersionData');
+//MochiKit.Logging.logDebug("--- RecordVersion.decryptData - 3");
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("RecordVersion.decryptData 2: " + res); return res;});
+ deferredResult.addCallback(Clipperz.PM.Crypto.deferredDecrypt, this.key(), anEncryptedData, this.version());
+//MochiKit.Logging.logDebug("--- RecordVersion.decryptData - 4");
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("RecordVersion.decryptData 3: " + res); return res;});
+//MochiKit.Logging.logDebug("--- RecordVersion.decryptData - 5");
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("RecordVersion.decryptData 4: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(this, 'setDecryptedData'));
+//MochiKit.Logging.logDebug("--- RecordVersion.decryptData - 6");
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("RecordVersion.decryptData 5: " + res); return res;});
+ deferredResult.callback();
+//MochiKit.Logging.logDebug("--- RecordVersion.decryptData - 7");
+ result = deferredResult;
+//MochiKit.Logging.logDebug("--- RecordVersion.decryptData - 8");
+ } else {
+//MochiKit.Logging.logDebug("--- RecordVersion.decryptData - 9");
+ result = MochiKit.Async.succeed(this.decryptedData());
+//MochiKit.Logging.logDebug("--- RecordVersion.decryptData - 10");
+ }
+//MochiKit.Logging.logDebug("<<< RecordVersion.decryptData");
+
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'processFieldData': function(someValues) {
+ var fieldValues;
+
+ this._fields = {};
+
+ if (typeof(someValues) == 'undefined') {
+ fieldValues = {};
+ } else {
+ fieldValues = someValues;
+ }
+
+ if (fieldValues.constructor == Array) {
+ var i, c;
+ c = fieldValues.length;
+ for (i=0; i<c; i++) {
+ var newRecordField;
+ var currentFieldValues;
+
+ currentFieldValues = fieldValues[i];
+ currentFieldValues['recordVersion'] = this;
+ newRecordField = new Clipperz.PM.DataModel.RecordField(currentFieldValues);
+ this._fields[newRecordField.key()] = newRecordField;
+ }
+
+ } else {
+ var fieldKey;
+
+ for (fieldKey in fieldValues) {
+ var newRecordField;
+ var currentFieldValues;
+
+ currentFieldValues = fieldValues[fieldKey];
+ currentFieldValues['key'] = fieldKey;
+ currentFieldValues['recordVersion'] = this;
+ newRecordField = new Clipperz.PM.DataModel.RecordField(currentFieldValues);
+ this._fields[fieldKey] = newRecordField;
+ }
+ }
+
+ },
+
+ 'processData': function(someValues) {
+ if (this.shouldProcessData()) {
+ this.processFieldData(someValues.fields);
+ this.setShouldProcessData(false);
+ }
+
+ this.notify('recordVersionDataReady');
+
+ return this;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'notify': function(aValue) {
+ Clipperz.NotificationCenter.notify(this, aValue);
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'removeField': function(aField) {
+ delete this.fields()[aField.key()];
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'previousVersion': function() {
+ return this._previousVersion;
+ },
+
+ 'setPreviousVersion': function(aValue) {
+ this._previousVersion = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'previousVersionKey': function() {
+ return this._previousVersionKey;
+ },
+
+ 'setPreviousVersionKey': function(aValue) {
+ this._previousVersionKey = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'serializedData': function() {
+ var result;
+ var fieldKey;
+
+//MochiKit.Logging.logDebug(">>> RecordVersion.serializedData");
+ result = {
+ fields: {}
+ };
+//MochiKit.Logging.logDebug("--- RecordVersion.serializedData - 1");
+
+ for (fieldKey in this.fields()) {
+//MochiKit.Logging.logDebug("--- RecordVersion.serializedData - 2");
+ result.fields[fieldKey] = this.fields()[fieldKey].serializeData();
+//MochiKit.Logging.logDebug("--- RecordVersion.serializedData - 3");
+ }
+//MochiKit.Logging.logDebug("--- RecordVersion.serializedData - 4");
+//MochiKit.Logging.logDebug("<<< RecordVersion.serializedData: " + Clipperz.Base.serializeJSON(result));
+
+ return result;
+ },
+
+ 'currentDataSnapshot': function() {
+ var result;
+
+ result = this.serializedData();
+ result['version'] = this.version();
+ result['reference'] = this.reference();
+ result['previousVersionKey'] = this.previousVersionKey();
+
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'encryptedData': function() {
+ var deferredResult;
+ var result;
+
+//MochiKit.Logging.logDebug(">>> RecordVersion.encryptedData - " + this);
+ result = {};
+ deferredResult = new MochiKit.Async.Deferred();
+//MochiKit.Logging.logDebug("--- RecordVersion.encryptedData - 1");
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("RecordVersion.encryptedData - 1: " + res); return res;});
+ deferredResult.addCallback(function(aResult, aRecordVersion) {
+ aResult['reference'] = aRecordVersion.reference();
+ aResult['recordReference'] = aRecordVersion.record().reference(); // TODO - this seems to be completely useless
+ return aResult;
+ }, result, this);
+//MochiKit.Logging.logDebug("--- RecordVersion.encryptedData - 2");
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("RecordVersion.encryptedData - 2: " + res); return res;});
+ deferredResult.addCallback(Clipperz.PM.Crypto.deferredEncryptWithCurrentVersion, this.key(), this.serializedData());
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("RecordVersion.encryptedData - 3: " + res); return res;});
+ deferredResult.addCallback(function(aResult, res) {
+ aResult['data'] = res;
+ return aResult;
+ }, result);
+//MochiKit.Logging.logDebug("--- RecordVersion.encryptedData - 3");
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("RecordVersion.encryptedData - 4: " + res); return res;});
+ deferredResult.addCallback(function(aResult) {
+ aResult['version'] = Clipperz.PM.Crypto.encryptingFunctions.currentVersion;
+ return aResult;
+ }, result);
+//MochiKit.Logging.logDebug("--- RecordVersion.encryptedData - 4");
+ if (this.previousVersion() != null) {
+//MochiKit.Logging.logDebug("--- RecordVersion.encryptedData - 5");
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("RecordVersion.encryptedData - 5: " + res); return res;});
+ deferredResult.addCallback(function(aResult, aRecordVersion) {
+ aResult['previousVersion'] = aRecordVersion.previousVersion();
+ return aResult;
+ }, result, this);
+//MochiKit.Logging.logDebug("--- RecordVersion.encryptedData - 6");
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("RecordVersion.encryptedData - 6: " + res); return res;});
+ deferredResult.addCallback(Clipperz.PM.Crypto.deferredEncryptWithCurrentVersion, this.key(), this.previousVersionKey());
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("RecordVersion.encryptedData - 7: " + res); return res;});
+ deferredResult.addCallback(function(aResult, res) {
+ aResult['previousVersionKey'] = res;
+ return aResult;
+ }, result);
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("RecordVersion.encryptedData - 8: " + res); return res;});
+//MochiKit.Logging.logDebug("--- RecordVersion.encryptedData - 7");
+ } else {
+//MochiKit.Logging.logDebug("--- RecordVersion.encryptedData - 8");
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("RecordVersion.encryptedData - 9: " + res); return res;});
+ deferredResult.addCallback(function(aResult) {
+ aResult['previousVersionKey'] = Clipperz.PM.Crypto.nullValue;
+ return aResult;
+ }, result);
+//MochiKit.Logging.logDebug("--- RecordVersion.encryptedData - 9");
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("RecordVersion.encryptedData - 10: " + res); return res;});
+ };
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("RecordVersion.encryptedData - 11: " + res); return res;});
+ deferredResult.callback();
+//MochiKit.Logging.logDebug("<<< RecordVersion.encryptedData");
+
+ return deferredResult;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'createNewVersion': function() {
+ if (this.record().isBrandNew() == false) {
+ this.setPreviousVersion(this.reference());
+ this.setPreviousVersionKey(this.key());
+
+ this.setReference(Clipperz.PM.Crypto.randomKey());
+ this.setKey(Clipperz.PM.Crypto.randomKey());
+ }
+ },
+
+ //-------------------------------------------------------------------------
+/*
+ 'shouldLoadData': function() {
+ return ((this.data() == null) && (this.isBrandNew() === false));
+ },
+
+ 'loadData': function() {
+//MochiKit.Logging.logDebug(">>> Record.loadData (" + this.label() + ")");
+// if (this.shouldLoadData()) {
+// this.user().connection().message( 'getRecordDetail',
+// {recordReference: this.reference()},
+// { callback:MochiKit.Base.bind(this.loadDataCallback, this),
+// errorHandler:Clipperz.PM.defaultErrorHandler });
+// } else {
+// this.notify('loadDataDone');
+// }
+ },
+
+ 'loadDataCallback': function() {
+MochiKit.Logging.logDebug("RecordVersion.loadDataCallback: " + Clipperz.Base.serializeJSON(arguments));
+ },
+*/
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+
+});
+
diff --git a/frontend/beta/js/Clipperz/PM/DataModel/Statistics.js b/frontend/beta/js/Clipperz/PM/DataModel/Statistics.js
new file mode 100644
index 0000000..fb5eb01
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/DataModel/Statistics.js
@@ -0,0 +1,133 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. 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.Statistics = function(args) {
+ args = args || {};
+
+ this._user = args.user;
+ this._data = args.data || null;
+
+ return this;
+}
+
+Clipperz.PM.DataModel.Statistics.prototype = MochiKit.Base.update(null, {
+
+ //-------------------------------------------------------------------------
+
+ 'decrypt': function(aVersion, someEncryptedData) {
+ var deferredResult;
+
+//MochiKit.Logging.logDebug(">>> Statistics.decrypt");
+ if (someEncryptedData == Clipperz.PM.Crypto.nullValue) {
+ this.setData({});
+ deferredResult = MochiKit.Async.succeed(this.data());
+ } else {
+ var statistic;
+ var user;
+
+ statistic = this;
+ user = this.user();
+ deferredResult = new MochiKit.Async.Deferred();
+//deferredResult.addCallback(function() { console.time("Statistics.decrypt.deferredDecrypt")});
+ deferredResult.addCallback(Clipperz.PM.Crypto.deferredDecrypt, user.passphrase(), someEncryptedData, aVersion);
+//deferredResult.addCallback(function() { console.timeEnd("Statistics.decrypt.deferredDecrypt")});
+//deferredResult.addCallback(function() { console.time("Statistics.decrypt.setup")});
+ deferredResult.addCallbacks(
+ MochiKit.Base.partial(function (aStatistic, someData) {
+ aStatistic.setData(someData);
+ return aStatistic.data();
+ }, statistic),
+ MochiKit.Base.partial(function (aStatistic) {
+ MochiKit.Logging.logWarning("resetting user statistics due to an error while decrypting stored data");
+ aStatistic.setData({});
+ return aStatistic.data();
+ }, statistic)
+ );
+//deferredResult.addCallback(function() { console.timeEnd("Statistics.decrypt.setup")});
+
+ deferredResult.callback();
+ }
+//MochiKit.Logging.logDebug("<<< Statistics.decrypt");
+
+ return deferredResult;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'user': function() {
+ return this._user;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'data': function() {
+ return this._data;
+ },
+
+ 'setData': function(aValue) {
+ this._data = aValue;
+
+ this.extractInfoFromData(aValue);
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'extractInfoFromData': function(someValues) {
+
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'encryptedData': function() {
+ return Clipperz.PM.Crypto.deferredEncryptWithCurrentVersion(this.user().passphrase(), this.serializedData());
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'serializedData': function() {
+ var result;
+
+//MochiKit.Logging.logDebug(">>> Statistics.serializedData");
+ result = {};
+//MochiKit.Logging.logDebug("<<< Statistics.serializedData");
+
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+
+});
+
diff --git a/frontend/beta/js/Clipperz/PM/DataModel/User.js b/frontend/beta/js/Clipperz/PM/DataModel/User.js
new file mode 100644
index 0000000..5aaaff7
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/DataModel/User.js
@@ -0,0 +1,904 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. 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) {
+//MochiKit.Logging.logDebug(">>> new User");
+ args = args || {};
+
+ this._username = args.username || null;
+ this._passphrase = args.passphrase || null;
+
+ this._connection = null;
+ this._connectionVersion = 'current';
+
+ this._header = null;
+ this._statistics = null;
+ this._lock = 'new lock';
+
+ this._preferences = null;
+ this._records = {};
+ this._directLoginReferences = {};
+ this._oneTimePasswordManager = null;
+
+ this._isLoadingUserDetails = false;
+ this._loadingUserDetailsPendingQueue = [];
+
+ this._maxNumberOfRecords = Number.MAX_VALUE;
+
+ this._shouldDownloadOfflineCopy = false;
+
+ this._loginInfo = null;
+ this._loginHistory = null;
+
+ this._serverData = null;
+//MochiKit.Logging.logDebug("<<< new User");
+
+ return this;
+}
+
+Clipperz.PM.DataModel.User.prototype = MochiKit.Base.update(null, {
+
+ 'toString': function() {
+ return "Clipperz.PM.DataModel.User - " + this.username();
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'username': function() {
+ return this._username;
+ },
+
+ 'setUsername': function(aValue) {
+ this._username = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'passphrase': function() {
+ return this._passphrase;
+ },
+
+ 'setPassphrase': function(aValue) {
+ this._passphrase = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'maxNumberOfRecords': function() {
+ return this._maxNumberOfRecords;
+ },
+
+ 'setMaxNumberOfRecords': function(aValue) {
+ this._maxNumberOfRecords = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'errorHandler': function(anErrorString, anException) {
+MochiKit.Logging.logError("- User.errorHandler: " + anErrorString + " (" + anException + ")");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'connectionVersion': function() {
+ return this._connectionVersion;
+ },
+
+ 'setConnectionVersion': function(aValue) {
+ this._connectionVersion = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'connection': function() {
+ if ((this._connection == null) && (this.connectionVersion() != null) ){
+ this._connection = new Clipperz.PM.Crypto.communicationProtocol.versions[this.connectionVersion()]({user:this});
+ }
+
+ return this._connection;
+ },
+
+ 'resetConnection': function(aValue) {
+ this._connection = null;
+ },
+
+ //=========================================================================
+
+ 'register': function(anInvitationCode) {
+ var deferredResult;
+ var prng;
+
+//MochiKit.Logging.logError(">>> User.register: " + this);
+ prng = Clipperz.Crypto.PRNG.defaultRandomGenerator();
+
+ deferredResult = new MochiKit.Async.Deferred()
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("User.register - 1: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(prng, 'deferredEntropyCollection'));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("User.register - 2: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(this.header(), 'updateAllSections'), anInvitationCode);
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("User.register - 2.1: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(this.connection(), 'register'), anInvitationCode);
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("User.register - 3: " + res); return res;});
+ deferredResult.callback();
+//MochiKit.Logging.logError("<<< User.register");
+
+ return deferredResult;
+ },
+
+ //=========================================================================
+
+ 'connect': function(aValue) {
+ var deferredResult;
+ var prng;
+
+ prng = Clipperz.Crypto.PRNG.defaultRandomGenerator();
+
+//MochiKit.Logging.logDebug(">>> User.connect");
+ deferredResult = new MochiKit.Async.Deferred();
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("1.2.1 - User.connect - 1: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(prng, 'deferredEntropyCollection'));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("1.2.2 - User.connect - 2: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(this.connection(), 'login'));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("1.2.3 - User.connect - 3: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+
+// TODO: add an addErrback call here to manage a wrong login. Any error after this point is due to some other causes.
+// possibly the same exact 'handleConnectionFallback use at the end of this same method.
+
+ if (this.connectionVersion() != 'current') {
+ var currentConnection;
+
+ currentVersionConnection = new Clipperz.PM.Crypto.communicationProtocol.versions['current']({user:this});
+
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("1.2.4 - User.connect - 4: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+ deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', 'connection_upgrading');
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("1.2.5 - User.connect - 5: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(this.connection(), 'message'), 'upgradeUserCredentials', currentVersionConnection.serverSideUserCredentials());
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("1.2.6 - User.connect - 6: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+ }
+
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("1.2.7 - User.connect - 7: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+ deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'userConnected', null);
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("1.2.8 - User.connect - 8: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+ deferredResult.addErrback(MochiKit.Base.method(this, 'handleConnectionFallback'));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("1.2.9 - User.connect - 9: "/* + res*/); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("ERROR: " + res); return res;});
+
+ deferredResult.callback(aValue);
+//MochiKit.Logging.logDebug("<<< User.connect");
+
+ return deferredResult;
+ },
+
+ //.........................................................................
+
+ 'handleConnectionFallback': function(aValue) {
+ var result;
+//MochiKit.Logging.logDebug(">>> User.handleConnectionFallback");
+ if (aValue instanceof MochiKit.Async.CancelledError) {
+//MochiKit.Logging.logDebug("--- User.handleConnectionFallback - operation cancelled");
+ result = aValue;
+ } else {
+
+//MochiKit.Logging.logDebug("--- User.handleConnectionFallback - an ERROR has occurred - " + aValue);
+ this.resetConnection();
+ this.setConnectionVersion(Clipperz.PM.Crypto.communicationProtocol.fallbackVersions[this.connectionVersion()]);
+
+ if (this.connectionVersion() != null) {
+ result = new MochiKit.Async.Deferred();
+
+ result.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', 'connection_tryOlderSchema');
+ result.addCallback(MochiKit.Base.method(this, 'connect'));
+ result.callback();
+ } else {
+ result = MochiKit.Async.fail(Clipperz.PM.DataModel.User.exception.LoginFailed);
+ }
+ }
+//MochiKit.Logging.logDebug("<<< User.handleConnectionFallback");
+ return result;
+ },
+
+ //=========================================================================
+
+ 'header': function() {
+ if (this._header == null) {
+ this._header = new Clipperz.PM.DataModel.Header({user:this});
+ }
+ return this._header;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'statistics': function() {
+ if (this._statistics == null) {
+ this._statistics = new Clipperz.PM.DataModel.Statistics({user:this});
+ }
+ return this._statistics;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'records': function() {
+ return this._records;
+ },
+
+ //.........................................................................
+
+ 'addRecord': function(aValue, isBatchUpdate) {
+ this.records()[aValue.reference()] = aValue;
+
+ if (isBatchUpdate != true) {
+ Clipperz.NotificationCenter.notify(aValue, 'recordAdded', null, true);
+ Clipperz.NotificationCenter.notify(this, 'updatedSection', 'records', true);
+ }
+ },
+
+ //-----------------------------------------------------------------------------
+
+ 'addNewRecord': function() {
+ var record;
+
+//MochiKit.Logging.logDebug(">>> User.addNewRecord");
+ record = new Clipperz.PM.DataModel.Record({user:this});
+ this.addRecord(record);
+ Clipperz.NotificationCenter.notify(this, 'updatedSection', 'records', true);
+//MochiKit.Logging.logDebug("<<< User.addNewRecord");
+
+ return record;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'saveRecords': function(someRecords, aMethodName) {
+ var deferredResult;
+ var methodName;
+ var result;
+ var i,c;
+
+//console.log("User.saveRecords - someRecords", someRecords);
+ methodName = aMethodName || 'addNewRecords';
+
+ Clipperz.NotificationCenter.notify(this, 'updatedSection', 'records', true);
+//MochiKit.Logging.logDebug(">>> User.saveRecords");
+//MochiKit.Logging.logDebug(">>> [" + (new Date()).valueOf() + "] User.saveRecords");
+/*
+MochiKit.Logging.logDebug("--- User.saveRecords - 1");
+ MochiKit.Iter.forEach(someRecords, function(aRecord) {
+ if (aRecord.headerNotes() != null) {
+ aRecord.setNotes(aRecord.headerNotes());
+ }
+ aRecord.syncDirectLoginReferenceValues();
+ aRecord.currentVersion().createNewVersion();
+ aRecord.updateKey();
+ });
+MochiKit.Logging.logDebug("--- User.saveRecords - 2");
+*/
+
+ result = {'records': []};
+
+ deferredResult = new MochiKit.Async.Deferred();
+ c = someRecords.length;
+ for (i=0; i<c; i++) {
+ deferredResult.addCallback(function(aRecord) {
+ if (aRecord.headerNotes() != null) {
+ aRecord.setNotes(aRecord.headerNotes());
+ }
+ aRecord.syncDirectLoginReferenceValues();
+ aRecord.currentVersion().createNewVersion();
+ aRecord.updateKey();
+ }, someRecords[i]);
+ deferredResult.addCallback(MochiKit.Async.wait, 0.1);
+ }
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("User.saveRecords - 1 " + res); return res;});
+ deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', 'saveCard_collectRecordInfo');
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("User.saveRecords - 2 " + res); return res;});
+
+ deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', 'saveCard_encryptUserData');
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("User.saveRecords - 3 " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(this, 'encryptedData'));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("User.saveRecords - 4 " + res); return res;});
+ deferredResult.addCallback(function(aResult, res) {
+ aResult['user'] = res;
+ return aResult;
+ }, result);
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("User.saveRecords - 5 " + res); return res;});
+
+ c = someRecords.length;
+ for (i=0; i<c; i++) {
+ var recordData;
+
+ recordData = {};
+
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("User.saveRecords - 6.1 " + res); return res;});
+ deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', 'saveCard_encryptRecordData');
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("User.saveRecords - 6.2 " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(someRecords[i], 'encryptedData'));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("User.saveRecords - 6.3 " + res); return res;});
+ deferredResult.addCallback(function(aResult, res) {
+ aResult['record'] = res;
+ return aResult;
+ }, recordData);
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("User.saveRecords - 6.4 " + res); return res;});
+
+ deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', {} /*'saveCard_encryptRecordVersions'*/);
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("User.saveRecords - 6.5 " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(someRecords[i].currentVersion(), 'encryptedData'));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("User.saveRecords - 6.6 " + res); return res;});
+ deferredResult.addCallback(function(aResult, res) {
+ aResult['currentRecordVersion'] = res;
+ return aResult;
+ }, recordData);
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("User.saveRecords - 6.7 " + res); return res;});
+
+ deferredResult.addCallback(function(aResult, res) {
+ aResult['records'].push(res);
+ return aResult;
+ }, result);
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("User.saveRecords - 6.8 " + res); return res;});
+ }
+
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("User.saveRecords - 7 " + res); return res;});
+ deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', 'saveCard_sendingData');
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("User.saveRecords - 8 " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(this.connection(), 'message'), methodName);
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("User.saveRecords - 9 " + res); return res;});
+
+ for (i=0; i<c; i++) {
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("User.saveRecords - 9.1 " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(someRecords[i], 'takeSnapshotOfCurrentData'));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("User.saveRecords - 9.2 " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(someRecords[i], 'setIsBrandNew'), false);
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("User.saveRecords - 9.3 " + res); return res;});
+ }
+
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("User.saveRecords - 10 " + res); return res;});
+ deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'notify', 'recordUpdated');
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("User.saveRecords - 11 " + res); return res;});
+ deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'notify', 'directLoginUpdated');
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("User.saveRecords - 12 " + res); return res;});
+ deferredResult.callback();
+
+ return deferredResult;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'removeRecord': function(aRecord) {
+//MochiKit.Logging.logDebug(">>> User.removeRecord");
+ delete this.records()[aRecord.reference()];
+//MochiKit.Logging.logDebug("--- User.removeRecord - 1");
+ Clipperz.NotificationCenter.notify(aRecord, 'recordRemoved', null, false);
+ Clipperz.NotificationCenter.notify(this, 'updatedSection', 'records', true);
+//MochiKit.Logging.logDebug("<<< User.removeRecord");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'deleteRecordsAction': function(someRecords) {
+ var deferredResult;
+ var parameters;
+
+//MochiKit.Logging.logDebug(">>> User.deleteRecordsAction - someRecords.length: " + someRecords.length);
+ parameters = {};
+ deferredResult = new MochiKit.Async.Deferred();
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("User.deleteRecordsAction - 1 " + res); return res;});
+ deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', 'deleteRecord_collectData');
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("User.deleteRecordsAction - 2 " + res); return res;});
+ deferredResult.addCallback(function(someParameters, someRecords) {
+ var recordReferences;
+
+ recordReferences = MochiKit.Base.map(function(aRecord) {
+ var result;
+
+ result = aRecord.reference();
+ aRecord.remove();
+
+ return result;
+ }, someRecords);
+ someParameters.recordReferences = recordReferences;
+
+ return someParameters;
+ }, parameters);
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("User.deleteRecordsAction - 3 " + res); return res;});
+ deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', 'deleteRecord_encryptData');
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("User.deleteRecordsAction - 4 " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(this, 'encryptedData'));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("User.deleteRecordsAction - 5 " + res); return res;});
+ deferredResult.addCallback(function(someParameters, anUserEncryptedData) {
+ someParameters.user = anUserEncryptedData;
+ return someParameters;
+ }, parameters);
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("User.deleteRecordsAction - 6 " + res); return res;});
+ deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', 'deleteRecord_sendingData');
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("User.deleteRecords parameters: " + Clipperz.Base.serializeJSON(res)); return res;});
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("User.deleteRecordsAction - 7 " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(this.connection(), 'message'), 'deleteRecords');
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("User.deleteRecordsAction - 8 " + res); return res;});
+ deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', 'deleteRecord_updatingInterface');
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("User.deleteRecordsAction - 9 " + res); return res;});
+ deferredResult.callback(someRecords);
+//MochiKit.Logging.logDebug("<<< User.deleteRecordsAction");
+
+ return deferredResult;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'resetAllLocalData': function() {
+ this.resetConnection();
+
+ this.setUsername("");
+ this.setPassphrase("");
+
+ this._header = null;
+ this._statistics = null;
+ this._preferences = null;
+ this._records = {};
+ this._directLoginReferences = {};
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'deleteAccountAction': function() {
+ var deferredResult;
+
+//MochiKit.Logging.logDebug(">>> user.deleteAccountAction - " + this);
+ deferredResult = new MochiKit.Async.Deferred();
+ deferredResult.addCallback(MochiKit.Base.method(this.connection(), 'message'), 'deleteUser');
+ deferredResult.addCallback(MochiKit.Base.method(this, 'resetAllLocalData'));
+ deferredResult.callback();
+//MochiKit.Logging.logDebug("<<< user.deleteAccountAction - " + this);
+
+ return deferredResult;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'encryptedData': function() {
+ var deferredResult;
+ var result;
+
+ result = {};
+
+ deferredResult = new MochiKit.Async.Deferred();
+
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("User.encryptedData - 0: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(this.header(), 'encryptedData'));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("User.encryptedData - 1: " + res); return res;});
+ deferredResult.addCallback(function(aResult, aValue) {
+ aResult['header'] = aValue;
+ }, result);
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("User.encryptedData - 2: " + res); return res;});
+
+ deferredResult.addCallback(MochiKit.Base.method(this.statistics(), 'encryptedData'));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("User.encryptedData - 3: " + res); return res;});
+ deferredResult.addCallback(function(aResult, aValue) {
+ aResult['statistics'] = aValue;
+ }, result);
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("User.encryptedData - 4: " + res); return res;});
+
+ deferredResult.addCallback(MochiKit.Base.bind(function(aResult, aValue) {
+ aResult['version'] = Clipperz.PM.Crypto.encryptingFunctions.currentVersion;
+ aResult['lock'] = this.lock();
+
+ return aResult;
+ }, this), result);
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("User.encryptedData - 5: " + res); return res;});
+ deferredResult.callback();
+
+ return deferredResult;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'preferences': function() {
+ if (this._preferences == null) {
+ this._preferences = new Clipperz.PM.DataModel.UserPreferences({user:this});
+ }
+
+ return this._preferences;
+ },
+/*
+ 'setPreferences': function(aValue) {
+ this._preferences = aValue;
+
+ if (this._preferences.preferredLanguage() != null) {
+ Clipperz.PM.Strings.Languages.setSelectedLanguage(this._preferences.preferredLanguage());
+ } else {
+//MochiKit.Logging.logDebug("### keepping the browser selected language: " + Clipperz.PM.Strings.selectedLanguage);
+ }
+ },
+*/
+ //-------------------------------------------------------------------------
+
+ 'oneTimePasswordManager': function() {
+ if (this._oneTimePasswordManager == null) {
+ this._oneTimePasswordManager = new Clipperz.PM.DataModel.OneTimePasswordManager(this, null);
+ }
+
+ return this._oneTimePasswordManager;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'directLoginReferences': function() {
+ return this._directLoginReferences;
+ },
+
+ 'addDirectLoginReference': function(aDirectLoginReference, isBatchUpdate) {
+//MochiKit.Logging.logDebug(">>> User.addDirectLoginReference");
+ this.directLoginReferences()[aDirectLoginReference.reference()] = aDirectLoginReference;
+
+ if (isBatchUpdate != true) {
+ Clipperz.NotificationCenter.notify(aDirectLoginReference, 'directLoginAdded');
+ Clipperz.NotificationCenter.notify(this, 'updatedSection', 'directLogins', true);
+ }
+ },
+
+ 'removeDirectLoginReference': function(aDirectLoginReference) {
+ delete this.directLoginReferences()[aDirectLoginReference.reference()];
+ Clipperz.NotificationCenter.notify(aDirectLoginReference, 'directLoginRemoved');
+ Clipperz.NotificationCenter.notify(this, 'updatedSection', 'directLogins', true);
+ },
+
+ //.........................................................................
+
+ 'addDirectLogin': function(aDirectLogin) {
+ var newDirectLoginReference;
+
+ newDirectLoginReference = new Clipperz.PM.DataModel.DirectLoginReference({user:this, directLogin:aDirectLogin})
+ this.addDirectLoginReference(newDirectLoginReference);
+ },
+
+ 'synchronizeDirectLogin': function(aDirectLogin) {
+ var directLoginReference;
+
+ directLoginReference = this.directLoginReferences()[aDirectLogin.reference()];
+ if (typeof(directLoginReference) != 'undefined') {
+ directLoginReference.synchronizeValues(aDirectLogin);
+ } else {
+ this.addDirectLogin(aDirectLogin);
+ }
+ },
+
+ 'removeDirectLogin': function(aDirectLogin) {
+ this.removeDirectLoginReference(aDirectLogin);
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'changeCredentials': function(aUsername, aPassphrase) {
+ var deferredResult;
+ var result;
+
+ result = {};
+
+ deferredResult = new MochiKit.Async.Deferred();
+
+ deferredResult.addCallback(MochiKit.Base.method(this.header(), 'loadAllSections'));
+ deferredResult.addCallback(MochiKit.Base.method(this.header(), 'updateAllSections'));
+
+ deferredResult.addCallback(MochiKit.Base.bind(function(aUsername, aPssphrase) {
+ this.setUsername(aUsername);
+ this.setPassphrase(aPassphrase);
+ }, this), aUsername, aPassphrase)
+
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("User.changeCredentials - 1: " + res); return res;});
+ deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', 'changeCredentials_encryptingData');
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("User.changeCredentials - 2: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(this, 'encryptedData'));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("User.changeCredentials - 3: " + res); return res;});
+ deferredResult.addCallback(function(aResult, anEncryptedData) {
+ aResult['user'] = anEncryptedData;
+
+ return aResult;
+ }, result);
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("User.changeCredentials - 4: " + res); return res;});
+ deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', 'changeCredentials_creatingNewCredentials');
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("User.changeCredentials - 5: " + res); return res;});
+ deferredResult.addCallback(function(aResult, anUser) {
+ var newConnection;
+
+ newConnection = new Clipperz.PM.Crypto.communicationProtocol.versions[Clipperz.PM.Crypto.communicationProtocol.currentVersion]({user:anUser})
+ aResult['credentials'] = newConnection.serverSideUserCredentials();
+
+ return aResult;
+ }, result, this);
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("User.changeCredentials - 6: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(this.oneTimePasswordManager(), 'encryptedData'));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("User.changeCredentials - 7: " + res); return res;});
+ deferredResult.addCallback(function(aResult, anEncryptedData) {
+ aResult['oneTimePasswords'] = anEncryptedData;
+
+ return aResult;
+ }, result);
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("User.changeCredentials - 8: " + res); return res;});
+ deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', 'changeCredentials_sendingCredentials');
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("User.changeCredentials - 9: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(this.connection(), 'message'), 'upgradeUserCredentials');
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("User.changeCredentials - 10: " + res); return res;});
+ deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', 'changeCredentials_done');
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("User.changeCredentials - 11: " + res); return res;});
+ deferredResult.callback();
+
+ return deferredResult;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'doLogout': function() {
+ var deferredResult;
+
+ deferredResult = new MochiKit.Async.Deferred();
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("User.doLogout - 1: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(this.connection(), 'logout'));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("User.doLogout - 2: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(this, 'resetAllLocalData'));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("User.doLogout - 3: " + res); return res;});
+
+ deferredResult.callback();
+
+ return deferredResult;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'lock': function() {
+ this.setPassphrase("")
+ this.connection().logout();
+ this.connection().resetSrpConnection();
+ },
+
+ 'unlockWithPassphrase': function(aValue) {
+ var deferredResult;
+// var connection;
+
+// connection = this.connection();
+
+ deferredResult = new MochiKit.Async.Deferred();
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("User.unlockWithPassphrase 1: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(this, 'setPassphrase'));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("User.unlockWithPassphrase 2: " + res); return res;});
+// deferredResult.addCallback(MochiKit.Base.method(connection, 'message'), 'echo', {'echo':"echo"});
+ deferredResult.addCallback(MochiKit.Base.method(this.connection(), 'reestablishConnection'));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("User.unlockWithPassphrase 3: " + res); return res;});
+// deferredResult.addErrback(MochiKit.Base.method(this, 'setPassphrase', ""));
+ deferredResult.addErrback(MochiKit.Base.bind(function(anError) {
+ this.setPassphrase("");
+ this.connection().resetSrpConnection();
+
+ return anError;
+ }, this));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("User.unlockWithPassphrase 4: " + res); return res;});
+ deferredResult.callback(aValue);
+
+ return deferredResult;
+ },
+
+ //-------------------------------------------------------------------------
+ //-------------------------------------------------------------------------
+ //-------------------------------------------------------------------------
+ //-------------------------------------------------------------------------
+ //-------------------------------------------------------------------------
+ //-------------------------------------------------------------------------
+ //-------------------------------------------------------------------------
+ //-------------------------------------------------------------------------
+ //-------------------------------------------------------------------------
+ //-------------------------------------------------------------------------
+ //-------------------------------------------------------------------------
+ //-------------------------------------------------------------------------
+
+ 'serverData': function() {
+ return this._serverData;
+ },
+
+ 'setServerData': function(aValue) {
+//MochiKit.Logging.logDebug(">>> User.setServerData");
+ this._serverData = aValue;
+
+ if (typeof(aValue.maxNumberOfRecords) != 'undefined') {
+ this.setMaxNumberOfRecords(aValue.maxNumberOfRecords);
+ }
+//MochiKit.Logging.logDebug("<<< User.setServerData");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'isLoadingUserDetails': function() {
+ return this._isLoadingUserDetails;
+ },
+
+ 'setIsLoadingUserDetails': function(aValue) {
+ this._isLoadingUserDetails = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'loadingUserDetailsPendingQueue': function() {
+ return this._loadingUserDetailsPendingQueue;
+ },
+
+ 'flushLoadingUserDetailsPendingQueue': function() {
+ var queue;
+
+//MochiKit.Logging.logDebug(">>> User.flushLoadingUserDetailsPendingQueue");
+ queue = this.loadingUserDetailsPendingQueue();
+
+ while(queue.length > 0) {
+//MochiKit.Logging.logDebug("--- User.flushLoadingUserDetailsPendingQueue - pop");
+ queue.pop().callback();
+ }
+//MochiKit.Logging.logDebug("<<< User.flushLoadingUserDetailsPendingQueue");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'getUserDetails': function() {
+ var deferredResult;
+
+//MochiKit.Logging.logDebug(">>> User.getUserDetails");
+ deferredResult = new MochiKit.Async.Deferred();
+ if ((this.serverData() == null) && (this.isLoadingUserDetails() == false)) {
+ deferredResult.addCallback(MochiKit.Base.method(this, 'setIsLoadingUserDetails', true));
+ deferredResult.addCallback(MochiKit.Base.method(this.connection(), 'message'), 'getUserDetails');
+ deferredResult.addCallback(MochiKit.Base.method(this, 'setServerData'));
+ deferredResult.addCallback(MochiKit.Base.method(this, 'flushLoadingUserDetailsPendingQueue'));
+ deferredResult.addCallback(MochiKit.Base.method(this, 'setIsLoadingUserDetails', false));
+ }
+
+ deferredResult.addCallback(MochiKit.Base.method(this, 'serverData'));
+
+ if (this.isLoadingUserDetails() == false) {
+ deferredResult.callback();
+ } else {
+ this.loadingUserDetailsPendingQueue().push(deferredResult);
+ }
+//MochiKit.Logging.logDebug("<<< User.getUserDetails");
+
+ return deferredResult;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'loadRecords': function() {
+ return this.header().loadRecords();
+ },
+
+ 'loadDirectLogins': function() {
+ return this.header().loadDirectLogins();
+ },
+
+ 'loadPreferences': function() {
+ return this.header().loadPreferences();
+ },
+
+ 'loadOneTimePasswords': function() {
+ return this.header().loadOneTimePasswords();
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'loadLoginHistory': function() {
+ var deferredResult;
+
+ deferredResult = new MochiKit.Async.Deferred();
+ deferredResult.addCallback(MochiKit.Base.method(this.connection(), 'message'), 'getLoginHistory');
+ deferredResult.addCallback(function(aResult) {
+ return aResult['result'];
+ });
+ deferredResult.addCallback(MochiKit.Base.method(this, 'setLoginHistory'));
+ deferredResult.addCallback(MochiKit.Base.method(this, 'loginHistory'));
+ deferredResult.callback();
+
+ return deferredResult;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'shouldDownloadOfflineCopy': function() {
+ return this._shouldDownloadOfflineCopy;
+ },
+
+ 'setShouldDownloadOfflineCopy': function(aValue) {
+ this._shouldDownloadOfflineCopy = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'loginInfo': function() {
+ return this._loginInfo;
+ },
+
+ 'setLoginInfo': function(aValue) {
+ this._loginInfo = aValue;
+//MochiKit.Logging.logDebug("### LoginInfo: " + Clipperz.Base.serializeJSON(aValue));
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'loginHistory': function() {
+ return this._loginHistory;
+ },
+
+ 'setLoginHistory': function(aValue) {
+ this._loginHistory = aValue;
+ },
+/*
+ 'loginInfoWithOneTimePasswordReference': function(aOneTimePasswordReference) {
+ var result;
+ var i,c;
+
+ result = null;
+ c = this.loginHistory().length;
+ for (i=0; (i<c) && (result == null); i++) {
+ var currentLoginInfo;
+
+ currentLoginInfo = this.loginHistory()[i];
+ if (currentLoginInfo['oneTimePasswordReference'] == aOneTimePasswordReference) {
+ result = currentLoginInfo;
+ }
+ }
+
+ return result;
+ },
+*/
+ //-------------------------------------------------------------------------
+
+ 'lock': function() {
+ return this._lock;
+ },
+
+ 'setLock': function(aValue) {
+//MochiKit.Logging.logDebug("=== User.setLock: " + aValue);
+ this._lock = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+
+});
+
+
+Clipperz.PM.DataModel.User.exception = {
+ LoginFailed: new MochiKit.Base.NamedError("Clipperz.PM.DataModel.User.exception.LoginFailed")
+};
+
diff --git a/frontend/beta/js/Clipperz/PM/DataModel/UserPreferences.js b/frontend/beta/js/Clipperz/PM/DataModel/UserPreferences.js
new file mode 100644
index 0000000..dc73ce1
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/DataModel/UserPreferences.js
@@ -0,0 +1,197 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. 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.UserPreferences = function(args) {
+ args = args || {};
+
+ this._user = args['user']; delete args['user'];
+ this._config = args;
+
+ return this;
+}
+
+Clipperz.PM.DataModel.UserPreferences.prototype = MochiKit.Base.update(null, {
+
+ //-------------------------------------------------------------------------
+
+ 'config': function() {
+ return this._config;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'user': function() {
+ return this._user;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'updateWithData': function(someValues) {
+ var currentLanguage;
+
+//MochiKit.Logging.logDebug(">>> Clipperz.PM.DataModel.UserPreferences.updateWithData: " + Clipperz.Base.serializeJSON(someValues));
+ currentLanguage = this.preferredLanguage();
+
+ MochiKit.Base.update(this._config, someValues);
+
+ if (this.preferredLanguage() != currentLanguage) {
+ Clipperz.PM.Strings.Languages.setSelectedLanguage(this.preferredLanguage());
+ } else {
+//MochiKit.Logging.logDebug("### keepping the browser selected language: " + Clipperz.PM.Strings.selectedLanguage);
+ }
+
+ return this;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'configValue': function(aConfigName, aDefaultValue) {
+ var result;
+
+//MochiKit.Logging.logDebug(">>> UserPreferences.configValue - config: " + Clipperz.Base.serializeJSON(this.config()));
+ if (typeof(this.config()[aConfigName]) == 'undefined') {
+ result = aDefaultValue;
+ } else {
+ result = this.config()[aConfigName];
+ }
+//MochiKit.Logging.logDebug("<<< UserPreferences.configValue");
+
+ return result;
+ },
+
+ 'setConfigValue': function(aConfigName, aValue) {
+ var result;
+
+ if (aValue != this.configValue(aConfigName)) {
+ if (aValue == null) {
+ delete this.config()[aConfigName]
+ } else {
+ this.config()[aConfigName] = aValue;
+ }
+
+ Clipperz.NotificationCenter.notify(this.user(), 'updatedSection', 'preferences', true);
+
+ result = true;
+ } else {
+ result = false;
+ }
+
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'useSafeEditMode': function() {
+ return this.configValue('useSafeEditMode', true);
+ },
+
+ 'setUseSafeEditMode': function(aValue) {
+ this.setConfigValue('useSafeEditMode', aValue);
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'preferredLanguage': function() {
+ return this.configValue('preferredLanguage', null);
+ },
+
+ 'setPreferredLanguage': function(aValue) {
+ if (this.setConfigValue('preferredLanguage', aValue)) {
+ Clipperz.PM.Strings.Languages.setSelectedLanguage(this.preferredLanguage());
+ }
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'shouldShowDonationPanel': function() {
+ return this.configValue('shouldShowDonationPanel', true);
+ },
+
+ 'setShouldShowDonationPanel': function(aValue) {
+ this.setConfigValue('shouldShowDonationPanel', aValue);
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'disableUnsecureFaviconLoadingForIE': function() {
+ return this.configValue('disableUnsecureFaviconLoadingForIE', false);
+ },
+
+ 'setDisableUnsecureFaviconLoadingForIE': function(aValue) {
+ this.setConfigValue('disableUnsecureFaviconLoadingForIE', aValue);
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'serializedData': function() {
+ return this.config();
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'saveChanges': function(aReferenceElement) {
+ var deferredResult;
+
+ deferredResult = new MochiKit.Async.Deferred();
+
+ deferredResult.addCallback(MochiKit.Base.method(Clipperz.PM.Components.MessageBox(), 'deferredShow'),
+ {
+ title:"", // Clipperz.PM.Strings['accountPreferencesSavingPanelTitle_Step1'],
+ text:"", // Clipperz.PM.Strings['accountPreferencesSavingPanelText_Step1'],
+ width:240,
+ showProgressBar:true,
+ showCloseButton:false
+ },
+ aReferenceElement
+ );
+ deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', 'account_savingPreferences_1');
+ deferredResult.addCallback(MochiKit.Base.method(this.user(), 'encryptedData'));
+ deferredResult.addCallback(function(res) {
+ return {user:res};
+ })
+ deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', 'account_savingPreferences_2');
+ deferredResult.addCallback(MochiKit.Base.method(this.user().connection(), 'message'), 'updateData');
+ deferredResult.addCallback(Clipperz.PM.Components.MessageBox().hide, YAHOO.ext.Element.get('main'));
+ deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedPreferences', null);
+
+ deferredResult.callback();
+
+ return deferredResult;
+ },
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+});
+
diff --git a/frontend/beta/js/Clipperz/PM/Date.js b/frontend/beta/js/Clipperz/PM/Date.js
new file mode 100644
index 0000000..5e21340
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Date.js
@@ -0,0 +1,193 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. 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['calendarStrings']['amDesignation'],
+ 'pmDesignation': Clipperz.PM.Strings['calendarStrings']['pmDesignation'],
+ 'days': Clipperz.PM.Strings['calendarStrings']['days'],
+ 'shortDays': Clipperz.PM.Strings['calendarStrings']['shortDays'],
+ 'shortMonths': Clipperz.PM.Strings['calendarStrings']['shortMonths'],
+ 'months': Clipperz.PM.Strings['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());
+ },
+*/
+ //=========================================================================
+
+ '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['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['elapsedTimeDescriptions']['MORE_THAN_A_WEEK_AGO'];
+ } else {
+ result = Clipprez.PM.Strings['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['elapsedTimeDescriptions']['YESTERDAY'];
+ } else {
+ result = Clipperz.PM.Strings['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['elapsedTimeDescriptions']['ABOUT_AN_HOUR_AGO'];
+ } else {
+ result = Clipperz.PM.Strings['elapsedTimeDescriptions']['*_HOURS_AGO'].replace(/__elapsed__/, elapsedHours);
+ }
+ } else {
+ var elapsed10Minutes;
+
+ elapsed10Minutes = (Math.floor((elapsedTime / millisencondsInAMinute) / 10)) * 10;
+ if (elapsed10Minutes == 0) {
+ result = Clipperz.PM.Strings['elapsedTimeDescriptions']['JUST_A_FEW_MINUTES_AGO'];
+ } else {
+ result = Clipperz.PM.Strings['elapsedTimeDescriptions']['ABOUT_*_MINUTES_AGO'].replace(/__elapsed__/, elapsed10Minutes+"");
+ }
+ }
+ }
+
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+
+});
+
diff --git a/frontend/beta/js/Clipperz/PM/Main.js b/frontend/beta/js/Clipperz/PM/Main.js
new file mode 100644
index 0000000..9a068e1
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Main.js
@@ -0,0 +1,588 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
+
+Clipperz.PM.VERSION = "0.1";
+Clipperz.PM.NAME = "Clipperz.PM";
+
+//#############################################################################
+
+Clipperz.PM.Main = function() {
+ this._loginPanel = null;
+ this._user = null;
+
+ this._isRunningCompact = false;
+
+ Clipperz.NotificationCenter.register(null, 'userConnected', this, 'userConnectedCallback');
+ Clipperz.NotificationCenter.register(null, 'switchLanguage', this, 'switchLanguageHandler');
+
+ Clipperz.NotificationCenter.register(null, 'EXCEPTION', this, 'reportException');
+
+ return this;
+}
+
+//=============================================================================
+
+MochiKit.Base.update(Clipperz.PM.Main.prototype, {
+ 'toString': function() {
+ return "Clipperz.PM.Main";
+ },
+
+ 'switchLanguageHandler': function() {
+//MochiKit.Logging.logDebug(">>> main.switchLanguageHandler");
+ YAHOO.ext.Element.get('donateHeaderIconLink').dom.href = Clipperz.PM.Strings['donateHeaderLinkUrl'];
+ YAHOO.ext.Element.get('donateHeaderLink').update(Clipperz.PM.Strings['donateHeaderLinkLabel']).dom.href = Clipperz.PM.Strings['donateHeaderLinkUrl'];
+ YAHOO.ext.Element.get('creditsHeaderLink').update(Clipperz.PM.Strings['creditsHeaderLinkLabel']).dom.href = Clipperz.PM.Strings['creditsHeaderLinkUrl'];
+ YAHOO.ext.Element.get('feedbackHeaderLink').update(Clipperz.PM.Strings['feedbackHeaderLinkLabel']).dom.href = Clipperz.PM.Strings['feedbackHeaderLinkUrl'];
+ YAHOO.ext.Element.get('helpHeaderLink').update(Clipperz.PM.Strings['helpHeaderLinkLabel']).dom.href = Clipperz.PM.Strings['helpHeaderLinkUrl'];
+ YAHOO.ext.Element.get('forumHeaderLink').update(Clipperz.PM.Strings['forumHeaderLinkLabel']).dom.href = Clipperz.PM.Strings['forumHeaderLinkUrl'];
+
+ if (YAHOO.ext.Element.get('logout') != null) {
+ YAHOO.ext.Element.get('logout').update(Clipperz.PM.Strings['logoutMenuLabel']);
+ YAHOO.ext.Element.get('lock').update(Clipperz.PM.Strings['lockMenuLabel']);
+
+ YAHOO.ext.Element.get('recordsTabAnchor').update(Clipperz.PM.Strings['recordMenuLabel']);
+ YAHOO.ext.Element.get('accountTabAnchor').update(Clipperz.PM.Strings['accountMenuLabel']);
+ YAHOO.ext.Element.get('dataTabAnchor').update(Clipperz.PM.Strings['dataMenuLabel']);
+// YAHOO.ext.Element.get('contactsTabAnchor').update(Clipperz.PM.Strings['contactsMenuLabel']);
+ YAHOO.ext.Element.get('toolsTabAnchor').update(Clipperz.PM.Strings['toolsMenuLabel']);
+ }
+//MochiKit.Logging.logDebug("<<< main.switchLanguageHandler");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'fixToDrawTheMainTabsCorrectlyOnSafari': function() {
+ this.switchLanguageHandler();
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'run': function(shouldShowRegistrationForm) {
+ var mainElement;
+
+ Clipperz.NotificationCenter.register(null, 'updatedProgressState', this, 'updateProgressDialogStatus');
+
+ YAHOO.ext.Element.get('recordDetailEditModeHeaderMask').setVisibilityMode(YAHOO.ext.Element.DISPLAY).hide().unmask();
+ YAHOO.ext.Element.get('recordDetailEditModeVerticalMask').setVisibilityMode(YAHOO.ext.Element.DISPLAY).hide().unmask();
+
+//MochiKit.Logging.logDebug(">>> Main.run");
+ mainElement = YAHOO.ext.Element.get('main');
+ if (Clipperz.PM.Proxy.defaultProxy.isReadOnly()) {
+ YAHOO.ext.Element.get('applicationVersionType').dom.className = "readOnly";
+ }
+ mainElement.update("");
+
+ Clipperz.YUI.DomHelper.append(mainElement.dom, {tag:'ul', cls:'clipperzTabPanels', children:[
+ {tag:'li', id:'loginPanel'}
+ ]})
+
+ this.setLoginPanel(new Clipperz.PM.Components.Panels.LoginPanel(YAHOO.ext.Element.get('loginPanel')));
+
+//MochiKit.Logging.logDebug("--- Main.run - selecting active form to show ...");
+ if (shouldShowRegistrationForm == true) {
+ this.loginPanel().showRegistrationForm(false);
+ } else {
+ this.loginPanel().showLoginForm(false);
+ }
+
+ this.switchLanguageHandler();
+//MochiKit.Logging.logDebug("--- Main.run - selecting active form to show. done.");
+//MochiKit.Logging.logDebug("<<< Main.run");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'runCompact': function() {
+ this.setIsRunningCompact(true);
+ YAHOO.ext.Element.get(document.body).addClass("compact");
+ new Clipperz.PM.Components.Compact.LoginForm(YAHOO.ext.Element.get('mainDiv'));
+ },
+
+ 'showCompactInterface': function() {
+//MochiKit.Logging.logDebug(">>> main.showCompactInterface");
+ new Clipperz.PM.Components.Compact.CompactInterface(YAHOO.ext.Element.get('compactBody'), {user:this.user()});
+//MochiKit.Logging.logDebug("<<< main.showCompactInterface");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'mainPage': function() {
+ if (this._mainPage == null) {
+ this._mainPage = new Clipperz.PM.Components.MainPage();
+ }
+
+ return this._mainPage;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'loginPanel': function() {
+ return this._loginPanel;
+ },
+
+ 'setLoginPanel': function(aValue) {
+ this._loginPanel = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'showMainPanels': function() {
+ var mainElement;
+ var logoutBlock;
+ var lockBlock;
+ var menusTRElement;
+
+ this.loginPanel().remove();
+ this.setLoginPanel(null);
+
+ logoutBlock = YAHOO.ext.Element.get('logoutLI');
+ Clipperz.YUI.DomHelper.append(logoutBlock.dom, {tag:'a', href:"#", id:'logout', htmlString:Clipperz.PM.Strings['logoutMenuLabel']});
+ MochiKit.Signal.connect('logout', 'onclick', this, 'doLogoutEventHandler');
+
+ lockBlock = YAHOO.ext.Element.get('lockLI');
+ Clipperz.YUI.DomHelper.append(lockBlock.dom, {tag:'a', href:"#", id:'lock', htmlString:Clipperz.PM.Strings['lockMenuLabel']});
+ MochiKit.Signal.connect('lock', 'onclick', this, 'doLockEventHandler');
+
+ menusTRElement = YAHOO.ext.Element.get('menusTR');
+ Clipperz.YUI.DomHelper.append(menusTRElement.dom, {tag:'td', id:'recordsTab', children:[{tag:'div', children:[{tag:'a', id:'recordsTabAnchor', htmlString:Clipperz.PM.Strings['recordMenuLabel']}]}]});
+ Clipperz.YUI.DomHelper.append(menusTRElement.dom, {tag:'td', id:'accountTab', children:[{tag:'div', children:[{tag:'a', id:'accountTabAnchor', htmlString:Clipperz.PM.Strings['accountMenuLabel']}]}]});
+ Clipperz.YUI.DomHelper.append(menusTRElement.dom, {tag:'td', id:'dataTab', children:[{tag:'div', children:[{tag:'a', id:'dataTabAnchor', htmlString:Clipperz.PM.Strings['dataMenuLabel']}]}]});
+// Clipperz.YUI.DomHelper.append(menusTRElement.dom, {tag:'td', id:'contactsTab', children:[{tag:'div', children:[{tag:'a', id:'contactsTabAnchor', htmlString:Clipperz.PM.Strings['contactsMenuLabel']}]}]});
+ Clipperz.YUI.DomHelper.append(menusTRElement.dom, {tag:'td', id:'toolsTab', children:[{tag:'div', children:[{tag:'a', id:'toolsTabAnchor', htmlString:Clipperz.PM.Strings['toolsMenuLabel']}]}]});
+
+ mainElement = YAHOO.ext.Element.get('main');
+ mainElement.update("");
+ Clipperz.YUI.DomHelper.append(mainElement.dom, {tag:'ul', cls:'clipperzTabPanels', children:[
+ {tag:'li', id:'recordsPanel'},
+ {tag:'li', id:'accountPanel'},
+ {tag:'li', id:'dataPanel'},
+// {tag:'li', id:'contactsPanel'},
+ {tag:'li', id:'toolsPanel'}
+ ]}, true)
+
+ new Clipperz.PM.Components.TabPanel.TabPanelController({
+ name: 'mainTabPanel',
+ config:{ 'recordsTab':'recordsPanel',
+ 'accountTab':'accountPanel',
+ 'dataTab':'dataPanel',
+// 'contactsTab':'contactsPanel',
+ 'toolsTab':'toolsPanel'},
+ selectedTab:'recordsTab'
+ }).setUp();
+
+ new Clipperz.PM.Components.Panels.MainPanel(YAHOO.ext.Element.get('recordsPanel'), {user:this.user()});
+ new Clipperz.PM.Components.Panels.AccountPanel(YAHOO.ext.Element.get('accountPanel'), {user:this.user()});
+ new Clipperz.PM.Components.Panels.DataPanel(YAHOO.ext.Element.get('dataPanel'), {user:this.user()});
+// new Clipperz.PM.Components.Panels.ContactsPanel(YAHOO.ext.Element.get('contactsPanel'), {user:this.user()});
+ new Clipperz.PM.Components.Panels.ToolsPanel(YAHOO.ext.Element.get('toolsPanel'), {user:this.user()});
+
+ this.fixToDrawTheMainTabsCorrectlyOnSafari(); // fix to
+//MochiKit.Logging.logDebug("<<< Main.showMainPanels");
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'userConnectedCallback': function(anEvent) {
+//MochiKit.Logging.logDebug(">>> Main.userConnectedCallback");
+//MochiKit.Logging.logDebug(">>> doConnect - user: " + this.user());
+ this.setUser(anEvent.source());
+
+ if (this.isRunningCompact()) {
+ this.showCompactInterface();
+ } else {
+ this.showMainPanels();
+ }
+//MochiKit.Logging.logDebug("<<< Main.userConnectedCallback");
+ },
+
+ //-----------------------------------------------------------------------------
+
+ 'user': function() {
+ return this._user;
+ },
+
+ 'setUser': function(aValue) {
+ this._user = aValue;
+ },
+
+ //-----------------------------------------------------------------------------
+
+ 'doLogoutEventHandler': function(anEvent) {
+ var deferred;
+
+ anEvent.stop();
+
+ deferred = new MochiKit.Async.Deferred();
+//deferred.addBoth(function(res) {MochiKit.Logging.logDebug("Main.doLogoutEventHandler - 1: " + res); return res;});
+ deferred.addCallback(MochiKit.Base.method(this.user(), 'doLogout'));
+//deferred.addBoth(function(res) {MochiKit.Logging.logDebug("Main.doLogoutEventHandler - 2: " + res); return res;});
+ deferred.addCallback(Clipperz.PM.exit, 'logout.html');
+//deferred.addBoth(function(res) {MochiKit.Logging.logDebug("Main.doLogoutEventHandler - 3: " + res); return res;});
+ deferred.callback();
+ },
+
+ //-----------------------------------------------------------------------------
+
+ 'doLockEventHandler': function(anEvent) {
+ var deferredResult;
+ var lockDialogElement;
+ var lockDialog;
+ var unlockButton;
+
+ anEvent.stop();
+
+ Clipperz.NotificationCenter.notify(this, 'accountLocked', null, true);
+
+ lockDialogElement = Clipperz.YUI.DomHelper.append(document.body, {tag:'div', id:'lockDialog', children:[
+ {tag:'div', cls:'ydlg-hd', htmlString:Clipperz.PM.Strings['lockTitle']},
+ {tag:'div', cls:'ydlg-bd', children:[
+ {tag:'div', cls:'alert-message', id:'lockMessage', children:[
+ {tag:'div', htmlString:Clipperz.PM.Strings['lockDescription']},
+ {tag:'form', id:'lockDialogForm', children:[
+ {tag:'input', type:'password', id:'lockPassphrase'}
+ ]}
+ ]}
+ ]},
+ {tag:'div', cls:'ydlg-ft'}
+ ]}, true);
+ new Clipperz.PM.Components.PasswordEntropyDisplay(YAHOO.ext.Element.get('lockPassphrase'));
+
+ lockDialog = new YAHOO.ext.BasicDialog(
+ lockDialogElement, {
+ closable:false,
+ modal:true,
+ autoTabs:false,
+ resizable:false,
+ fixedcenter:true,
+ constraintoviewport:false,
+ width:350,
+ height:130,
+ shadow:true
+ }
+ );
+
+ unlockButton = lockDialog.addButton(Clipperz.PM.Strings['unlockButtonLabel'], MochiKit.Base.method(this, 'exitLock', lockDialog));
+//MochiKit.Logging.logDebug("--- Main.showAlertDialog - 5");
+ lockDialog.setDefaultButton(unlockButton);
+
+ MochiKit.Signal.connect('lockDialogForm', 'onsubmit', MochiKit.Base.method(this, 'exitLock', lockDialog));
+ lockDialog.on('show', function() {YAHOO.ext.Element.get('lockPassphrase').focus();});
+ lockDialog.show('main');
+// this.user().lock();
+ },
+
+ 'exitLock': function(aLockDialog, anEvent) {
+// var deferredResult;
+
+//MochiKit.Logging.logDebug(">>> Exiting lock");
+ if (typeof(anEvent.stop) != 'undefined') {
+ anEvent.stop();
+ }
+
+ if (this.user().passphrase() == YAHOO.ext.Element.get('lockPassphrase').dom.value) {
+ aLockDialog.hide(MochiKit.Base.method(aLockDialog, 'destroy', true));
+ Clipperz.NotificationCenter.notify(this, 'accountUnlocked', null, true);
+ } else {
+ YAHOO.ext.Element.get('lockPassphrase').dom.value = "";
+ YAHOO.ext.Element.get('lockPassphrase').focus();
+ }
+
+// deferredResult = new MochiKit.Async.Deferred();
+// deferredResult.addCallback(MochiKit.Base.method(this.user(), 'unlockWithPassphrase'));
+// deferredResult.addCallback(MochiKit.Base.method(aLockDialog, 'hide', MochiKit.Base.method(aLockDialog, 'destroy', true)));
+// deferredResult.addCallback(MochiKit.Base.method(Clipperz.NotificationCenter, 'notify', this, 'accountUnlocked', null, true));
+// deferredResult.addErrback(function() {
+// YAHOO.ext.Element.get('lockPassphrase').dom.value = "";
+// YAHOO.ext.Element.get('lockPassphrase').focus();
+// });
+// deferredResult.callback(YAHOO.ext.Element.get('lockPassphrase').dom.value);
+
+ return false;
+ },
+
+ //-----------------------------------------------------------------------------
+
+ 'updateProgressDialogStatus': function(anEvent) {
+//MochiKit.Logging.logDebug(">>> main.updateProgressDialogStatus - " + anEvent.parameters());
+//try {
+ if (Clipperz.Base.objectType(anEvent.parameters()) == 'string') {
+ Clipperz.PM.Components.MessageBox().update(Clipperz.PM.Strings.messagePanelConfigurations[anEvent.parameters()]());
+ } else {
+ Clipperz.PM.Components.MessageBox().update(anEvent.parameters());
+ }
+//} catch (exception) {
+//console.log("updateProgressDialogStatus - anEvent", anEvent);
+// MochiKit.Logging.logError("Main.updateProgressDialogStatus: " + exception);
+// throw exception;
+//}
+//MochiKit.Logging.logDebug("<<< main.updateProgressDialogStatus");
+ },
+
+ //-----------------------------------------------------------------------------
+
+ 'defaultErrorHandler': function(anErrorString, anException) {
+MochiKit.Logging.logDebug(">>> DEFAULT ERROR HANDLER: " + anErrorString + " (exception: " + Clipperz.Base.serializeJSON(anException) + ")");
+ },
+
+ //-----------------------------------------------------------------------------
+
+ 'isRunningCompact': function() {
+ return this._isRunningCompact;
+ },
+
+ 'setIsRunningCompact': function(aValue) {
+ this._isRunningCompact = aValue;
+ },
+
+ //-----------------------------------------------------------------------------
+
+ 'reportException': function(anError) {
+/*
+ var deferredResult;
+
+ deferredResult = new MochiKit.Async.Deferred();
+
+ Clipperz.PM.Components.MessageBox().show(
+ {
+ title:Clipperz.PM.Strings['fatalErrorMessageTitle'],
+ text:Clipperz.PM.Strings['fatalErrorMessageText'],
+ width:240,
+ showProgressBar:false,
+ showCloseButton:false,
+ fn:MochiKit.Base.method(deferredResult, 'callback'),
+ scope:this,
+ buttons:{
+ 'ok': Clipperz.PM.Strings['fatalErrorMessageCloseButtonLabel']
+ }
+ }
+ );
+
+ deferredResult.addCallback(function() {
+ window.document.body.innerHTML = "";
+ window.location.reload(true);
+ });
+*/
+ Clipperz.PM.exit('error.html');
+ },
+
+ //-----------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+
+});
+
+
+
+//#############################################################################
+
+MochiKit.Base.update(Clipperz.PM, {
+
+ __repr__: function() {
+ return "[" + this.NAME + " " + this.VERSION + "]";
+ },
+
+ toString: function() {
+ return this.__repr__();
+ },
+
+ //-----------------------------------------------------------------------------
+
+ 'initPage': function() {
+ var main;
+ var shouldShowRegistrationForm;
+ var useCompactDesign;
+
+//MochiKit.Logging.logWarning("Just testing logging system");
+ Clipperz.PM.Strings.Languages.initSetup();
+// DWRUtil.useLoadingMessage(Clipperz.PM.Strings['DWRUtilLoadingMessage']);
+
+ if (window.location.search.indexOf("registration") != -1) {
+ shouldShowRegistrationForm = true;
+ } else {
+ shouldShowRegistrationForm = false;
+ }
+
+ if (window.location.search.indexOf("compact") != -1) {
+ useCompactDesign = true;
+ } else {
+ useCompactDesign = false;
+ }
+
+ main = new Clipperz.PM.Main();
+
+ if (useCompactDesign == true) {
+ main.runCompact();
+ } else {
+ if (Clipperz_IEisBroken === true) {
+ if (Clipperz.PM.Proxy.defaultProxy.isReadOnly()) {
+ var logoParentNode;
+
+ YAHOO.ext.Element.get('donateHeaderIcon').remove();
+ logoParentNode = YAHOO.ext.Element.get('logo').dom.parentNode;
+ YAHOO.ext.Element.get('logo').remove();
+ Clipperz.YUI.DomHelper.append(logoParentNode, {tag:'span', children:[
+ {tag:'span', cls:'clipperzLogoSpan', html:'clipper'},
+ {tag:'span', cls:'clipperzLogoZSpan', html:'z'}
+ ]})
+ } else {
+ YAHOO.ext.Element.get('donateHeaderIcon').dom.src = "./images/smiles.gif";
+ YAHOO.ext.Element.get('logo').dom.src = "./images/logo.gif";
+ }
+ } else {
+ YAHOO.ext.Element.get('donateHeaderIcon').dom.src = "data:image/gif;charset=utf-8;base64,R0lGODlhEAAQAPf/ADMzZvrFL/KbGPrER3VXJeaJHvnGXNJ/KAEAAPnKefvJDamopMvLy8GZEfrTpvvgwGhVB0xKSO3BDUk+A/vYqnVgLcmndoRqM/exO3hrS3lmPYRsB39lDum9Dv3aCuebVPnIdP////3cCvewE07BafrQk/rHG1tYR5qZl7eUWZl7CfnGjdeuDPnCPpl4LDEoA5R2OP3XC/jBgfi2EvrXrvrRlWpYHgGtKdiqKPvfvu6nFzTNWfexFv7gCEc4GPrFDvaqFJmDB/euE/vYrJV5SfzUC7uTIuCxDf8AAPrHX519EbONGLubCvvYqzsxA/42AwaIGPzTC9u8CfTALlRUUomJiACWHaaMCsmeJFBFBZ5wUtaRVGlOVrySGLBvPNaBKsSGU9OOUbF7VPOycaRxUaFzWfGtaLZ6L+CaHcZ/Kt6YHVxJXfvXqaGhn0A8Z/i8c7JwM7d4MP6SBrJtM21MUDs4ZT84YmFhYaBnPqtyNM2QW6t2Va18XfvWsPvZsmVOXUQ7X86CJ1ZDWzo2Y6FoOfzSDBMPB/rTqW1OT0I5YEQ9ZnVTS1pEV9iCI7x+Ljw4ZvnJlqNnOfeyUfnMi/CkSfnKhAOmJ/WqU/ewJmVUO6qRB3ljHOGzFvauSfnFWveuI/esFK2JE5iVifrEEA+uJ/K+RayHMYVvTsyiE3NxbnBdQl5KG+cAAPnBIQYFA8GXN82hJbWXa6WDEQgGBFNBGMKeC4iFeZiiGdTZ1aqgd1dTPF9fX4R1BHReOOi9cdmsUn9xBKKFIWVPG5J0FLmzmcLCwtK5B6eQcnx5doZrFPnAH6eFP/fDL1RLBYVsQW5raMXGEFA5E+rLoUQEAG0kA8ONCteZId6wF86tCJ0AAGFQBurKn6mJHks/A2tZQOKfIHFua+29Wum1OOzv7LysCN3i3s/Rz/DDdeOyKCckHxQTEDsuEUIvEI1EBfP29KuIQbqUR9O7CbnCER8ZCSIeGDQJADQXAaCVaKeCGUNAPFRGMpmJS1xIF/rELPXARv///yH/C05FVFNDQVBFMi4wAwEAAAAh+QQFZAD/ACwAAAAAEAAQAAAI+AABCASwhkyYDx+27PkzcGCdMmZWOOjT5xCkMXwUDXwERgaNHA9CPsjhZ4UeNwK1vHEwpAmFlxSaDGEjQwwAQZQq1aihKlaJEhYylagx6RIXPJ1AJEjgSsNSIrOWJpDk5QAGT0mSIKiQFQaCrAYwfCnwqUWpAatMDRjwitYAfy0wFSgwQhksZgHy6mWGpRWPAgdGjEKlxIThw7IajBrRKBIQBQpUaGMiQUItbSogA5nDSMCPIlGudHPiZEKQKEV+CKADgJCQQh5iy44dZQQcgXbSzCjSo7fvGDMCJRo4KA8oBTFEiIihQEgcQA0FIjqjRocONI4WNQwIACH5BAVkAP8ALAEABAANAAkAAAhaAP8J1GehhMASBgUqREAExLkUEFMoFOgDXpJwFzLCUChuwL8BHj8O8OeRRxd0ASbiwBKgn8AjHK5N5AQB1bUjAmt128BCIIssL3gqlALBiUAnGyRMFChiqcKAACH5BAVkAP8ALAEABAANAAoAAAhzAP8JrKEqlkALmQQq/JfAlYYECYjMSrDwXxIEFZIkgYEgicIWAleZEviK1gCBI/7BqhggwD8cS/4tEVWBg5JQoZRwsGEr2D8JuUKYa1OlCopiIYgdEchEVIinUBdcWahJFwoGDNqcCFLxnxRezbIAM6YwIAAh+QQFZAD/ACwCAAMADAAMAAAIeQD//ZN2TOC/bQUN/st06pRAhg4NOuvlS+DEigZ/LbsgUCNHgwSEuRAYcuS/JUam4FCIg5kRfF3anNqUbNiwZJs0oOCmYN8/d+VwmcM17t89Cf+kaCCxo+kOEhmwGYwHxYpVK1DIKYR2o2tXS/IU3rpBqiwpS7cEBgQAIfkEBWQA/wAsAgADAAwADAAACH4A//0b0kTgPwoFDf6roSqWQAuZSihM4EqDQCKzEihMgqCCQBgIkhgsNWCVKYGvaA3w908Zln8BFMbE0moUKiUmcuqU1WDUPwUqtDHp0KEatXYKFPwrUkRTN3v1pmV7UsSgBw8x5CBhxeqJwiI9wsp58kSOQlAKYlyNoWCEwIAAIfkEBWQA/wAsAQAEAA4ACwAACIwACURIhQxcBG8a8j1DlooKAXpUdt3ZFUGdoQgS71BJFw2Bx38IYLxDANIju2/C5hla5+LfP1M+DM3jZ+1fF1gBXOr8FwDHEpdLRFXgoCRUKCUcbNgK5lJCrhDm2lSpgqJYCGJHdDIRFaKr1wVXdv7TpAsFAwZtTgQR61IKr2ZZgBmLwVanCBEuhegMCAA7Cg==";
+ YAHOO.ext.Element.get('logo').dom.src = "data:image/gif;charset=utf-8;base64,R0lGODlhgwAoAPf/AP////+SAIKCmV1df3l5jYmhef//9vr6+YSQrJSguNfk60xMZjw8bf+PAI2Zsq6ulTU1ZZqasrzE05Gdtf//90pHW6d4KuPj6cLCz6ampzw3Ymt9nXp6Z21tif+MAHV1mPaOBJGRrPLy8dPT21Zhifb2+H19j/z8+MmOG3V/n729zcnJ1jU1aLmKIsnb5M3O2Xe5y3JyjHZqRD1xlElJd7KyuPSSBGFhhPn59kFBcKiovIaGov+KAP7+/sDA0HZ2mKqtwV5fh6y1yMTM2X19nXuCoTg5al1MUdTV4O3u8jU8bTMzZv+OAIt6Nfz8/G5ukldTVF5egv///nFxlJ2eeFFRfPX18cN/HpOTanV1lLOzp3l5m1dXesXF1O7u7MOPHj4+YaWltdXV1WJqj4ODdU1NeZWVZNaSFff39WFmjEtQfP+GAPSGBenq77q6ym1thP//+3l5kX5+kIOiubx8IpyCMf3//8nJ0eHh20JMedHRwVJSeba2yEJyPsaDHVhYffT+/llag4uNqcTE0T4+bvDw7dra4v7///n//6GhuGZojTw8a/r6+/z89OLy9ZWVr8mMG9ra1t/f5zo6ZUNEcjs7bPHx9dzc34iVsE5Od319mZ2dbUZJd2hoh4xsOf398mBhiP39/ZmZkmtrkKOmvK7B0T9Bb77H1evr2c2PGX2Ipn1YQT9RbOrq56bR3Y2NgLrV35mZZ+yOCqmptZiYmN/fx7OzxTY+YFJXgVFchdnZvsLE08jI0ztcTeCLEPuVAv2QAIqSrZietlJUbGpqYYWFWWdlSKKlepajukJvQMbI1kZhiURukj09ZlNUf5mwxOHhxFxchVtehoaOqoqKZv39+HF5mnR6m5OZsj8/bDQ0ZzQzZuzs6vr67MDAyUhIdGpqj+np0IqZstfY4o+btI6dtv2NAPf353ibtGJcTtWJEDJIdrPD0u/9/ufo7ZWiuZWjulVVdeLi6Nvb5N3d4oiIcIyMecLC0XWAoGVlfpCQmGCctXR3mXh4W2lukv///yH5BAEAAP8ALAAAAACDACgAAAj/AP8JHEiwoMGDCBMqXMiwocOHECNKnEixosWLGDNq3Mixo8ePIEOKHEmypMmTKFOqXMmyZcktLwZ1wRBF4I+YM2+43IlRWI8eAKrFEIgNANBqcXgqpfgOgFMDBAROcAqAgpylWCEmoApVIDyqVrOKZbj1adR/RbqoHdRprFuEZQF0fes2yIcfH55QOhh37sMcU378eMLAIaEngp8QYhjt7gdFRh5W+fCBVUcWIVaUoCplnopoBfueLbKiNK8OAkmXngVhzjjOSIQtKnit9Ioa/9Ah4TwuUbaDLAQp20z1RYTIBP3Z9sbClBB3Tgs0gYSiuvXrKCCla6jmBdXvTp1Q/yEoWiAysCakOpXS5hQi8E51LSCIab0lCe/h15pPMI8r+OuNkAlBRVAlAi4ufEcFJGt44OCDEHqwhgwM0aBAD4cASNUrA5X3z1ROUZDePw5oCN8IhQmEwHeHZAigITkMtM4FJgIgRSR7CZQCVSW0YYeLACzYIIRMBGCkkR5QuBAQ35XABxHiwPJdEvEI5CGIVY1Y4nehuLHDIyOAJ8BAK4Knwg4heMfZDgMJ8Z0kiXyQCHRO9RDGQDtqeMgxTXzhp58tnNHAkQFMuBAngFDVyJgCKXHKd8VYydVZWIoo0JZOhaLJQEbA8F0kZH7XA5sCsQADUE7hIdAyB6CqxzdLxP+qhgJUWZFinpxh8MEoHwxzUAvmHOlBKhUoxEk5VMHxQEEzcPaIpGapF6KWVPWwLEFKtFGrTv+UaaMWBWlDo1M4tLXPeiIsEOu6G9hRZz06fgfHnQktYUGwSJ4BxkK5lEJVKFVi+8QUU3xQBbRyUYrepf9yYBApLkpBhorVOlyQMJzZo80QVBWywxZEhLwFOe5+Gy9VYsyWkCfAAGNkA74Uu1AaElDVzb5kTSptlgw7xc0eBinCmRkUO2XFHwYF8V0sRjhSo6hunOzUMQrJMOiRNhzRECg+UIUKzgtduTCJVF2QI0FCU0V0t1S1QYNBoHy3CQu0Pk2VClJLIUpCxoD/cHUAHqziEM1UnQO2QmJP2zMAPxuUxndreysCFwZJI3fTVJ3Aiwo+dO655/pIfQBqB/Viw98NePIQCexkzt9AlAChwuykJs4z2eQOVZC3AFBTNAAnJFWQKt9hoQ0SLuJRSUO4jn7QEWwQ6kEdEKnxDJARFDRGok7t/Y/tluLu1CwF0U0VI7rzjhtBLCQYXlJzKFpTQSCHPH/zpBNUgTrSUw+REYFAFQBEQIyBMIBjVOkHwuZSKWpRBQdZIMgjnEAVaEzidwA4wKYGIghGUCUcF2wWVXiRon9oAwE/AgAczoK/gtzCDx44UgMsAIGCbKMh/qLKJ0LwASIYgjOXSBH4/xz4Lx1QRgXgoUWo5AUEyvCBSxkYCAKdIo8dUGYXJQOAHvBEFecRpA88IFQA/ECHK5jxjHSQWULyIImnweENHdLZh8aGqaeJoYS8q9ElYiQQErTjaZ/IBxed4sWBgFGMf5PhL6DAEGeMI4vgScIWCNKUaH0PLFcRHxruoCF6IG2JAMDBHQT4HXnMbyDMkIeJLDGxgeBjPaHIn0AOKcZaBsAGjGQIJQThjlaFpwQ6+ORAglGCYlqBdNMoZgmsoDtMteIbH7iABwHgBGC+jSDeKkQZniCJaYaiBEAow0Fo8Igk+JKaViBFIApiDWWKoC0ESQYbQEDPetqznrLIZUOMQIEDcExhC9EoIfsYQFAGsKBUBTXo4gpBOSM4IzBBWIxBJDeAfxihCoEBBR8TUokyjKJggWgGcBJ6UIJAQAMoTalKV1pDlmDKC5RrCEXpwpOXxpQhM6WpS2zqkJzqlCVYOppD6kOuU/5UJfwYxOxs8Q2HTOEes+ODOI9K1apa9aoLCQgAOwo=";
+ }
+
+ main.run(shouldShowRegistrationForm);
+ }
+
+ Clipperz.PM.defaultErrorHandler = main.defaultErrorHandler;
+
+ // DEBUG
+ if ((typeof(_clipperz_pm_test_user) != 'undefined') && (typeof(_clipperz_pm_test_passphrase) != 'undefined')) {
+//------- automatic login with test/test --------------
+// Clipperz.PM.Proxy.defaultProxy = new Clipperz.PM.Proxy.Offline();
+//MochiKit.Logging.logWarning("activating AUTOLOGIN (" + _clipperz_pm_test_user + "/" + _clipperz_pm_test_passphrase + ")");
+// MochiKit.Async.callLater(0.9, MochiKit.Base.bind(main.doLogin, main), _clipperz_pm_test_user, _clipperz_pm_test_passphrase, YAHOO.ext.Element.get('Clipperz_PM_Components_Panels_login_submit_9'));
+ MochiKit.Async.callLater(0.5, MochiKit.Base.bind(main.loginPanel().doLoginWithUsernameAndPassphrase, main.loginPanel()), _clipperz_pm_test_user, _clipperz_pm_test_passphrase);
+//------- automatic registration --------------
+//MochiKit.Logging.logWarning("Testing registration (user,passwd)");
+//MochiKit.Logging.logDebug("mainPanel: " + main.mainPage().mainPanel().content());
+// main.mainPage().getActivePanel().showRegistrationFormAnimator().play();
+// MochiKit.Async.callLater(1.9, MochiKit.Base.bind(main.doRegistration, main), 'user', 'passwd');
+//-------------------------------------
+// main.showMainPanels('ok');
+ };
+
+ if (/fastEntropyAccumulationForTestingPurpose/.test(window.location.search)) {
+ Clipperz.Crypto.PRNG.defaultRandomGenerator().fastEntropyAccumulationForTestingPurpose();
+ }
+
+// Clipperz.PM.Proxy.defaultProxy.knock();
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'showDonationSplashScreen': function(aUser, aFocusElementId) {
+ var deferredResult;
+ var donateElement;
+ var donateDialog;
+ var closeButton;
+ var closeFunction;
+ var donateButton;
+ var donateFunction;
+
+ deferredResult = new MochiKit.Async.Deferred();
+
+//MochiKit.Logging.logDebug(">>> Main.showRegistrationSplashScreen");
+ donateElement = Clipperz.YUI.DomHelper.append(document.body, {tag:'div', id:'donateSplash', children:[
+ {tag:'div', cls:'ydlg-hd', htmlString:Clipperz.PM.Strings['donateSplashPanelTitle']},
+ {tag:'div', cls:'ydlg-bd', children:[
+ {tag:'div', cls:'alert-message', id:'donateMessage', children:[
+ {tag:'div', cls:'donateSplashPanelIcon', children:[
+ {tag:'img', src:Clipperz.PM.Strings['donateSplashPanelIconUrl']}
+ ]},
+ {tag:'div', cls:'donateSplashPanelDescription', htmlString:Clipperz.PM.Strings['donateSplashPanelDescription']}
+ ]}
+ ]},
+ {tag:'div', cls:'ydlg-ft'}
+ ]}, true);
+
+ donateDialog = new YAHOO.ext.BasicDialog(
+ donateElement, {
+ closable:false,
+ modal:true,
+ autoTabs:false,
+ resizable:false,
+ fixedcenter:true,
+ constraintoviewport:false,
+ width:450,
+ height:220,
+ shadow:true,
+ minWidth:300,
+ minHeight:300
+ }
+ );
+
+ closeFunction = MochiKit.Base.partial(deferredResult.callback, false);
+ donateFunction = MochiKit.Base.partial(deferredResult.callback, true);
+ donateButton = donateDialog.addButton(Clipperz.PM.Strings['donateDonateButtonLabel'], donateFunction, deferredResult);
+
+ donateDialog.addKeyListener(27, closeFunction, deferredResult);
+ closeButton = donateDialog.addButton(Clipperz.PM.Strings['donateCloseButtonLabel'], closeFunction, deferredResult);
+
+ donateDialog.setDefaultButton(donateButton);
+ donateDialog.show(aFocusElementId /*'recordListAddRecordButton'*/);
+
+ deferredResult.addCallback(MochiKit.Base.bind(function(shouldOpenDonatePage) {
+ var result;
+
+ if (shouldOpenDonatePage) {
+ window.open(Clipperz.PM.Strings['donateHeaderLinkUrl'], "donate");
+ aUser.preferences().setShouldShowDonationPanel(false);
+ aUser.preferences().saveChanges();
+ }
+ }, this));
+ deferredResult.addBoth(MochiKit.Base.method(donateDialog, 'hide'));
+ deferredResult.addBoth(MochiKit.Base.method(donateElement, 'remove'));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Main.showDonationSplashScreen - 2: " + res); return res;});
+//MochiKit.Logging.logDebug("<<< Main.showRegistrationSplashScreen");
+
+ return deferredResult;
+ },
+
+ //-----------------------------------------------------------------------------
+
+ 'exit': function(aPageName) {
+// alert("ERROR: " + aPageName);
+
+// YAHOO.ext.Element.get('menus').update("");
+// YAHOO.ext.Element.get('logoutLI').update("");
+// YAHOO.ext.Element.get('lockLI').update("");
+// YAHOO.ext.Element.get('main').update("");
+// Clipperz.YUI.DomHelper.append('main', {tag:'div', id:'exitBlock', children:Clipperz.PM.Strings['exitConfig']});
+
+ MochiKit.Async.wait(0).addCallback(function() {
+// window.location.href = "http://www.google.com/search?hl=" + Clipperz.PM.Strings.preferredLanguage + "&q=phishing&btnI=Google+Search";
+ window.location.href = "./" + aPageName;
+ });
+ },
+
+ //-----------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+
+});
+
+//#############################################################################
+
+//Clipperz.PM.SerializeAsyncCalls = function(aDelay, aFunction) {
+// aFunction.apply(extend(null, arguments, 1));
+//};
+
+MochiKit.DOM.addLoadEvent(Clipperz.PM.initPage);
diff --git a/frontend/beta/js/Clipperz/PM/Proxy.js b/frontend/beta/js/Clipperz/PM/Proxy.js
new file mode 100644
index 0000000..d05a5e0
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Proxy.js
@@ -0,0 +1,173 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. 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;
+
+//console.log(">>> Proxy.payToll", aRequestType, someParameters);
+ if (this.shouldPayTolls()) {
+ deferredResult = new MochiKit.Async.Deferred();
+
+ if (this.tolls()[aRequestType].length == 0) {
+ deferredResult.addCallback(MochiKit.Base.method(this, 'sendMessage', 'knock', {requestType:aRequestType}));
+ deferredResult.addCallback(MochiKit.Base.method(this, 'setTollCallback'));
+ }
+ deferredResult.addCallback(MochiKit.Base.method(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});
+ }
+//console.log("<<< Proxy.payToll");
+
+ return deferredResult;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'addToll': function(aToll) {
+//console.log(">>> Proxy.addToll", aToll);
+ this.tolls()[aToll.requestType()].push(aToll);
+//console.log("<<< Proxy.addToll");
+ },
+
+ //=========================================================================
+
+ 'setTollCallback': function(someParameters) {
+//console.log(">>> Proxy.setTollCallback", someParameters);
+ if (typeof(someParameters['toll']) != 'undefined') {
+//console.log("added a new toll", someParameters['toll']);
+ this.addToll(new Clipperz.PM.Toll(someParameters['toll']));
+ }
+//console.log("<<< Proxy.setTallCallback", someParameters['result']);
+ //return someParameters['result'];
+ return someParameters;
+ },
+
+ //=========================================================================
+
+ '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 MochiKit.Async.Deferred();
+ deferredResult.addCallback(MochiKit.Base.method(this, 'payToll', aRequestType));
+ deferredResult.addCallback(MochiKit.Base.method(this, 'sendMessage', aFunctionName));
+ deferredResult.addCallback(MochiKit.Base.method(this, 'setTollCallback'));
+ deferredResult.callback(someParameters);
+
+ return deferredResult;
+ },
+
+ //=========================================================================
+
+ 'sendMessage': function () {
+ throw Clipperz.Base.exception.AbstractMethod;
+ },
+
+ //=========================================================================
+
+ 'isReadOnly': function () {
+ return false;
+ },
+
+ //=========================================================================
+ __syntaxFix__: "syntax fix"
+
+});
diff --git a/frontend/beta/js/Clipperz/PM/Proxy/Proxy.JSON.js b/frontend/beta/js/Clipperz/PM/Proxy/Proxy.JSON.js
new file mode 100755
index 0000000..889e1f1
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Proxy/Proxy.JSON.js
@@ -0,0 +1,100 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. 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;
+}
+
+YAHOO.extendX(Clipperz.PM.Proxy.JSON, Clipperz.PM.Proxy, {
+
+ 'toString': function() {
+ return "Clipperz.PM.Proxy.JSON";
+ },
+
+ //=========================================================================
+
+ 'url': function () {
+ return this._url;
+ },
+
+ //=========================================================================
+
+ 'sendMessage': function(aFunctionName, someParameters) {
+ var deferredResult;
+ var parameters;
+
+ parameters = {
+ method: aFunctionName,
+// version: someParameters['version'],
+// message: someParameters['message'],
+ parameters: Clipperz.Base.serializeJSON(someParameters)
+ };
+
+ deferredResult = new MochiKit.Async.Deferred();
+ deferredResult.addCallback(function (aValue) {
+ MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'remoteRequestSent');
+ return aValue;
+ });
+ deferredResult.addCallback(MochiKit.Async.doXHR, this.url(), {
+ method:'POST',
+ sendContent:MochiKit.Base.queryString(parameters),
+ headers:{"Content-Type":"application/x-www-form-urlencoded"}
+ });
+ deferredResult.addCallback(function (aValue) {
+ MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'remoteRequestReceived');
+ return aValue;
+ });
+// deferredResult.addCallback(MochiKit.Async.evalJSONRequest);
+ deferredResult.addCallback(MochiKit.Base.itemgetter('responseText'));
+ deferredResult.addCallback(Clipperz.Base.evalJSON);
+ deferredResult.addCallback(function (someValues) {
+ if (someValues['result'] == 'EXCEPTION') {
+ throw someValues['message'];
+ }
+
+ return someValues;
+ })
+// return MochiKit.Base.evalJSON(req.responseText);
+ deferredResult.callback();
+
+ return deferredResult;
+ },
+
+ //=========================================================================
+ __syntaxFix__: "syntax fix"
+
+});
diff --git a/frontend/beta/js/Clipperz/PM/Proxy/Proxy.Offline.DataStore.js b/frontend/beta/js/Clipperz/PM/Proxy/Proxy.Offline.DataStore.js
new file mode 100644
index 0000000..4d3ba08
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Proxy/Proxy.Offline.DataStore.js
@@ -0,0 +1,804 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. 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._connections = {};
+
+ this._b = null;
+ this._B = null;
+ this._A = null;
+ this._userData = null;
+
+ return this;
+}
+
+//Clipperz.Base.extend(Clipperz.PM.Proxy.Offline.DataStore, Object, {
+Clipperz.PM.Proxy.Offline.DataStore.prototype = MochiKit.Base.update(null, {
+
+ //-------------------------------------------------------------------------
+
+ 'isReadOnly': function () {
+ return this._isReadOnly;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'shouldPayTolls': function() {
+ return this._shouldPayTolls;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'data': function () {
+ return this._data;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'tolls': function () {
+ return this._tolls;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'connections': function () {
+ return this._connections;
+ },
+
+ //=========================================================================
+
+ '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 MochiKit.Async.Deferred();
+ c = someData['users'].length;
+
+ for (i=0; i<c; i++) {
+ var newConnection;
+ var recordConfiguration;
+
+ deferredResult.addCallback(MochiKit.Base.method(this, 'userSerializedEncryptedData', someData['users'][i]));
+ deferredResult.addCallback(MochiKit.Base.bind(function(aUserSerializationContext) {
+//console.log("SERIALIZED USER", 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() {
+//console.log("this._data", resultData);
+ this._data = resultData;
+ }, this));
+
+ deferredResult.callback();
+//Clipperz.log("<<< Proxy.Test.setupWithData");
+
+ return deferredResult;
+ },
+
+ //=========================================================================
+
+ 'b': function() {
+ return this._b;
+ },
+
+ 'set_b': function(aValue) {
+ this._b = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'B': function() {
+ return this._B;
+ },
+
+ 'set_B': function(aValue) {
+ this._B = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'A': function() {
+ return this._A;
+ },
+
+ 'set_A': function(aValue) {
+ this._A = aValue;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'userData': function() {
+ return this._userData;
+ },
+
+ 'setUserData': function(aValue) {
+ this._userData = aValue;
+ },
+
+ //=========================================================================
+
+ '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";
+ }
+ }
+ },
+
+ //=========================================================================
+
+ 'processMessage': function(aFunctionName, someParameters) {
+ var result;
+
+ switch(aFunctionName) {
+ case 'knock':
+ result = this._knock(someParameters);
+ break;
+ case 'registration':
+ this.checkToll(aFunctionName, someParameters);
+ result = this._registration(someParameters.parameters);
+ break;
+ case 'handshake':
+ this.checkToll(aFunctionName, someParameters);
+ result = this._handshake(someParameters.parameters);
+ break;
+ case 'message':
+ this.checkToll(aFunctionName, someParameters);
+ result = this._message(someParameters.parameters);
+ break;
+ case 'logout':
+ result = this._logout(someParameters.parameters);
+ break;
+ }
+
+ return result;
+ },
+
+ //=========================================================================
+
+ '_knock': function(someParameters) {
+ var result;
+
+ result = {
+ toll: this.getTollForRequestType(someParameters['requestType'])
+// toll: {
+// requestType: someParameters['requestType'],
+// targetValue: "3a1ba0be23580f902885c6c8a6b035e228ed1ca74d77de5f9bb0e0c899f07cfe",
+// cost:
+// }
+ }
+
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+
+ '_registration': function(someParameters) {
+//console.log("_registration", 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': someParameters['user']['lock'],
+ 'lock': Clipperz.Crypto.Base.generateRandomSeed(),
+ // 'maxNumberOfRecords': '100',
+ '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 MochiKit.Async.succeed(result);
+ },
+
+ //-------------------------------------------------------------------------
+
+ '_handshake': function(someParameters) {
+ var result;
+ var nextTollRequestType;
+
+//Clipperz.log(">>> Proxy.Offline.DataStore._handshake");
+ result = {};
+ if (someParameters.message == "connect") {
+ var userData;
+ var randomBytes;
+ var b, B, v;
+
+//console.log(">>> Proxy.Offline.DataStore._handshake.connect", someParameters);
+ userData = this.data()['users'][someParameters.parameters.C];
+
+ if ((typeof(userData) != 'undefined') && (userData['version'] == someParameters.version)) {
+ this.setUserData(userData);
+ } else {
+ this.setUserData(this.data()['users']['catchAllUser']);
+ }
+
+ randomBytes = Clipperz.Crypto.Base.generateRandomSeed();
+ this.set_b(new Clipperz.Crypto.BigInt(randomBytes, 16));
+ v = new Clipperz.Crypto.BigInt(this.userData()['v'], 16);
+ this.set_B(v.add(Clipperz.Crypto.SRP.g().powerModule(this.b(), Clipperz.Crypto.SRP.n())));
+
+ this.set_A(someParameters.parameters.A);
+
+ result['s'] = this.userData()['s'];
+ result['B'] = this.B().asString(16);
+
+ nextTollRequestType = 'CONNECT';
+ } else if (someParameters.message == "credentialCheck") {
+ var v, u, S, A, K, M1;
+
+//console.log(">>> Proxy.Offline.DataStore._handshake.credentialCheck", someParameters);
+ v = new Clipperz.Crypto.BigInt(this.userData()['v'], 16);
+ u = new Clipperz.Crypto.BigInt(Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(this.B().asString(10))).toHexString(), 16);
+ A = new Clipperz.Crypto.BigInt(this.A(), 16);
+ S = (A.multiply(v.powerModule(u, Clipperz.Crypto.SRP.n()))).powerModule(this.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) + this.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;
+
+//console.log("HANDSHAKE WITH OTP", someParameters.parameters.oneTimePasswordKey);
+//console.log("someParameters", someParameters);
+//console.log("data.OTP", Clipperz.Base.serializeJSON(this.data()['onetimePasswords']));
+ 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 {
+ MochiKit.Logging.logError("Clipperz.PM.Proxy.Test.handshake - unhandled message: " + someParameters.message);
+ }
+//console.log("<<< Proxy.Offline._handshake", result);
+
+ result = {
+ result: result,
+ toll: this.getTollForRequestType(nextTollRequestType)
+ }
+
+ return MochiKit.Async.succeed(result);
+ },
+
+ //-------------------------------------------------------------------------
+
+ '_message': function(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;
+
+//try {
+ recordsStats = {};
+ for (recordReference in this.userData()['records']) {
+ recordsStats[recordReference] = {
+ 'updateDate': this.userData()['records'][recordReference]['updateDate']
+ }
+ }
+
+ result['header'] = this.userDetails();
+ result['statistics'] = this.statistics();
+ result['maxNumberOfRecords'] = this.userData()['maxNumberOfRecords'];
+ result['version'] = this.userData()['userDetailsVersion'];
+ result['recordsStats'] = recordsStats;
+
+ if (this.isReadOnly() == false) {
+ var lock;
+
+ if (typeof(this.userData()['lock']) == 'undefined') {
+ this.userData()['lock'] = "<<LOCK>>";
+ }
+
+ result['lock'] = this.userData()['lock'];
+ }
+//} catch (exception) {
+// console.log("*#*#*#*#*#*#*", exception);
+// throw exception;
+//}
+ //=====================================================================
+ } else if (someParameters.message == 'getRecordDetail') {
+ 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'];
+ }
+
+ //=====================================================================
+ //
+ // 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;
+ parameters = someParameters.parameters;
+
+ if (parameters['C'] == null) {
+ result = Clipperz.PM.DataModel.User.exception.CredentialUpgradeFailed;
+ } else if (parameters['s'] == null) {
+ result = Clipperz.PM.DataModel.User.exception.CredentialUpgradeFailed;
+ } else if (parameters['v'] == null) {
+ result = Clipperz.PM.DataModel.User.exception.CredentialUpgradeFailed;
+ } else if (parameters['version'] != Clipperz.PM.Connection.communicationProtocol.currentVersion) {
+ result = Clipperz.PM.DataModel.User.exception.CredentialUpgradeFailed;
+ } else {
+ 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;
+
+//console.log("###===============================================================");
+//console.log("###>>>", Clipperz.Base.serializeJSON(someParameters));
+//console.log("###--- userData", Clipperz.Base.serializeJSON(this.userData()));
+ 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';
+//console.log("###<<< userData", Clipperz.Base.serializeJSON(this.userData()));
+ } else {
+ throw Clipperz.PM.Proxy.Offline.DataStore.exception.ReadOnly;
+ }
+*/ //=====================================================================
+ } else if (someParameters.message == 'saveChanges') {
+ if (this.isReadOnly() == false) {
+ var i, c;
+
+//console.log("###===============================================================");
+//console.log("###>>>", someParameters);
+//console.log("###>>>", Clipperz.Base.serializeJSON(someParameters));
+//console.log("###--- userData", Clipperz.Base.serializeJSON(this.userData()));
+//console.log("###===============================================================");
+//console.log("--- userData.lock ", this.userData()['lock']);
+//console.log("--- parameters.lock", someParameters['parameters']['user']['lock']);
+ 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']['updated'].length;
+ for (i=0; i<c; i++) {
+ var currentRecord;
+ var currentRecordData;
+
+ currentRecordData = someParameters['parameters']['records']['updated'][i];
+ currentRecord = this.userData()['records'][currentRecordData['record']['reference']];
+
+ if (
+ (typeof(this.userData()['records'][currentRecordData['record']['reference']]) == 'undefined')
+ &&
+ (typeof(currentRecordData['currentRecordVersion']) == 'undefined')
+ ) {
+//console.log("######## SHIT HAPPENS");
+ 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());
+
+ this.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];
+//console.log("DELETING records", currentRecordReference);
+ delete this.userData()['records'][currentRecordReference];
+ }
+
+ this.userData()['lock'] = Clipperz.PM.Crypto.randomKey();
+ result['lock'] = this.userData()['lock'];
+ result['result'] = 'done';
+//console.log("###<<< userData", Clipperz.Base.serializeJSON(this.userData()));
+ } 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 {
+ MochiKit.Logging.logError("Clipperz.PM.Proxy.Test.message - unhandled message: " + someParameters.message);
+ }
+
+ result = {
+ result: result,
+ toll: this.getTollForRequestType('MESSAGE')
+ }
+
+ return MochiKit.Async.succeed(result);
+ },
+
+ //-------------------------------------------------------------------------
+
+ '_logout': function(someParameters) {
+ return MochiKit.Async.succeed({result: 'done'});
+ },
+
+ //=========================================================================
+ //#########################################################################
+
+ 'isTestData': function() {
+ return (typeof(this.userData()['__masterkey_test_value__']) != 'undefined');
+ },
+
+ 'userDetails': function() {
+ var result;
+
+ if (this.isTestData()) {
+ var serializedHeader;
+ var version;
+
+//MochiKit.Logging.logDebug("### test data");
+ version = this.userData()['userDetailsVersion'];
+ serializedHeader = Clipperz.Base.serializeJSON(this.userData()['userDetails']);
+ result = Clipperz.PM.Crypto.encryptingFunctions.versions[version].encrypt(this.userData()['__masterkey_test_value__'], serializedHeader);
+ } else {
+//MochiKit.Logging.logDebug("### NOT test data");
+ result = this.userData()['userDetails'];
+ }
+
+ return result;
+ },
+
+ 'statistics': function() {
+ var result;
+
+ if (this.userData()['statistics'] != null) {
+ if (this.isTestData()) {
+ var serializedStatistics;
+ var version;
+
+ version = this.userData()['userDetailsVersion'];
+ serializedStatistics = Clipperz.Base.serializeJSON(this.userData()['statistics']);
+ result = Clipperz.PM.Crypto.encryptingFunctions.versions[version].encrypt(this.userData()['__masterkey_test_value__'], serializedStatistics);
+ } else {
+ result = this.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) {
+//console.log("#-#-#-#-#", aDeferredContext);
+// return aDeferredContext['user'].serializedDataUsingVersion(MochiKit.Base.values(aDeferredContext['user'].records()), aDeferredContext['data']['version']);
+// }, deferredContext);
+// deferredResult.addCallback(function(aUserSerializedData) {
+//console.log("USER SERIALIZED DATA", 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")
+}; \ No newline at end of file
diff --git a/frontend/beta/js/Clipperz/PM/Proxy/Proxy.Offline.js b/frontend/beta/js/Clipperz/PM/Proxy/Proxy.Offline.js
new file mode 100644
index 0000000..072f9bf
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Proxy/Proxy.Offline.js
@@ -0,0 +1,73 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. 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;
+}
+
+YAHOO.extendX(Clipperz.PM.Proxy.Offline, Clipperz.PM.Proxy, {
+
+ 'toString': function () {
+ return "Clipperz.PM.Proxy.Offline";
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'dataStore': function () {
+ return this._dataStore;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'sendMessage': function(aFunctionName, someParameters) {
+ return this.dataStore().processMessage(aFunctionName, someParameters);
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'isReadOnly': function () {
+ return true;
+ },
+
+ //-------------------------------------------------------------------------
+
+ __syntaxFix__: "syntax fix"
+
+});
+
diff --git a/frontend/beta/js/Clipperz/PM/Proxy/Proxy.PHP.js b/frontend/beta/js/Clipperz/PM/Proxy/Proxy.PHP.js
new file mode 100755
index 0000000..e7c2bc1
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Proxy/Proxy.PHP.js
@@ -0,0 +1,259 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
+if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
+
+//=============================================================================
+
+Clipperz.PM.Proxy.PHP = function(args) {
+ Clipperz.PM.Proxy.PHP.superclass.constructor.call(this, args);
+/*
+ this._tolls = {
+ 'CONNECT': [],
+ 'REGISTER': [],
+ 'MESSAGE': []
+ };
+*/
+ return this;
+}
+
+YAHOO.extendX(Clipperz.PM.Proxy.PHP, Clipperz.PM.Proxy, {
+
+ 'toString': function() {
+ return "Clipperz.PM.Proxy.PHP - " + this.args();
+ },
+
+ //=========================================================================
+/*
+ 'tolls': function() {
+ return this._tolls;
+ },
+*/
+ //-------------------------------------------------------------------------
+/*
+ 'payToll': function(aRequestType, someParameters) {
+ var deferredResult;
+
+//MochiKit.Logging.logDebug(">>> Proxy.DWR.payToll: " + aRequestType);
+ if (this.tolls()[aRequestType].length > 0) {
+ deferredResult = MochiKit.Async.succeed(this.tolls()[aRequestType].pop());
+ } else {
+//MochiKit.Logging.logDebug("### " + aRequestType + " toll NOT immediately available; request queued.");
+ deferredResult = new MochiKit.Async.Deferred();
+ deferredResult.addCallback(function(someParameters) {
+ return new Clipperz.PM.Toll(someParameters['toll']);
+ })
+ com_clipperz_pm_Proxy.knock(Clipperz.Base.serializeJSON({requestType:aRequestType}), {
+ callback:MochiKit.Base.method(deferredResult, 'callback'),
+ errorHandler:MochiKit.Base.method(deferredResult, 'errback')
+ });
+ }
+
+ deferredResult.addCallback(function(aToll) {
+ return aToll.deferredPay();
+ });
+ deferredResult.addCallback(function(someParameters, aToll) {
+ var result;
+
+ result = {
+ parameters: someParameters,
+ toll: aToll
+ }
+
+ return result;
+ }, someParameters);
+
+ return deferredResult;
+ },
+*/
+ //-------------------------------------------------------------------------
+/*
+ 'addToll': function(aToll) {
+ this.tolls()[aToll.requestType()].push(aToll);
+ },
+*/
+ //=========================================================================
+/*
+ 'setTollCallback': function(someParameters) {
+//MochiKit.Logging.logDebug(">>> Proxy.DWR.setTollCallback");
+//MochiKit.Logging.logDebug("--- Proxy.DWR.setTollCallback - " + Clipperz.Base.serializeJSON(someParameters));
+ if (typeof(someParameters['toll']) != 'undefined') {
+ this.addToll(new Clipperz.PM.Toll(someParameters['toll']));
+ }
+ return someParameters['result'];
+ },
+*/
+ //=========================================================================
+
+ 'registration': function(someParameters) {
+ return this.sendMessage('registration', someParameters, 'REGISTER');
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'handshake': function(someParameters) {
+/*
+ _s = "e8a2162f29aeaabb729f5625e9740edbf0cd80ac77c6b19ab951ed6c88443b8c";
+ _v = new Clipperz.Crypto.BigInt("955e2db0f7844aca372f5799e5f7e51b5866718493096908bd66abcf1d068108", 16);
+ _b = new Clipperz.Crypto.BigInt("5761e6c84d22ea3c5649de01702d60f674ccfe79238540eb34c61cd020230c53", 16);
+
+ _B = _v.add(Clipperz.Crypto.SRP.g().powerModule(_b, Clipperz.Crypto.SRP.n()));
+ _u = new Clipperz.Crypto.BigInt(Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(_B.asString(10))).toHexString(), 16);
+ _A = new Clipperz.Crypto.BigInt("3b3567ec33d73673552e960872eb154d091a2488915941038aef759236a27e64", 16);
+ _S = (_A.multiply(_v.powerModule(_u, Clipperz.Crypto.SRP.n()))).powerModule(_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) + _B.asString(10) + _K)).toHexString().slice(2);
+ _M2 = Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(_A.asString(10) + _M1 + _K)).toHexString().slice(2);
+
+// MochiKit.Logging.logDebug("b = " + _b.asString(16));
+// MochiKit.Logging.logDebug("v = " + _v.asString(16));
+ MochiKit.Logging.logDebug("B = " + _B.asString(16));
+ MochiKit.Logging.logDebug("u = " + _u.asString(16));
+ MochiKit.Logging.logDebug("S = " + _S.asString(16));
+ MochiKit.Logging.logDebug("K = " + _K);
+ MochiKit.Logging.logDebug("M1 = " + _M1);
+ MochiKit.Logging.logDebug("M2 = " + _M2);
+// MochiKit.Logging.logDebug("someParameters.version: " + someParameters.version);
+*/
+ return this.sendMessage('handshake', someParameters, 'CONNECT');
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'message': function(someParameters) {
+ return this.sendMessage('message', someParameters, 'MESSAGE');
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'logout': function(someParameters) {
+//MochiKit.Logging.logDebug("=== Proxy.DWR.logout");
+ return this.sendMessage('logout', someParameters, 'MESSAGE');
+ },
+
+ //=========================================================================
+
+ 'sendMessage': function(aFunctionName, someParameters, aRequestType) {
+/*
+ var deferredResult;
+ var proxy;
+
+//MochiKit.Logging.logDebug(">>> Proxy.DWR.sendMessage - " + aFunctionName + " - " + aRequestType);
+ proxy = this;
+
+ deferredResult = new MochiKit.Async.Deferred();
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("x.1 Proxy.DWR.sendMessage - 1: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(proxy, 'payToll'), aRequestType);
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("x.2 Proxy.DWR.sendMessage - 2: " + Clipperz.Base.serializeJSON(res)); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(proxy, 'sendRemoteMessage'), aFunctionName);
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("x.3 Proxy.DWR.sendMessage - 3: " + res); return res;});
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("x.3 Proxy.DWR.sendMessage - 3: " + Clipperz.Base.serializeJSON(res)); return res;});
+ deferredResult.callback(someParameters);
+
+//MochiKit.Logging.logDebug("<<< Proxy.DWR.sendMessage");
+ return deferredResult;
+*/
+
+// return this.sendRemoteMessage(aFunctionName, someParameters);
+
+
+ var deferredResult;
+ var proxy;
+
+ proxy = this;
+
+ deferredResult = new MochiKit.Async.Deferred();
+ deferredResult.addCallback(MochiKit.Base.method(proxy, 'sendRemoteMessage'), aFunctionName);
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("x.3 Proxy.PHP.sendMessage - 3: " + res); return res;});
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("x.3 Proxy.PHP.sendMessage - 3.1: " + Clipperz.Base.serializeJSON(res)); return res;});
+
+ deferredResult.callback(someParameters);
+
+ return deferredResult;
+ },
+
+ //=========================================================================
+
+ 'sendRemoteMessage': function(aFunctionName, someParameters) {
+/*
+ var deferredResult;
+
+//MochiKit.Logging.logDebug(">>> Proxy.DWR.sendRemoteMessage('" + aFunctionName + "', " + Clipperz.Base.serializeJSON(someParameters) + ") - " + this);
+ deferredResult = new MochiKit.Async.Deferred();
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Proxy.DWR.sendRemoteMessage - 1: " + res); return res;});
+// deferredResult.addCallback(MochiKit.Base.method(this, 'setTollCallback'));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("Proxy.DWR.sendRemoteMessage - 2: " + res); return res;});
+
+ com_clipperz_pm_Proxy[aFunctionName](Clipperz.Base.serializeJSON(someParameters), {
+ callback:MochiKit.Base.method(deferredResult, 'callback'),
+ errorHandler:MochiKit.Base.method(deferredResult, 'errback')
+ });
+//MochiKit.Logging.logDebug("<<< Proxy.PHP.sendRemoteMessage - result: " + deferredResult);
+
+ return deferredResult;
+*/
+
+ var deferredResult;
+ var parameters;
+
+//MochiKit.Logging.logDebug(">>> Proxy.PHP.sendRemoteMessage('" + aFunctionName + "', " + Clipperz.Base.serializeJSON(someParameters) + ") - " + this);
+ parameters = {};
+ parameters['method'] = aFunctionName;
+// parameters['version'] = someParameters['version'];
+// parameters['message'] = someParameters['message'];
+ parameters['parameters'] = Clipperz.Base.serializeJSON(someParameters);
+//MochiKit.Logging.logDebug("--- Proxy.PHP.sendRemoteMessage('" + Clipperz.Base.serializeJSON(parameters) + ") - " + this);
+ deferredResult = new MochiKit.Async.Deferred();
+ deferredResult.addCallback(MochiKit.Async.doXHR, "./php/index.php", {
+ method:'POST',
+ sendContent:MochiKit.Base.queryString(parameters),
+ headers:{"Content-Type":"application/x-www-form-urlencoded"}
+ });
+//deferredResult.addCallback(function(res) {MochiKit.Logging.logDebug("Proxy.PHP.response - 2: " + res.responseText); return res;});
+//deferredResult.addErrback(function(res) {MochiKit.Logging.logDebug("Proxy.PHP.response - ERROR: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Async.evalJSONRequest);
+ deferredResult.callback();
+
+ return deferredResult;
+ },
+
+ //=========================================================================
+
+ 'isReadOnly': function() {
+ return false;
+ },
+
+ //=========================================================================
+ __syntaxFix__: "syntax fix"
+
+});
+
+//=============================================================================
+
+//Clipperz.PM.Proxy.defaultProxy = new Clipperz.PM.Proxy.PHP("Proxy.PHP - async test");
diff --git a/frontend/beta/js/Clipperz/PM/Proxy/Proxy.Test.js b/frontend/beta/js/Clipperz/PM/Proxy/Proxy.Test.js
new file mode 100644
index 0000000..fd5bf8a
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Proxy/Proxy.Test.js
@@ -0,0 +1,94 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. 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) {
+ args = args || {};
+
+ Clipperz.PM.Proxy.Offline.call(this, args);
+
+
+
+ return this;
+}
+
+Clipperz.PM.Proxy.Test.prototype = MochiKit.Base.update(new Clipperz.PM.Proxy.Offline(), {
+
+ 'toString': function() {
+ return "Clipperz.PM.Proxy.Test";
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'isTestData': function() {
+ return typeof(this.userData()['__masterkey_test_value__'] != 'undefined');
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'userDetails': function() {
+ var result;
+
+ if (this.isTestData()) {
+ var serializedHeader;
+ var version;
+
+ version = this.userData()['version'];
+ serializedHeader = Clipperz.Base.serializeJSON(this.userData()['userDetails']);
+ result = Clipperz.PM.Crypto.encryptingFunctions.versions[version].encrypt(this.userData()['__masterkey_test_value__'], serializedHeader);
+ } else {
+ result = Clipperz.PM.Proxy.Offline.prototype.userDetails.call(this);
+ }
+
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'statistics': function() {
+ var result;
+ var serializedStatistics;
+ var version;
+
+ version = this.userData()['version'];
+ serializedStatistics = Clipperz.Base.serializeJSON(this.userData()['statistics']);
+ result = Clipperz.PM.Crypto.encryptingFunctions.versions[version].encrypt(this.userData()['__masterkey_test_value__'], serializedStatistics);
+
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+
+});
+
diff --git a/frontend/beta/js/Clipperz/PM/Strings.js b/frontend/beta/js/Clipperz/PM/Strings.js
new file mode 100644
index 0000000..e9f5dbe
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Strings.js
@@ -0,0 +1,231 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. 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 = {
+ 'en-us': {
+ '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",
+
+ 'donateSplashPanelIconUrl': "./images/smiles_big.gif",
+
+ 'icons_baseUrl': "https://www.clipperz.com/images/icons",
+
+ 'passwordGeneratorLowercaseCharset': "abcdefghijklmnopqrstuvwxyz",
+ 'passwordGeneratorUppercaseCharset': "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
+ 'passwordGeneratorNumberCharset': "0123456789",
+ 'passwordGeneratorSymbolCharset': "!@#$%^&*+?[]{}/|\\<>,.;:~=-_",
+
+ '_': ""
+ }
+}
+
+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.Languages.setSelectedLanguage = function(aLanguage) {
+ var language;
+ var selectedLanguage;
+
+ language = (aLanguage || Clipperz.PM.Strings.preferredLanguage || 'default').toLowerCase();
+//MochiKit.Logging.logDebug("1 - language: " + language);
+ if (typeof(Clipperz.PM.Strings.defaultLanguages[language]) != 'undefined') {
+ language = Clipperz.PM.Strings.defaultLanguages[language];
+//MochiKit.Logging.logDebug("2 - language: " + language);
+ }
+
+ if (typeof(Clipperz.PM.Strings.Languages[language]) != 'undefined') {
+ selectedLanguage = language;
+//MochiKit.Logging.logDebug("### selectedLanguage full match: " + selectedLanguage);
+ } else if (typeof(Clipperz.PM.Strings.defaultLanguages[language.substr(0,2)]) != 'undefined') {
+ selectedLanguage = Clipperz.PM.Strings.defaultLanguages[language.substr(0,2)];
+//MochiKit.Logging.logDebug("### selectedLanguage partial match: " + selectedLanguage);
+ } else {
+ selectedLanguage = Clipperz.PM.Strings.defaultLanguages['default'];
+//MochiKit.Logging.logDebug("### selectedLanguage default match: " + selectedLanguage);
+ }
+
+//MochiKit.Logging.logDebug("### selectedLanguage: " + selectedLanguage);
+ if (selectedLanguage != Clipperz.PM.Strings.selectedLanguage) {
+//MochiKit.Logging.logDebug(">>> setting Clipperz.PM.Strings.selectedLanguage: " + selectedLanguage);
+ Clipperz.PM.Strings.selectedLanguage = selectedLanguage;
+
+ MochiKit.Base.update(Clipperz.PM.Strings, Clipperz.PM.Strings.standardStrings)
+//MochiKit.Logging.logDebug("=== 1: " + Clipperz.PM.Strings['bookmarkletTabInstructions']);
+ MochiKit.Base.updatetree(Clipperz.PM.Strings, Clipperz.PM.Strings.Languages[Clipperz.PM.Strings.defaultLanguages['default']]);
+//MochiKit.Logging.logDebug("=== 2: " + Clipperz.PM.Strings['bookmarkletTabInstructions']);
+ MochiKit.Base.updatetree(Clipperz.PM.Strings, Clipperz.PM.Strings.GeneralSettings[Clipperz.PM.Strings.defaultLanguages['default']]);
+//MochiKit.Logging.logDebug("=== 3: " + Clipperz.PM.Strings['bookmarkletTabInstructions']);
+ MochiKit.Base.updatetree(Clipperz.PM.Strings, Clipperz.PM.Strings.Languages[selectedLanguage]);
+//MochiKit.Logging.logDebug("=== 4: " + Clipperz.PM.Strings['bookmarkletTabInstructions']);
+ MochiKit.Base.updatetree(Clipperz.PM.Strings, Clipperz.PM.Strings.GeneralSettings[selectedLanguage]);
+//MochiKit.Logging.logDebug("=== 5: " + Clipperz.PM.Strings['bookmarkletTabInstructions']);
+
+ Clipperz.NotificationCenter.notify(Clipperz.PM.Strings.Languages, 'switchLanguage', selectedLanguage);
+//MochiKit.Logging.logDebug("<<< setting Clipperz.PM.Strings.selectedLanguage. Done");
+ }
+}
+
+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)) {
+//MochiKit.Logging.logDebug("LANGUAGE specified in the query string");
+ language = RegExp.$1;
+ }
+
+//MochiKit.Logging.logDebug("+++ preferredLanguage: " + language);
+ Clipperz.PM.Strings.preferredLanguage = language.toLowerCase();
+//MochiKit.Logging.logDebug("## preferredLanguage: " + Clipperz.PM.Strings.preferredLanguage);
+ Clipperz.PM.Strings.Languages.setSelectedLanguage(Clipperz.PM.Strings.preferredLanguage);
+}
+
+//MochiKit.DOM.addLoadEvent(Clipperz.PM.Strings.Languages.initSetup);
diff --git a/frontend/beta/js/Clipperz/PM/Strings/MessagePanelConfigurations.js b/frontend/beta/js/Clipperz/PM/Strings/MessagePanelConfigurations.js
new file mode 100644
index 0000000..446e96c
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Strings/MessagePanelConfigurations.js
@@ -0,0 +1,389 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. 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"
+
+}
diff --git a/frontend/beta/js/Clipperz/PM/Strings/Strings_de-DE.js b/frontend/beta/js/Clipperz/PM/Strings/Strings_de-DE.js
new file mode 100644
index 0000000..ecc8a36
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Strings/Strings_de-DE.js
@@ -0,0 +1,352 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+Clipperz.PM.Strings.Languages['de-DE'.toLowerCase()] = MochiKit.Base.merge(Clipperz.PM.Strings.Languages['en-us'], {
+'clipperzServiceDescription': "<h2>Privatsphäre für Deine Daten</h2> <ul> <li> <h3>Clipperz heißt:</h3> <ul> <li> <p>sichere und einfache zu bedienene Passwortverwaltung</p> </li> <li> <p>eine effektive Lösung des einmaligen Anmeldens</p> </li> <li> <p>eine digitale Brieftasche für Deine vertraulichen Daten</p> </li> </ul> </li> <li> <h3>Clipperz bietet Dir:</h3> <ul> <li> <p>einfaches Speichern und Verwalten von Passwörtern und Webzugangsdaten</p> </li> <li> <p>schnelles unkompliziertes einloggen, ohne Eingabe des Benutzernamen und Passworts, bei Webdiensten</p> </li> <li> <p>Schutz aller Deiner persönlichen Daten: Zutrittscodes, PINs, Benutzernamen, Passwörter, Kreditkartennummern, &hellip;</p> </li> <li> <p>Deine Geheimnisse mit Familienmitgliedern und Freunden zu teilen (mehr dazu in Kürze)</p> </li> </ul> </li> <li> <h3>Clipperz ist:</h3> <ul> <li> <p>kostenlos und absolut anonym</p> </li> <li> <p>unkomplizierter Zugriff zu jeder Zeit von jedem Rechner</p> </li> <li> <p>ohne Download und Installation verwendbar</p> </li> <li> <p>ein Schutz gegen das Speichern von Passwörtern auf Deinem PC oder das Notieren auf Papier</p> </li> </ul> </li> <li> <h3>Clipperz Sicherheit:</h3> <ul> <li> <p>Deine sensiblen persönlichen Informationen werden lokal durch Deinen Browser verschlüsselt, bevor sie an Clipperz über das Internet gesendet werden</p> </li> <li> <p>Der Schlüssel für diese Daten ist der Sicherheitssatz, den nur Du kennst</p> </li> <li> <p>Clipperz speichert Deine sensiblen Daten nur in verschlüsselter Form und kann zu keinem Zeitpunkt diese entschlüssel und in ihrer ursprünglichen Klartextform zugänglich machen</p> </li> <li> <p>Clipperz basiert auf standart Verschlüsselungsverfahren. Nichts ausergewöhnliches – oder hand gestricktes</p> </li> <li> <p>Du kannst den Quellcode zu jeder Zeit anschauen, aber Du brauchst nichts von Kryptographie zu verstehen um ein glücklicher Anwender zu sein!</p> </li> </ul> </li> <li> <a href=\"http://www.clipperz.com\" target=\"_blank\">Weitere Informationen</a> </li> </ul> ",
+'loginFormTitle': "Login zu Deinem Clipperz Konto",
+'loginFormUsernameLabel': "Benutzernamen",
+'loginFormPassphraseLabel': "Sicherheitssatz",
+'loginFormDontHaveAnAccountLabel': "Du hast noch kein Clipperz Konto?",
+'loginFormCreateOneLabel': "Konto erstellen",
+'loginFormForgotYourCredentialsLabel': "Zugangsdaten vergessen?",
+'loginFormAarghThatsBadLabel': "Misst! Dass ist schlecht!",
+'loginFormAfraidOfMaliciousScriptsLabel': "verängstigt von bösartigen Scripts?",
+'loginFormVerifyTheCodeLabel': "begutachte den Quellcode",
+'loginFormButtonLabel': "Einloggen",
+'loginPanelSwithLanguageDescription': "<h5>Wechsel zu Deiner vervorzugten Sprache</h5> ",
+'browserCompatibilityDescription': "<p>Bessere und sicherere Clipperz-Erfahrung mit Firefox. Clipperz funktioniert auch mit Safari, Opera und MS Internet Explorer!</p> ",
+'loginMessagePanelInitialTitle': "Du wirst eingeloggt…",
+'loginMessagePanelInitialButtonLabel': "Abbruch",
+'loginMessagePanelConnectedTitle': "Verbunden",
+'loginMessagePanelConnectedText': "Fertig",
+'loginMessagePanelFailureTitle': "Fehler",
+'loginMessagePanelFailureText': "Login fehlgeschlagen",
+'loginMessagePanelFailureButtonLabel': "Schließen",
+'connectionLoginSendingCredentialsMessageTitle': "Prüfe Zugangsdaten",
+'connectionLoginSendingCredentialsMessageText': "Sende Zugangsdaten",
+'connectionLoginCredentialsVerificationMessageTitle': "Prüfe Zugangsdaten",
+'connectionLoginCredentialsVerificationMessageText': "Führe SRP Authentifizierung durch",
+'connectionLoginDoneMessageTitle': "Prüfe Zugangsdaten",
+'connectionLoginDoneMessageText': "Verbunden",
+'userLoginPanelUpgradingUserCredentialsMessageTitle': "Prüfe Zugangsdaten",
+'userLoginPanelUpgradingUserCredentialsMessageText': "Aktualisierung Deiner Zugangsdaten auf ein neues Authentifizierungsschema",
+'userLoginPanelConnectedMessageTitle': "Benutzer authentifiziert",
+'userLoginPanelConnectedMessageText': "Login erfolgreich",
+'userLoginPanelTryingAnOlderConnectionSchemaMessageTitle': "Prüfe Zugangsdaten",
+'userLoginPanelTryingAnOlderConnectionSchemaMessageText': "Probiere älteres Authentifizierungsschema",
+'userLoginPanelLoadingUserDataMessageTitle': "Benutzer authentifiziert",
+'userLoginPanelLoadingUserDataMessageText': "Lade verschlüsselte Kartendaten von Clipperz",
+'userLoginPanelDecryptingUserDataMessageTitle': "Benutzer authentifiziert",
+'userLoginPanelDecryptingUserDataMessageText': "Lokale Entschlüsselung der Kartendaten",
+'userLoginPanelDecryptingUserStatisticsMessageTitle': "Benutzer authentifiziert",
+'userLoginPanelDecryptingUserStatisticsMessageText': "Lokale Entschlüsselung der Benutzerstatisik",
+'splashAlertTitle': "Willkommen bei Clipperz!",
+'splashAlertText': "<p>Sicherheitshinweis</p> <ul> <li> <p>Die Speicherung von Informationen bei Clipperz ist so sicher, wie der Sicherheitssatz den Du zum Schutz gewählt hast. Ist der Sicherheitssatz nicht bekannt, können keine Informationen abgefragt werden.</p> </li> <li> <p>Solltest Du Clipperz nutzen, um sensible und kritische persönliche Daten abzuspeichern, so empfehlen wir in jedem Fall die Nutzung eines langen Sicherheitssatzes als Passwort und die Nutzung von Sonderzeichen, Zahlen, Groß- und Kleinbuchstaben.</p> </li> <li> <p>Clipperz kann einen verlorenen Sicherheitssatz nicht wiederherstellen!</p> </li> </ul> <p>Weitere Informationen findest Du bei <a href=\"http://www.clipperz.com\" target=\"_blank\">Clipperz</a>.</p> ",
+'splashAlertCloseButtonLabel': "Ok",
+'registrationFormTitle': "Erstelle Dein Konto",
+'registrationFormUsernameLabel': "Benutzernamen",
+'registrationFormPassphraseLabel': "Sicherheitssatz",
+'registrationFormRetypePassphraseLabel': "Wiederhole Sicherheitssatz",
+'registrationFormSafetyCheckLabel': "Ich akzeptiere dass es Clipperz nicht möglich ist, einen verlorenen Sicherheitssatz wiederherzustellen.",
+'registrationFormTermsOfServiceCheckLabel': "Ich habe die <a href='http://www.clipperz.com/terms_of_service' target='_blank'>Nutzungsbedingungen</a> gelesen, verstanden und akzeptiere diese.",
+'registrationFormDoYouAlreadyHaveAnAccountLabel': "Hast Du bereits einen Zugang?",
+'registrationFormSimplyLoginLabel': "Einloggen",
+'registrationFormButtonLabel': "Anmelden",
+'registrationFormWarningMessageNotMatchingPassphrases': "Deine Sicherheitssätze stimmen nicht überein. Bitte erneut eingeben.",
+'registrationFormWarningMessageSafetyCheckNotSelected': "Bitte lese die Bedingungen und akzeptiere die Auswahlboxen weiter unten.",
+'registrationFormWarningMessageTermsOfServiceCheckNotSelected': "Du musst die Nutzungsbedingungen akzeptieren.",
+'registrationMessagePanelInitialTitle': "Benutzer wird angelegt…",
+'registrationMessagePanelInitialButtonLabel': "Abbruch",
+'registrationMessagePanelRegistrationDoneTitle': "Anmeldung",
+'registrationMessagePanelRegistrationDoneText': "Fertig",
+'registrationMessagePanelFailureTitle': "Anmerldung fehlgeschlagen",
+'registrationMessagePanelFailureButtonLabel': "Schließen",
+'connectionRegistrationSendingRequestMessageText': "Zugangsdaten werden geprüft",
+'connectionRegistrationSendingCredentialsMessageText': "Sende Zugangsdaten",
+'registrationSplashPanelTitle': "Sicherheitshinweis",
+'registrationSplashPanelDescription': "<p>Dies sind Deine Clipperz Zugangsdaten, pass sehr gut auf sie auf. Clipperz wird diese kein zweites und weiteres mal anzeigen!</p> ",
+'registrationSplashPanelUsernameLabel': "Benutzernamen",
+'registrationSplashPanelPassphraseLabel': "Schlüsselsatz",
+'donateHeaderLinkLabel': "spende",
+'creditsHeaderLinkLabel': "credits",
+'feedbackHeaderLinkLabel': "feedback",
+'helpHeaderLinkLabel': "hilfe",
+'forumHeaderLinkLabel': "forum",
+'recordMenuLabel': "Karten",
+'accountMenuLabel': "Benutzer",
+'dataMenuLabel': "Daten",
+'contactsMenuLabel': "Kontakt",
+'bookmarkletMenuLabel': "Bookmarklet",
+'logoutMenuLabel': "Ausloggen",
+'lockMenuLabel': "Sperren",
+'lockTitle': "Dieses Konto ist gesperrt",
+'lockDescription': "<p>Bitte gebe Deinen Sicherheitssatz ein, um das Clipperz-Konto zu entsperren.</p> ",
+'unlockButtonLabel': "Entsperren",
+'changePasswordTabLabel': "Sicherheitssatz ändern",
+'changePasswordTabTitle': "Sicherheitssatz ändern",
+'changePasswordFormUsernameLabel': "Benutzername",
+'changePasswordFormOldPassphraseLabel': "Alter Sicherheitssatz",
+'changePasswordFormNewPassphraseLabel': "Neuer Sicherheitssatz",
+'changePasswordFormRetypePassphraseLabel': "Wiederholdung neuen Sicherheitssatz",
+'changePasswordFormSafetyCheckboxLabel': "Ich akzeptiere dass es Clipperz nicht möglich ist, einen verlorenen Sicherheitssatz wiederherzustellen.",
+'changePasswordFormSubmitLabel': "Sicherheitssatz ändern",
+'changePasswordFormWrongUsernameWarning': "Falscher Benutzername",
+'changePasswordFormWrongPassphraseWarning': "Falscher Sicherheitssatz",
+'changePasswordFormWrongRetypePassphraseWarning': "Deine Sicherheitssätze stimmen nicht überein. Bitte erneut eingeben.",
+'changePasswordFormSafetyCheckWarning': "Bitte ließ die folgenden Hinweise und akzeptiere diese.",
+'changePasswordFormProgressDialogTitle': "Ändere Zugangsdaten",
+'changePasswordFormProgressDialogConnectedMessageTitle': "Verbunden",
+'changePasswordFormProgressDialogConnectedMessageText': "Fertig",
+'changePasswordFormProgressDialogErrorMessageTitle': "Fehler",
+'changePasswordFormProgressDialogErrorMessageText': "Ändern der Zugangsdaten fehlgeschlagen!",
+'changeCredentialsPanelEncryptingDataMessageTitle': "Ändere Sicherheitssatz",
+'changeCredentialsPanelEncryptingDataMessageText': "Lokale Verschlüsselung der Kartendaten",
+'changeCredentialsPanelCreatingNewCredentialsMessageTitle': "Ändere Sicherheitssatz",
+'changeCredentialsPanelCreatingNewCredentialsMessageText': "Aktualisiere Zugangsdaten",
+'changeCredentialsPanelSendingNewCredentialsToTheServerMessageTitle': "Ändere Sicherheitssatz",
+'changeCredentialsPanelSendingNewCredentialsToTheServerMessageText': "Sende verschlüsselte Zugangsdaten zu Clipperz",
+'changeCredentialsPanelDoneMessageTitle': "Ändere Sicherheitssatz",
+'changeCredentialsPanelDoneMessageText': "Fertig",
+'manageOTPTabLabel': "Verwaltung des Sicheitssatzes für einmaliges Anmelden",
+'manageOTPTabTitle': "Verwaltung des Sicheitssatzes für einmaliges Anmelden",
+'manageOTPTabDescription': "<p>Der Sicherheitssatz für einmaliges Anmelden funktoniert wie Dein regulärer Sicherheitssatz, nur dass er nur einmal verwendet werden kann.</p> <p>Sollte der gleiche Sicherheitssatz zu einem späteren Zeitpunkt nocheinmal genutzt werden, wird dieser automatisch zurückgewießen und der Einlogvorgang scheitert.</p> <p>Sofort nach einem erfolgreichen Login wird der Sicherheitssatz für einmaliges Anmelden gelöscht und somit verhindert dass er ungewollt verwendet wird.</p> <p>Die Nutzung von Sicherheitssätzen für einmaliges Anmelden sind eine ideale Möglichkeit wenn Du verunsichert bist ob Trojaner, Spyware oder ähnliches auf Deinem Rechner vorhanden ist.</p> <p> <b>Es wird empfohlen Sicherheitssätze für einmaliges Anmelden beim Zugiff auf Clipperz zu verwenden, wenn man sich an öffentlichen Rechnern befindet, wie in Internet Cafes oder Bücherreien.</b> </p> <p> </p> <p> <b>Mehr dazu in Kürze ...</b> </p> ",
+'accountPreferencesLabel': "Einstellungen",
+'accountPreferencesTabTitle': "Einstellungen",
+'accountPreferencesLanguageTitle': "Sprachenauswahl",
+'accountPreferencesLanguageDescription': "<p>Wähle Deine bevorzugte Sprache, aus der unten stehenden Liste.</p> ",
+'accountPreferencesInterfaceTitle': "Personalisiere Dein persönliches Clipperz-Erscheinungsbild",
+'accountPreferencesInterfaceDescription': "<p>Passe dass Clipperz-Erscheinungsbild an Deine Wünsche an.</p> ",
+'saveUserPreferencesFormSubmitLabel': "Speichern",
+'cancelUserPreferencesFormSubmitLabel': "Abbruch",
+'accountPreferencesSavingPanelTitle_Step1': "Speichere Einstellungen",
+'accountPreferencesSavingPanelText_Step1': "Lokale Verschlüsselung der Einstellungen",
+'accountPreferencesSavingPanelTitle_Step2': "Speichere Einstellungen",
+'accountPreferencesSavingPanelText_Step2': "Sende verschlüsselte Einstellungen",
+'deleteAccountTabLabel': "Konto löschen",
+'deleteAccountTabTitle': "Konto löschen",
+'deleteAccountFormUsernameLabel': "Benutzername",
+'deleteAccountFormPassphraseLabel': "Sicherheitssatz",
+'deleteAccountFormSafetyCheckboxLabel': "Ich bin mir bewusst, dass alle meine Daten gelöscht werden und dieser Vorgang in keinem Falle rückgängig gemacht werden kann.",
+'deleteAccountFormSubmitLabel': "Konto löschens",
+'deleteAccountFormWrongUsernameWarning': "Falscher Benutzername",
+'deleteAccountFormWrongPassphraseWarning': "Falscher Sicherheitssatz",
+'deleteAccountFormSafetyCheckWarning': "Bitte lese die Bedingungen und akzeptiere die Auswahlboxen weiter unten.",
+'accountPanelDeletingAccountPanelConfirmationTitle': "ACHTUNG",
+'accountPanelDeleteAccountPanelConfirmationText': "Bist Du sicher, dass Du den Zugang löschen möchtest?",
+'accountPanelDeleteAccountPanelConfirmButtonLabel': "Ja",
+'accountPanelDeleteAccountPanelDenyButtonLabel': "Nein",
+'offlineCopyTabLabel': "Offline Kopie",
+'offlineCopyTabTitle': "Offline Kopie",
+'offlineCopyTabDescription': "<p>Mit nur einem Klick kannst Du alle Deine verschlüsselten Daten von dem Clipperz Server auf Deine Festplatte speichern und somit eine “nur lesbare” Offline Version anlegen. Diese Version ist auch dann verwendbar, wenn Du keine Verbindung ins Internet hast. (Zum Beispiel zum Speichern von Login-Informationen bei einem Hotspot)</p> <p>Die “nur lesbare” Version ist genauso sicher, wie die änderbare Version auf dem Server. Deine Daten werden niemals entschlüsselt gespeichert - beide Versionen verwenden die gleiche Art der Verschlüsselung und Entschlüsselung direkt im Browser.</p> <ol> <li> <p>Klicke auf den untenstehenden Link um die Offline Version herunterzuladen.</p> </li> <li> <p>Der Browser fragt Dich, was Du mit der Datei “Clipperz_YYYYMMDD.zip” machen möchtest. Speichere Sie auf Deine Festplatte.</p> </li> <li> <p>Unzip (dekomprimiere) die Datei. Du erhälst das Verzeichnis “Clipperz_YYYYMMDD”.</p> </li> <li> <p>Öffne das Verzeichnis “Clipperz_YYYYMMDD” und mache einen Doppelklick auf die Datei “index.html”.</p> </li> <li> <p>Gib Deinen Clipperz Benutzernamen und Sicherheitsschlüssel ein, um Zugriff auf Deine persönlichen Daten auch ohne Internetzugang zu erhalten.</p> </li> </ol> ",
+'offlineCopyDownloadLinkLabel': "Download",
+'sharingTabLabel': "Freigabe für gemeinsame Nutzung",
+'sharingTabTitle': "Freigabe für gemeinsame Nutzung",
+'sharingTabDescription': "<p>Häufig muss eine vertrauenswürdige Information mit mehreren Personen geteilt werden.</p> <p>Dies sollte so einfach sein, wie einem Kollegen die PIN für den Anrufbeantworter zu geben, wenn Du im Urlaub bist; jedoch so schwierig, wie berechtigten Erben Zugriff auf das Ersparte bei der Bank zu geben.</p> <p>Clipperz ermöglicht die einfache Freigabe für gemeinsam genutzte Informationen, an berechtigte Personen, durch einen einfachen Prozess.</p> <p> </p> <p> <b>Mehr dazu in Kürze ...</b> </p> ",
+'importTabLabel': "Import",
+'importTabTitle': "Import",
+'importTabDescription': "<p> <b>In Kürze ...</b> </p> ",
+'printingTabLabel': "Export",
+'printingTabTitle': "Export",
+'printingTabDescription': "<p> <b>Drucke deine Kartendaten</b> </p> <p>Klicke auf den untenstehenden Link. Es öffnet sich ein Fenster mit Deinen Kartendaten in einem druckerfreundlichen Format.</p> <p>Wenn Du den Ausdruck aus Absicherungsgründen nutzen möchtest, nutze lieber die Variante der sichereren “Offline Kopie”. Ein Ausdruck ist wie eine Notiz auf dem Scheibtisch und könnte von jedem ohne weiteres gelesen werden. Bewahre diesen an einem sicheren, für andere nicht zugänglichen Ort auf!</p> ",
+'printingLinkLabel': "Druckerfreundliches Format",
+'contactsTabLabel': "Kontakte",
+'contactsTabTitle': "Kontakte",
+'bookmarkletTabLabel': "Bookmarklet",
+'bookmarkletTabTitle': "Bookmarklet",
+'bookmarkletTabDescription': "<p>Ein Bookmarklet ist ein Werkezug, welches Dir mit einem Mausklick wichtige Funktionen ermöglicht. Es kann gespeichert und verwendet werden wie eine ganz normale Webseite, die Du in Deine Favoriten gespeichert hast.</p> <p>Das clipperz Bookmarklet ermöglicht Dir schnell und einfach neue Karten und Direkt-Logins für bestehende Karten anzulegen.</p> <p> <b>Bitte beachte: Das Bookmarklet enthält keine Informationen zu Deinem Zugang (wie Benutzernamen oder Passwort), das Bookmarklet ist ein generisches Werzeug, welches für jeden Clipperz Anwender den gleichen Code beinhaltet.</b> </p> <div> <p>Um das Bookmarklet zu installieren <b>ziehe</b> den unten stehenden Link in die Lesezeichen-Leiste Deines Browsers.</p> </div> ",
+'bookmarkletTabBookmarkletTitle': "Zu Clipperz hinzufügen",
+'bookmarkletTabInstructions': "<h3>Anlegen einer neuen Karte für das Direkt Login bei einem Webservice</h3> <ol> <li> <p>Öffne die Webseite, auf der das Anmeldeforumlar vorhanden ist. (Das ist die Seite, auf der Du normal Deine Zugangsdaten einträgst)</p> </li> <li> <p>Öffne das Boormarklet durch anklicken: ein Pop-Up Fenster erscheint und bietet Dir die Karteninformationen an.</p> </li> <li> <p>Kopiere von diesem Fenster den Inhalt des größten Textfeldes durch in die Zwischenablage (Makieren und STRG+C)</p> </li> <li> <p>Öffne Deinen Clipperz Zugang und wähle <b>Neue Karte anlegen</b>.</p> </li> <li> <p>Füge den Inhalt Deiner Zwischenablage in das Textfeld ein (STRG+V) und ergänze optional einen <b>Titel</b>.</p> </li> <li> <p>Drücke die <b>Anlegen</b> Schaltfläche, kontrolliere nocheinmal die Details, und wähle anschließend <b>Speichern<b>.</p> </li> </ol> <h3>Direkt Login Funktionalität zu einer bestehenden Karte ergänzen</h3> <ol> <li> <p>Gleich wie oben.</p> </li> <li> <p>Gleich wie oben.</p> </li> <li> <p>Gleich wie oben.</p> </li> <li> <p>Öffne Deinen Clipperz Zugang und wähle die Karte, die Du ändern möchtest. Klicke anschließend auf <b>Bearbeiten</b>.</p> </li> <li> <p>Füge den Inhalt Deiner Zwischenablage in das Textfeld für “Direkt Login” ein (STRG+V).</p> </li> <li> <p>Drücke auf <b>Direkt Login hinzufügen</b>, kontrolliere die Angabgen und wähle <b>Speichern</b>.</p> </li> </ol> <p> </p> <p>Weitere Informationen über das Bookmarklet findest Du <a href=\"http://www.clipperz.com/support/user_guide/bookmarklet\" target=\"_blank\">hier</a>.</p> ",
+'mainPanelDirectLoginBlockLabel': "Direktes Login",
+'directLinkReferenceShowButtonLabel': "zeigen",
+'mainPanelDirectLoginBlockDescription': "<p>Add “direct logins” to sign in to your web accounts without typing usernames and passwords!</p> <p>“Direct logins” greatly enhance your password security since you can:</p> <ul> <li> <p>conveniently adopt and enter complex passwords;</p> </li> <li> <p>never re-use the same and easy-to-guess password.</p> </li> </ul> <p>Simple and quick configuration with the Clipperz <b>bookmarklet</b>.</p> <a href=\"http://www.clipperz.com/support/user_guide/direct_logins\" target=\"_blank\">Learn more about “direct logins”</a> ",
+'mainPanelRecordsBlockLabel': "Karten",
+'mainPanelAddRecordButtonLabel': "Neue Karte anlegen",
+'mainPanelRemoveRecordButtonLabel': "Karte löschen",
+'mainPanelRecordFilterBlockAllLabel': "all",
+'mainPanelRecordFilterBlockTagsLabel': "tags",
+'mainPanelRecordFilterBlockSearchLabel': "search",
+'recordDetailNoRecordAtAllTitle': "Willkommen bei Clipperz!",
+'recordDetailNoRecordAtAllDescription': "<h5>Beginne mit dem Hinzufügen von Karten zu Deinem Zugang.</h5> <p>Karten sind einfache und flexible Formulare, bei denen Du Deine Passwörter und andere vertrauenswürde Daten speichern kannst.</p> <p>Karten können Zugangsinformationen für eine WebSite, die Kombination Deines Fahrradschlosses, oder Daten Deiner Kreditkarte enthalten, ...</p> <h5>Vergiss nicht das Bookmarklet</h5> <p>Bevor Du beginnst, installiere Dir das “Add to Clipperz” Bookmarklet: Es vereinfacht Dir das anlegen von Karten und verbessert somit den Komfor.</p> <p>Gehe zum “Bookmarklet” Tabulator um herauszufinden, wie es installiert und verwendet werden kann.</p> <p> </p> <p>Dann klicke einfach auf den <b>Neue Karte anlegen</b> Button und genieße Deinen Clipperz Zugang.</p> <p> </p> <a href=\"http://www.clipperz.com/support/user_guide/managing_cards\" target=\"_blank\">Näheres zum Erstellen und Verwalten von Karten lernen</a> ",
+'newRecordWizardTitleBox': "<h5>Bitte wähle eine Vorlage</h5> <p>Karten sind einfache und flexible Formulare, bei denen Du Passwörter oder jede Art von vertraulichen Informationen speichern kannst.</p> <p>Beginne mit der Auswahl einer der unten stehenden Vorlagen. Zu jeder Zeit kannst Du Deine Karten durch hinzufügen oder entfernen von Feldern verändern.</p> ",
+'newRecordWizardBookmarkletConfigurationTitle': "Direktes Login",
+'newRecordWizardBookmarkletConfigurationDescription': "<p>Füge bitte unten den Konfigurationscode ein, den das Clipperz Bookmarklet erzeugt hat.</p> <p>Eine neue Karte mit einem vollständigen Direkt Login zu dem gewählten Webzugang wird angelegt.</p> ",
+'newRecordWizardCreateButtonLabel': "Anlegen",
+'newRecordWizardCancelButtonLabel': "Abbruch",
+'recordTemplates': {
+ 'WebAccount': {
+ 'title': "Web Zugangsdaten",
+ 'description': "<p>Eine einfache Karte, die die Login Informationen für einen Online Service speichert.</p> ",
+ 'fields': {
+ 'URL': "Web Adresse",
+ 'TXT': "Benutzername / E-Mail",
+ 'PWD': "Passwort"
+ }
+ },
+ 'BankAccount': {
+ 'title': "Bank Zugangsdaten",
+ 'description': "<p>Speichere geschützt Deine Online Banking Zugangsdaten.</p> ",
+ 'fields': {
+ 'TXT': "Bank",
+ 'TXT': "Kontonummer",
+ 'URL': "Web Adresse",
+ 'TXT': "Online Zugangsdaten",
+ 'PWD': "Online Passwort"
+ }
+ },
+ 'CreditCard': {
+ 'title': "Kreditkarte",
+ 'description': "<p>Kartennummer, CVV2, Ablaufdatum und PIN zu jeder Zeit abrufbar bei Clipperz.</p> ",
+ 'fields': {
+ 'TXT': "Art (Visa, AmEx, ...)",
+ 'TXT': "Nummer",
+ 'TXT': "Inhaber",
+ 'TXT': "Ablaufdatum",
+ 'TXT': "CVV2",
+ 'PWD': "PIN",
+ 'URL': "Webseite",
+ 'TXT': "Online Zugangsdaten",
+ 'PWD': "Passwort"
+ }
+ },
+ 'AddressBookEntry': {
+ 'title': "Adressbuch Eintrag",
+ 'description': "<p>Clipperz kann auch als Dein neues privates Adressbuch agieren. Nutze diese Vorlage um einfach eine neuen Eintrag anzulegen.</p> ",
+ 'fields': {
+ 'TXT': "Name",
+ 'TXT': "Email",
+ 'TXT': "Telefon",
+ 'TXT': "Handy",
+ 'ADDR': "Adresse"
+ }
+ },
+ 'Custom': {
+ 'title': "Benutzerdefinierte Karte",
+ 'description': "<p>Egal welche Art von vertraulichen Informationen Du speichern musst, mit der benutzerdefinierten Karte kannst Du diese Informationen speichern.</p> ",
+ 'fields': {
+ 'TXT': "Feldname 1",
+ 'TXT': "Feldname 2",
+ 'TXT': "Feldname 3"
+ }
+ }
+},
+'recordFieldTypologies': {
+ 'TXT': {
+ 'description': "simple text field",
+ 'shortDescription': "Text"
+ },
+ 'PWD': {
+ 'description': "simple text field, with default status set to hidden",
+ 'shortDescription': "Passwort"
+ },
+ 'URL': {
+ 'description': "simple text field in edit mode, that became an active url in view mode",
+ 'shortDescription': "Webadresse"
+ },
+ 'DATE': {
+ 'description': "a value set with a calendar helper",
+ 'shortDescription': "Datum"
+ },
+ 'ADDR': {
+ 'description': "just like the URL, but the active link points to Google Maps (or similar service) passing the address value as argument",
+ 'shortDescription': "Postanschrift"
+ },
+ 'CHECK': {
+ 'description': "check description",
+ 'shortDescription': "check"
+ },
+ 'RADIO': {
+ 'description': "radio description",
+ 'shortDescription': "radio"
+ },
+ 'SELECT': {
+ 'description': "select description",
+ 'shortDescription': "select"
+ }
+},
+'newRecordPanelGeneralExceptionTitle': "Fehler",
+'newRecordPanelGeneralExceptionMessage': "Der Konfigurationstext ist nicht gültig. Stelle sicher, dass Du den Text des Bookmarket Pop-Up eingefügt hast und versuch es nocheinmal.",
+'newRecordPanelWrongBookmarkletVersionExceptionTitle': "Fehler",
+'newRecordPanelWrongBookmarkletVersionExceptionMessage': "Der Konfigurationstext wurde von einer älteren Version des Bookmarklets erstellt. Bitte aktualisiere Dein Bookmarklet und probiere es erneut.",
+'newRecordPanelExceptionPanelCloseButtonLabel': "Abbruch",
+'mainPanelDeletingRecordPanelConfirmationTitle': "Lösche ausgewählte Karte",
+'mainPanelDeleteRecordPanelConfirmationText': "Möschtest Du wirklich die ausgewählte Karte löschen?",
+'mainPanelDeleteRecordPanelConfirmButtonLabel': "Ja",
+'mainPanelDeleteRecordPanelDenyButtonLabel': "Nein",
+'mainPanelDeletingRecordPanelInitialTitle': "Lösche ausgewählte Karte",
+'mainPanelDeletingRecordPanelCompletedText': "Fertig",
+'deleteRecordPanelCollectRecordDataMessageTitle': "Karte löschen",
+'deleteRecordPanelCollectRecordDataMessageText': "Aktualisiere Kartenliste",
+'deleteRecordPanelEncryptUserDataMessageTitle': "Karte löschen",
+'deleteRecordPanelEncryptUserDataMessageText': "Lokale Verschlüsselung der Karten Kopfdaten",
+'deleteRecordPanelSendingDataToTheServerMessageTitle': "Karte löschen",
+'deleteRecordPanelSendingDataToTheServerMessageText': "Lade verschlüsselte Karten Kopfdaten zu Clipperz hoch",
+'deleteRecordPanelUpdatingTheInterfaceMessageTitle': "Karte löschen",
+'deleteRecordPanelUpdatingTheInterfaceMessageText': "Aktualisiere Benutzerschnittstelle",
+'recordDetailNoRecordSelectedTitle': "Keine Karte ausgewählt",
+'recordDetailNoRecordSelectedDescription': "<p>Bitte wähle aus der linken Liste eine Karte aus.</p> ",
+'recordDetailLoadingRecordMessage': "Lade verschlüsselte Karte von Clipperz runter",
+'recordDetailDecryptingRecordMessage': "Lokale entschlüsselung der Kartendaten",
+'recordDetailLoadingRecordVersionMessage': "Herunterladen der aktuellsten Kartenversion",
+'recordDetailDecryptingRecordVersionMessage': "Lokale Entschlüsselung der aktuellen Version",
+'recordDetailLoadingErrorMessageTitle': "Fehler beim Herunterladen der Karte",
+'recordDetailNotesLabel': "Notiz",
+'recordDetailLabelFieldColumnLabel': "Feld Namen",
+'recordDetailDataFieldColumnLabel': "Feld Daten",
+'recordDetailTypeFieldColumnLabel': "Art",
+'recordDetailSavingChangesMessagePanelInitialTitle': "Speichere Karte",
+'recordDetailAddFieldButtonLabel': "Neues Feld hinzufügen",
+'recordDetailDirectLoginBlockTitle': "Direkt Logins",
+'recordDetailNewDirectLoginDescription': "<p>Direkt Login Konfiguration</p> ",
+'recordDetailDirectLoginBlockNoDirectLoginConfiguredDescription': "<p>Enthält diese Karte Informationen um Zugriff auf ein Online Service zu erhalten?</p> <p>Verwende das Bookmarklet um ein “Direkt Login” mit nur einem Klick von Clipperz zu konfigurieren.</p> ",
+'recordDetailAddNewDirectLoginButtonLabel': "Neues Direktlogin hinzufügen",
+'recordDetailEditButtonLabel': "Bearbeiten",
+'recordDetailSaveButtonLabel': "Speichern",
+'recordDetailCancelButtonLabel': "Abbruch",
+'newRecordTitleLabel': "_neue Karte_",
+'newDirectLoginLabelSuffix': "",
+'recordSaveChangesPanelCollectRecordInfoMessageTitle': "Karte speichern",
+'recordSaveChangesPanelCollectRecordInfoMessageText': "Aktualisierung der Karten Kopfdaten",
+'recordSaveChangesPanelEncryptUserDataMessageTitle': "Karte speichern",
+'recordSaveChangesPanelEncryptUserDataMessageText': "Lokale Verschlüsselung der Karten Kopfdaten",
+'recordSaveChangesPanelEncryptRecordDataMessageTitle': "Karte speichern",
+'recordSaveChangesPanelEncryptRecordDataMessageText': "Lokale Verschlüsselung der Karten Informationen",
+'recordSaveChangesPanelEncryptRecordVersionDataMessageTitle': "Karte speichern",
+'recordSaveChangesPanelEncryptRecordVersionDataMessageText': "Lokale Verschlüsselung der Karten Versions Informationen",
+'recordSaveChangesPanelSendingDataToTheServerMessageTitle': "Karte speichern",
+'recordSaveChangesPanelSendingDataToTheServerMessageText': "Verschlüsselte Karten Kopfdaten auf Clipperz hochladen",
+'recordSaveChangesPanelUpdatingTheInterfaceMessageTitle': "Karte speichern",
+'recordSaveChangesPanelUpdatingTheInterfaceMessageText': "Aktualisierung der Benutzerschnittstelle",
+'exit': "<h2> <b>Auf Wiedersehen! Danke, dass Du Clipperz verwendet hast.</b> </h2> <ul> <li> <h3>Hinweis:</h3> <ul> <li> <p>Speichere diese Seite in Deine Favoriten, damit Du auch in Zukunft dich sicher mit Clipperz verbinden kannst (solltest Du dies nicht bereits getan haben)</p> </li> <li> <p>Clipperz wird Dir niemals eine E-Mail senden, weil wir Dich niemals nach Deiner E-Mail Anschrift gefragt haben (und dies auch nie werden) – öffne daher niemals eine Mail, die wvon Clipperz zu sein scheint</p> </li> </ul> </li> </ul> <p> </p> <p>In 10 Sekunden wirdst Du auf eine Seite von Wikipedia umgeleitet, wo Du über eine herausragende Sicherheitslücke informiert wirst.</p> ",
+//'DWRUtilLoadingMessage': "Lade Daten ...",
+'comingSoon': "In Kürze ...",
+'panelCollectingEntryopyMessageText': "Sammlung",
+'directLoginConfigurationCheckBoxFieldSelectedValue': "Ja",
+'directLoginConfigurationCheckBoxFieldNotSelectedValue': "Nein",
+
+__syntaxFix__: "syntax fix"
+});
diff --git a/frontend/beta/js/Clipperz/PM/Strings/Strings_el-GR.js b/frontend/beta/js/Clipperz/PM/Strings/Strings_el-GR.js
new file mode 100644
index 0000000..37e0a96
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Strings/Strings_el-GR.js
@@ -0,0 +1,701 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+//=============================================================================
+//
+// G R E E K (el_GR)
+//
+//=============================================================================
+
+Clipperz.PM.Strings.Languages['el-gr'] = MochiKit.Base.merge(Clipperz.PM.Strings.Languages['en-us'], {
+
+//-----------------------------------------------------
+// Login page - description
+ 'clipperzServiceDescriptionConfig': [
+ {tag:'h2', html:'Κρατήστε το για τον Εαυτό Σας'},
+ {tag:'ul', children:[
+ {tag:'li', children:[
+ {tag:'h3', html:'Το Clipperz είναι:'},
+ {tag:'ul', children:[
+ {tag:'li', children:[{tag:'span', html:'Ένας ασφαλής και απλός τρόπος διαχείρησης όλων των κωδικών πρόσβασης σας'}]},
+ {tag:'li', children:[{tag:'span', html:'Μια αποτελεσματική λύση πρόσβασης σε δεδομένα/εφαρμογές με μοναδικό κωδικό'}]},
+ {tag:'li', children:[{tag:'span', html:'Μια ψηφιακή θυρίδα για τα απόρρητα δεδομένα σας'}]}
+ ]}
+ ]},
+ {tag:'li', children:[
+ {tag:'h3', html:'Με το Clipperz μπορείτε:'},
+ {tag:'ul', children:[
+ {tag:'li', children:[{tag:'span', html:'Να αποθηκεύσετε και να διαχειριστείτε όλους τους κωδικούς πρόσβασης και τα online πιστοποιητικά/διαπιστευτήρια σας'}]},
+ {tag:'li', children:[{tag:'span', html:'Να έχετε πρόσβαση (login) στις υπηρεσίες διαδικτύου χωρίς την εισαγωγή oνομάτων λογαρισμών χρήστη (username),ή, κωδικών πρόσβασης (passwords)'}]},
+ {tag:'li', children:[{tag:'span', html:'Να προστατεύσετε όλα τα προσωπικά δεδομένα σας: κωδικούς συναγερμών, PINs, αριθμούς πιστωτικών καρτών, ...'}]},
+ {tag:'li', children:[{tag:'span', html:'Να μοιραστείτε δεδομένα με μέλη της οικογένεια σας και τους συνεργάτες σας (σύντομα στην διάθεση σας)'}]}
+ ]}
+ ]},
+ {tag:'li', children:[
+ {tag:'h3', html:'Τα πλεονεκτήματα του Clipperz είναι:'},
+ {tag:'ul', children:[
+ {tag:'li', children:[{tag:'span', html:'Είναι δωρεάν και προσφέρει πρόσβαση ανώνυμα'}]},
+ {tag:'li', children:[{tag:'span', html:'Μπορεί να χρησιμοποιηθεί οποαδήποτε ώρα και από οποιοδήποτε τερματικό'}]},
+ {tag:'li', children:[{tag:'span', html:'Δεν απαιτεί την φόρτωση και εγκατάσταση οποιουδήποτε λογισμικού'}]},
+ {tag:'li', children:[{tag:'span', html:'Αποφεύγετε την διατήριση απορρήτων στον υπολογιστή σας ή σε έντυπη μορφή'}]}
+ ]}
+ ]},
+ {tag:'li', children:[
+ {tag:'h3', html:'Η ασφάλεια που παρέχει το Clipperz:'},
+ {tag:'ul', children:[
+ {tag:'li', children:[{tag:'span', html:'Τα απόρρητα δεδομένα σας κωδικοποιούνται τοπικά από τον διακομιστή σας (browser) πρίν να φορτωθούν στο Clipperz'}]},
+ {tag:'li', children:[{tag:'span', html:'Το κλειδί της κωδικοποίησης είναι μία φράση-κωδικός γνωστή μόνο σε εσάς'}]},
+ {tag:'li', children:[{tag:'span', html:'Το Clipperz φυλάσσει τα προσωπικά σας δεδομένα σε κωδικοποιημένη μορφή, και δεν μπορεί να έχει πρόσβαση σε αυτά στην αρχική τους μορφή'}]},
+ {tag:'li', children:[{tag:'span', html:'Το Clipperz χρησιμοποιεί επίσημες /πρότυπες μεθόδους κωδικοποίησης, και όχι αόριστα και εφάνταστα μοντέλα'}]},
+ {tag:'li', children:[{tag:'span', html:'Έχετε πρόσβαση στον πηγαίο κώδικα οποτεδήποτε το θελήσετε, και δεν χρειάζετε να γνωρίζετε τίποτα από κρυπτογράφηση για να είστε ένας ευχαριστημένος χρήστης!'}]}
+ ]}
+ ]},
+ {tag:'li', children:[
+ {tag:'a', href:"http://www.clipperz.com", target:'_blank', html:'Μάθετε περισσότερα'}
+ ]}
+ ]}
+ ],
+
+// Login page - form
+ 'loginFormTitle': "Συνδεθείτε με τον Clipperz λογαριασμό σας",
+ 'loginFormUsernameLabel': "Όνομα χρήστη",
+ 'loginFormPassphraseLabel': "Κωδική φράση",
+ 'loginFormDontHaveAnAccountLabel': "Δεν έχετε δημιουργήσει λογαριασμό?",
+ 'loginFormCreateOneLabel': "Δημιουργήστε έναν",
+ 'loginFormForgotYourCredentialsLabel': "Ξεχάσατε τα διαπιστευτήριά σας?",
+ 'loginFormAarghThatsBadLabel': "Ααααργκ! Αυτό είναι κακό!",
+ 'loginFormAfraidOfMaliciousScriptsLabel': "φοβάστε κακόβουλα προγράμματα (scripts)?",
+ 'loginFormVerifyTheCodeLabel': "Επαληθεύστε τον κωδικό",
+ 'loginFormButtonLabel': "Σύνδεση",
+
+// Login page - language selection
+ 'loginPanelSwithLanguageDescriptionConfig': [
+ {tag:'h5', html:"Αλλάξτε στην γλώσσα προτήμησης σας"}
+ ],
+
+// Login page - browser compatibility
+ 'browserCompatibilityDescriptionConfig': [
+ {tag:'p', html:"Έχετε μία καλύτερη και πιό ασφαλή Clipperz εμπειρία χρησιμοποιόντας τον Firefox. Ωστόσο το Clipperz συνεργάζετε άψογα με Opera και MS Internet Explorer!"}
+ ],
+
+// Login message panel
+ 'loginMessagePanelInitialTitle': "Γίνεται σύνδεση ...",
+ 'loginMessagePanelInitialButtonLabel': "Ακύρωση",
+ 'loginMessagePanelConnectedTitle': "Συνδεθήκατε",
+ 'loginMessagePanelConnectedText': "Ολοκληρώθηκε",
+ 'loginMessagePanelFailureTitle': "Λάθος",
+ 'loginMessagePanelFailureText': "Η σύνδεση χρήστη απέτυχε",
+ 'loginMessagePanelFailureButtonLabel': "Κλείσιμο",
+
+// Login message panel - connection
+ 'connectionLoginSendingCredentialsMessageTitle': "Γίνεται επαλήθευση διαπιστευτηρίων",
+ 'connectionLoginSendingCredentialsMessageText': "Αποστέλλονται διαπιστευτήρια",
+ 'connectionLoginCredentialsVerificationMessageTitle': "Γίνεται επαλήθευση διαπιστευτηρίων",
+ 'connectionLoginCredentialsVerificationMessageText': "Εκτέλεση πιστοποίησης SRP ",
+ 'connectionLoginDoneMessageTitle': "Γίνεται επαλήθευση διαπιστευτηρίων",
+ 'connectionLoginDoneMessageText': "Συνδεδεμένος",
+
+// Login message panel - user
+ 'userLoginPanelUpgradingUserCredentialsMessageTitle': "Γίνεται επαλήθευση διαπιστευτηρίων",
+ 'userLoginPanelUpgradingUserCredentialsMessageText': "Αναβάθμηση των διαπιστευτηρίων σας σε ένα νέο σζήμα πιστοποίησης",
+ 'userLoginPanelConnectedMessageTitle': "Χρήστης πιστοποιήθηκε ",
+ 'userLoginPanelConnectedMessageText': "Συνδεθήκατε με επιτυχία",
+ 'userLoginPanelTryingAnOlderConnectionSchemaMessageTitle': "Γίνεται επαλήθευση διαπιστευτηρίων",
+ 'userLoginPanelTryingAnOlderConnectionSchemaMessageText': "Trying an older authentication schema",
+ 'userLoginPanelLoadingUserDataMessageTitle': "Χρήστης πιστοποιήθηκε ",
+ 'userLoginPanelLoadingUserDataMessageText': "Downloading encrypted card headers from Clipperz",
+ 'userLoginPanelDecryptingUserDataMessageTitle': "Χρήστης πιστοποιήθηκε ",
+ 'userLoginPanelDecryptingUserDataMessageText': "Local decryption of card headers",
+ 'userLoginPanelDecryptingUserStatisticsMessageTitle': "Χρήστης πιστοποιήθηκε ",
+ 'userLoginPanelDecryptingUserStatisticsMessageText': "Local decryption of usage statistics",
+
+//-----------------------------------------------------
+// Registration page - splash alert
+ 'splashAlertTitle': "Καλώς ήλθατε στο Clipperz!",
+ 'splashAlertTextConfig': [
+ {tag:'p', html:'Μερικές συμβουλές ασφαλείας'},
+ {tag:'ul', children:[
+ {tag:'li', children:[{tag:'span', html:'Η αποθήκευση των δεδομένων σας στο Clipperz είναι τόσο ασφαλής, όσο η κωδική φράση που επιλέγετε για να τα προστατεύσετε. Κανένας δεν θα έχει πρόσβαση σε αυτά, εκτός αν γνωρίζει την κωδική φράση σας.'}]},
+ {tag:'li', children:[{tag:'span', html:'Αν πρόκειται να χρησιμοποιήσετε το Clipperz για ασφαλή προστασία ευαίσθητων ή σημαντικών πληροφοριών, βεβαιωθείτε ότι θα χρησιμοποιήσετε μία “γερή” κωδική φράση. Όσο μεγαλύτερη, τόσο καλύτερη!'}]},
+ {tag:'li', children:[{tag:'span', html:'Το Clipperz δεν θα έχει τη δυνατότητα να ανακτήσει μία χαμένη κωδική φράση!'}]}
+ ]},
+ {tag:'p', html:'Για περισσότερες πληροφορίες, παρακαλώ ανατρέξτε στο <a href=\"http://www.clipperz.com\" target=\"_blank\">Clipperz</a>.'}
+ ],
+ 'splashAlertCloseButtonLabel': "Εντάξει",
+
+// Registration page - form
+ 'registrationFormTitle': "Δημιουργήστε λογαριασμό",
+ 'registrationFormUsernameLabel': "Όνομα χρήστη",
+ 'registrationFormPassphraseLabel': "Κωδική φράση",
+ 'registrationFormRetypePassphraseLabel': "Εισάγετε ξανά την κωδική φράση",
+ 'registrationFormSafetyCheckLabel': "Κατανοώ πως το Clipperz δεν θα μπορεί να ανακτήσει μία χαμένη κωδική φράση.",
+ 'registrationFormTermsOfServiceCheckLabel': "Έχω διαβάσει και αποδέχομαι τους Όρους Χρήσης <a href='http://www.clipperz.com/terms_of_service' target='_blank'>Όρους Χρήσης</a>.",
+ 'registrationFormDoYouAlreadyHaveAnAccountLabel': "Έχετε ήδη έναν λογαριασμό?",
+ 'registrationFormSimplyLoginLabel': "απλώς συνδεθείτε",
+ 'registrationFormButtonLabel': "Εγγραφείτε",
+
+// Registration page - warning messages
+ 'registrationFormWarningMessageNotMatchingPassphrases': "Οι κωδικές φράσεις που εισάγατε δεν ταιριάζουν. Παρακαλώ ξαναπροσπαθήστε.",
+ 'registrationFormWarningMessageSafetyCheckNotSelected': "Παρακαλώ διαβάστε και επιλέξτε όλες τις παρακάτω επιλογές.",
+ 'registrationFormWarningMessageTermsOfServiceCheckNotSelected': "Πρέπει να αποδεχθείτε τους Όρους Χρήσης.",
+
+// Registration message panel
+ 'registrationMessagePanelInitialTitle': "Δημιουργία λογαριασμού ...",
+ 'registrationMessagePanelInitialButtonLabel': "Ακύρωση",
+ 'registrationMessagePanelRegistrationDoneTitle': "Εγγραφή",
+ 'registrationMessagePanelRegistrationDoneText': "Ολοκληρώθηκε",
+ 'registrationMessagePanelFailureTitle': "Η εγγραφή απέτυχε",
+ 'registrationMessagePanelFailureButtonLabel': "Κλείσιμο",
+
+// Registration - connection
+ 'connectionRegistrationSendingRequestMessageText': "Γίνεται επαλήθευση διαπιστευτηρίων",
+ 'connectionRegistrationSendingCredentialsMessageText': "Αποστέλλονται διαπιστευτήρια",
+
+//-----------------------------------------------------
+// Registration splash panel
+ 'registrationSplashPanelTitle': "Συμβουλές Ασφαλείας",
+ 'registrationSplashPanelDescriptionConfig': [
+ {tag:'p', html:'Αυτά είναι τα διαπιστευτήριά σας στο Clipperz, δείτε τα προσεκτικά. Το Clipperz δεν θα απεικονίσει το όνομα χρήστη και την κωδική σας φράση δεύτερη φορά!'}
+ ],
+ 'registrationSplashPanelUsernameLabel': "όνομα χρήστη",
+ 'registrationSplashPanelPassphraseLabel': "κωδική φράση",
+
+//-----------------------------------------------------
+// Header links
+ 'donateHeaderLinkLabel': "donate",
+ 'creditsHeaderLinkLabel': "credits",
+ 'feedbackHeaderLinkLabel': "feedback",
+ 'helpHeaderLinkLabel': "Βοήθεια",
+ 'forumHeaderLinkLabel': "forum",
+
+//-----------------------------------------------------
+// Menu labels
+ 'recordMenuLabel': "cards",
+ 'accountMenuLabel': "Λογαριασμός",
+ 'dataMenuLabel': "Δεδομένα",
+ 'contactsMenuLabel': "Επαφές",
+ 'bookmarkletMenuLabel': "bookmarklet",
+ 'logoutMenuLabel': "Αποσύνδεση",
+ 'lockMenuLabel': "lock",
+
+//-----------------------------------------------------
+// Lock dialog
+ 'lockTitle': "The account is locked",
+ 'lockDescriptionConfig': [
+ {tag:'p', html:'To unlock your account, please insert your passphrase'}
+ ],
+ 'unlockButtonLabel': "Unlock",
+
+//-----------------------------------------------------
+// Account panel - change passphrase
+ 'changePasswordTabLabel': "Αλλάξτε την κωδική φράση σας",
+ 'changePasswordTabTitle': "Αλλάξτε την κωδική φράση σας",
+
+// Account panel - change passphrase - form
+ 'changePasswordFormUsernameLabel': "όνομα χρήστη",
+ 'changePasswordFormOldPassphraseLabel': "παλαιά κωδική φράση",
+ 'changePasswordFormNewPassphraseLabel': "νέα κωδική φράση",
+ 'changePasswordFormRetypePassphraseLabel': "Εισάγετε ξανά τη νέα κωδική φράση",
+ 'changePasswordFormSafetyCheckboxLabel': "Κατανοώ πως το Clipperz δεν θα μπορεί να ανακτήσει μία χαμένη κωδική φράση.",
+ 'changePasswordFormSubmitLabel': "Αλλάξτε την κωδική φράση σας",
+
+// Account panel - change passphrase - warnings
+ 'changePasswordFormWrongUsernameWarning': "Λάθος όνομα χρήστη",
+ 'changePasswordFormWrongPassphraseWarning': "Λάθος κωδική φράση",
+ 'changePasswordFormWrongRetypePassphraseWarning': "Οι κωδικές φράσεις που εισάγατε δεν ταιριάζουν. Παρακαλώ ξαναπροσπαθήστε.",
+ 'changePasswordFormSafetyCheckWarning': "Παρακαλώ διαβάστε και επιλέξτε όλες τις παρακάτω επιλογές.",
+
+// Account panel - change passphrase - progress dialog
+ 'changePasswordFormProgressDialogTitle': "Γίνεται αλλαγή διαπιστευτηρίων χρήστη",
+ 'changePasswordFormProgressDialogConnectedMessageTitle': "Συνδεδεμένος",
+ 'changePasswordFormProgressDialogConnectedMessageText': "Ολοκληρώθηκε",
+ 'changePasswordFormProgressDialogErrorMessageTitle': "Σφάλμα",
+ 'changePasswordFormProgressDialogErrorMessageText': "Απέτυχε η αλλαγή διαπιστευτηρίων!",
+
+ 'changeCredentialsPanelEncryptingDataMessageTitle': "Γίνεται αλλαγή της κωδικής φράσης σας",
+ 'changeCredentialsPanelEncryptingDataMessageText': "Local encryption of card headers",
+ 'changeCredentialsPanelCreatingNewCredentialsMessageTitle': "Γίνεται αλλαγή της κωδικής φράσης σας",
+ 'changeCredentialsPanelCreatingNewCredentialsMessageText': "Γίνεται ανανέωση των διαπιστευτηρίων σας",
+ 'changeCredentialsPanelSendingNewCredentialsToTheServerMessageTitle': "Γίνεται αλλαγή της κωδικής φράσης σας",
+ 'changeCredentialsPanelSendingNewCredentialsToTheServerMessageText': "Uploading your encrypted credentials to Clipperz",
+ 'changeCredentialsPanelDoneMessageTitle': "Γίνεται αλλαγή της κωδικής φράσης σας",
+ 'changeCredentialsPanelDoneMessageText': "Ολοκληρώθηκε",
+
+//-----------------------------------------------------
+// Account panel - manage OTP
+ 'manageOTPTabLabel': "Manage your one-time passphrases",
+ 'manageOTPTabTitle': "Manage your one-time passphrases",
+
+// Account panel - manage OTP - description
+ 'manageOTPTabDescriptionConfig': [
+ {tag:'p', html:"A one-time passphrase works like your regular passphrase, but can be used only once."},
+ {tag:'p', html:"If the same passphrase is used again at a later stage in a login attempt it will be rejected and the login process will fail."},
+ {tag:'p', html:"Immediately after a successful login, your one-time passphrase will be deleted preventing any fraudulent access."},
+ {tag:'p', html:"One-time passwords are an excellent choice if one is concerned about keyloggers or spyware infections that may be collecting data from compromised machines."},
+ {tag:'p', html:"<b>It's strongly advisable to use one-time passphrases when accessing Clipperz from public terminals, such as Internet cafes and libraries.</b>"},
+ {tag:'p', html:""},
+ {tag:'p', html:"<b>Coming soon ...</b>"}
+ ],
+
+//-----------------------------------------------------
+// Account panel - user preferences
+ 'accountPreferencesLabel': "Προτιμήσεις",
+ 'accountPreferencesTabTitle': "Προτιμήσεις",
+
+// Account panel - user preferences - description
+ 'accountPreferencesLanguageTitle': "Επιλογή Γλώσσας",
+ 'accountPreferencesLanguageDescriptionConfig': [
+ {tag:'p', html:"Choose your preferred language from the list below."}
+ ],
+
+ 'accountPreferencesInterfaceTitle': "Interface customization",
+ 'accountPreferencesInterfaceDescriptionConfig': [
+ {tag:'p', html:"Tune the Clipperz interface to your needs."}
+ ],
+
+// Account panel - user preferences - form
+ 'saveUserPreferencesFormSubmitLabel': "Αποθήκευση",
+ 'cancelUserPreferencesFormSubmitLabel': "Ακύρωση",
+
+// Account panel - user preferences - panel
+ 'accountPreferencesSavingPanelTitle_Step1': "Saving preferences",
+ 'accountPreferencesSavingPanelText_Step1': "Local encryption of your preferences",
+ 'accountPreferencesSavingPanelTitle_Step2': "Saving preferences",
+ 'accountPreferencesSavingPanelText_Step2': "Sending encrypted preferences to Clipperz",
+
+//-----------------------------------------------------
+// Account panel - delete account
+ 'deleteAccountTabLabel': "Διαγράψτε τον λογαριασμό σας",
+ 'deleteAccountTabTitle': "Γίνεται διαγραφή του λογαριασμού σας",
+
+// Account panel - delete account - form
+ 'deleteAccountFormUsernameLabel': "όνομα χρήστη",
+ 'deleteAccountFormPassphraseLabel': "κωδική φράση",
+ 'deleteAccountFormSafetyCheckboxLabel': "Κατανοώ πως όλα τα δεδομένα μου θα διαγραφούν και πως αυτή η πράξη είναι μη αναστρέψιμη.",
+ 'deleteAccountFormSubmitLabel': "Διαγράψτε τον λογαριασμό μου",
+
+// Account panel - delete account - warnings
+ 'deleteAccountFormWrongUsernameWarning': "λάθος όνομα χρήστη",
+ 'deleteAccountFormWrongPassphraseWarning': "λάθος κωδική φράση",
+ 'deleteAccountFormSafetyCheckWarning': "Παρακαλώ διαβάστε και επιλέξτε την παρακάτω επιλογή.",
+
+// Account panel - delete account - confirmation
+ 'accountPanelDeletingAccountPanelConfirmationTitle': "ΠΡΟΣΟΧΗ",
+ 'accountPanelDeleteAccountPanelConfirmationText': "Είστε σίγουρος/η ότι θέλετε να διαγράψετε αυτόν τον λογαριασμό?",
+ 'accountPanelDeleteAccountPanelConfirmButtonLabel': "Ναι",
+ 'accountPanelDeleteAccountPanelDenyButtonLabel': "Όχι",
+
+//-----------------------------------------------------
+// Data panel - offline copy
+ 'offlineCopyTabLabel': "Offline copy",
+ 'offlineCopyTabTitle': "Offline copy",
+
+// Data panel - offline copy - description
+ 'offlineCopyTabDescriptionConfig': [
+ {tag:'p', html:"With just one click you can dump all your encrypted data from Clipperz servers to your hard disk and create a read-only offline version of Clipperz to be used when you are not connected to the Internet."},
+ {tag:'p', html:"The read-only version is as secure as the read-and-write one and will not expose your data to higher risks since they both share the same code and security architecture."},
+ {tag:'ol', children:[
+ {tag:'li', children:[{tag:'span', html:"Click the link below to download the offline copy."}]},
+ {tag:'li', children:[{tag:'span', html:"The browser will ask you what to do with the “Clipperz_YYYYMMDD.zip” file. Save it on your hard disk."}]},
+ {tag:'li', children:[{tag:'span', html:"Unzip the file to reveal the “Clipperz_YYYYMMDD” folder."}]},
+ {tag:'li', children:[{tag:'span', html:"Open the “Clipperz_YYYYMMDD” folder and double click on the “index.html” file."}]},
+ {tag:'li', children:[{tag:'span', html:"Enter the usual username and passphrase and access your private data without an Internet connection."}]}
+ ]}
+ ],
+ 'offlineCopyDownloadLinkLabel': "Download",
+
+//-----------------------------------------------------
+// Data panel - sharing
+ 'sharingTabLabel': "Sharing",
+ 'sharingTabTitle': "Sharing",
+
+// Data panel - sharing - description
+ 'sharingTabDescriptionConfig': [
+ {tag:'p', html:"Quite often a confidential piece of information needs to be shared with one or more persons."},
+ {tag:'p', html:"This could be as simple as giving your colleague the access code of your voice mailbox when you are out of the office, or as complicated as enabling the entitled heirs to access your safe deposit box at the local bank when you pass on."},
+ {tag:'p', html:"Clipperz can make sharing your secrets a secure and straightforward process."},
+ {tag:'p', html:""},
+ {tag:'p', html:"<b>Coming soon ...</b>"}
+ ],
+
+//-----------------------------------------------------
+// Data panel - import
+ 'importTabLabel': "Εισαγωγή",
+ 'importTabTitle': "Εισαγωγή",
+
+// Data panel - import - description
+ 'importTabDescriptionConfig': [
+ {tag:'p', html:"<b>Σύντομα κοντά σας ...</b>"}
+ ],
+
+//-----------------------------------------------------
+// Data panel - export
+ 'printingTabLabel': "Εξαγωγή",
+ 'printingTabTitle': "Εξαγωγή",
+
+// Data panel - export - description “”
+ 'printingTabDescriptionConfig': [
+ {tag:'p', html:"<b>Print your data</b>"},
+ {tag:'p', html:"Clicking on the link below will open a new window displaying all your cards in a printable format."},
+ {tag:'p', html:"If you are going to print for backup purposes, please consider the more safe option provided by the creating an “offline copy”."}
+ ],
+ 'printingLinkLabel': "Έκδοση Εκτύπωσης",
+
+//-------------------------------------------------------------------
+// Contacts panel
+ 'contactsTabLabel': "Contacts",
+ 'contactsTabTitle': "Contacts",
+
+//-------------------------------------------------------------------
+// Bookmarklet panel
+ 'bookmarkletTabLabel': "Bookmarklet",
+ 'bookmarkletTabTitle': "Bookmarklet",
+
+// Bookmarklet panel - description
+ 'bookmarkletTabDescriptionConfig': [
+ {tag:'p', html:"A bookmarklet is a simple “one-click” tool that can perform very useful tasks. It can be saved and used like a normal web page bookmark."},
+ {tag:'p', html:"The Clipperz bookmarklet will help you to quickly create new cards and new “direct logins” within existing cards."},
+ {tag:'p', html:"<b>Please note that the bookmarklet does not include any information related to your account (e.g. your username or passphrase), the bookmarklet is a general tool containing the same code for every Clipperz user.</b>"},
+ {tag:'div', children:[
+ {tag:'p', html:"To install the bookmarklet <b>drag</b> the link below to the bookmark bar of your browser."}
+ ]}
+ ],
+ 'bookmarkletTabBookmarkletTitle': "Προσθήκη στο Clipperz",
+
+// Bookmarklet panel - instructions
+ 'bookmarkletTabInstructionsConfig': [
+ {tag:'h3', html:"How to create a new card inclusive of a “direct login” link to an online service"},
+ {tag:'ol', children:[
+ {tag:'li', children:[{tag:'span', html:"Open the web page where the login form is hosted. (this is the page where you usually enter your sign-in credentials)"}]},
+ {tag:'li', children:[{tag:'span', html:"Launch the bookmarklet by clicking on it: a pop-up window will appear over the web page."}]},
+ {tag:'li', children:[{tag:'span', html:"Copy to the clipboard the content of the large text area within the pop-up. (ctrl-C)"}]},
+ {tag:'li', children:[{tag:'span', html:"Enter your Clipperz account and click on the <b>Add new card</b> button."}]},
+ {tag:'li', children:[{tag:'span', html:"Select the “Direct login” template and paste the content of the clipboard to the large text area in the form. (ctrl-V)"}]},
+ {tag:'li', children:[{tag:'span', html:"Press the <b>Create</b> button, complete and review the details, then click <b>Save</b>."}]}
+ ]},
+ {tag:'h3', html:"How to add a “direct login” link to an existing card"},
+ {tag:'ol', children:[
+ {tag:'li', children:[{tag:'span', html:"Same as above."}]},
+ {tag:'li', children:[{tag:'span', html:"Same as above."}]},
+ {tag:'li', children:[{tag:'span', html:"Same as above."}]},
+ {tag:'li', children:[{tag:'span', html:"Enter your Clipperz account and select the card containing the credentials for the web service you just visited and click the <b>Edit</b> button."}]},
+ {tag:'li', children:[{tag:'span', html:"Paste the content of the clipboard to the large text area in the “Direct logins” section. (ctrl-V)"}]},
+ {tag:'li', children:[{tag:'span', html:"Press the <b>Add direct login</b> button, review the details and then click <b>Save</b>."}]}
+ ]},
+ {tag:'p', html:""},
+ {tag:'p', html:"Further information about the bookmarklet are <a href=\"http://www.clipperz.com/support/user_guide/bookmarklet\" target=\"_blank\">available here</a>."}
+ ],
+
+//-------------------------------------------------------------------
+// Direct logins block
+ 'mainPanelDirectLoginBlockLabel': "Απευθείας σύνδεση",
+ 'directLinkReferenceShowButtonLabel': "Επίδειξη",
+
+// Direct logins - blank slate “”
+ 'mainPanelDirectLoginBlockDescriptionConfig': [
+ {tag:'p', html:"Add “direct logins” to sign in to your web accounts without typing usernames and passwords!"},
+ {tag:'p', html:"“Direct logins” greatly enhance your password security since you can:"},
+ {tag:'ul', children:[
+ {tag:'li', children:[{tag:'span', html:"conveniently adopt and enter complex passwords;"}]},
+ {tag:'li', children:[{tag:'span', html:"never re-use the same and easy-to-guess password."}]}
+ ]},
+ {tag:'p', html:"Simple and quick configuration with the Clipperz <b>bookmarklet</b>."},
+ {tag:'a', href:"http://www.clipperz.com/support/user_guide/direct_logins", target:'_blank', html:'Learn more about “direct logins”'}
+ ],
+
+//-------------------------------------------------------------------
+// Cards block
+ 'mainPanelRecordsBlockLabel': "Κάρτες",
+ 'mainPanelAddRecordButtonLabel': "Προσθήκη νέας Κάρτας ",
+ 'mainPanelRemoveRecordButtonLabel': "Διαγραφή κάρτας",
+
+// Cards block - filter tabs
+ 'mainPanelRecordFilterBlockAllLabel': "Όλα",
+ 'mainPanelRecordFilterBlockTagsLabel': "Επιλογές",
+ 'mainPanelRecordFilterBlockSearchLabel': "Αναζήτηση",
+
+// Cards block - blank slate
+ 'recordDetailNoRecordAtAllTitle': "Welcome to Clipperz!",
+ 'recordDetailNoRecordAtAllDescriptionConfig': [
+ {tag:'h5', html:'Get started by adding cards to your account.'},
+ {tag:'p', html:'Cards are simple and flexible forms where you can store your passwords and any other confidential data.'},
+ {tag:'p', html:'Cards could contain credentials for accessing a web site, the combination of your bicycle lock, details of your credit card, ...'},
+ {tag:'h5', html:'Don\'t forget the bookmarklet!'},
+ {tag:'p', html:'Before you start, install the “Add to Clipperz” bookmarklet: it will make creating cards easier and more fun.'},
+ {tag:'p', html:'Go to the bookmarklet tab to discover how to install it and how it use it.'},
+ {tag:'p', html:''},
+ {tag:'p', html:'Then simply click the <b>"Add new card"</b> button and enjoy your Clipperz account.'},
+ {tag:'p', html:''},
+ {tag:'a', href:"http://www.clipperz.com/support/user_guide/managing_cards", target:'_blank', html:'Learn more about creating and managing cards'}
+ ],
+
+// Cards block - new card wizard - bookmarklet configuration
+ 'newRecordWizardTitleBoxConfig': [
+ {tag:'h5', html:"Please select a template"},
+ {tag:'p', html:'Cards are simple and flexible forms where you can store passwords or any other confidential data.'},
+ {tag:'p', html:'Start choosing one of the template below. You can always customize your cards later by adding or removing fields.'}
+ ],
+
+ 'newRecordWizardBookmarkletConfigurationTitle': "Απευθείας σύνδεση",
+ 'newRecordWizardBookmarkletConfigurationDescriptionConfig': [
+ {tag:'p', html:"Paste below the configuration code generated by the Clipperz bookmarklet."},
+ {tag:'p', html:"A new card complete with a direct login to your web account will be created."}
+ ],
+
+ 'newRecordWizardCreateButtonLabel': "Δημιουργία",
+ 'newRecordWizardCancelButtonLabel': "Ακύρωση",
+
+//-------------------------------------------------------------------
+// Card templates
+//-------------------------------------------------------------------
+
+ 'recordTemplates': {
+
+// Web password
+ 'WebAccount': {
+ 'title': "Web password",
+ 'description': [
+ {tag:'p', html:"A simple card to store login credentials for your online services."}
+ ],
+ 'fields': [
+ {label:"Διεύθυνση δικτύου", type:'URL'},
+ {label:"Χρήστης ή διεύθυνση ηλεκτρονικού ταχυδρομείου", type:'TXT'},
+ {label:"Κωδικός Πράσβασης", type:'PWD'}
+ ]
+ },
+
+// Bank account
+ 'BankAccount': {
+ 'title': "Bank account",
+ 'description': [
+ {tag:'p', html:"Safely store your bank account number and online banking credentials."}
+ ],
+ 'fields': [
+ {label:"Τράπεζα", type:'TXT'},
+ {label:"Αριθμός λογαριασμού", type:'TXT'},
+ {label:"Ιστοσελίδα τράπεζας", type:'URL'},
+ {label:"Αρ. Ηλεκτρονικής τράπεζας (ID)", type:'TXT'},
+ {label:"Κώδικος Ηλεκτρονικής τράπεζας", type:'PWD'}
+ ]
+ },
+
+// Credit card
+ 'CreditCard': {
+ 'title': "Credit card",
+ 'description': [
+ {tag:'p', html:"Card number, expire date, CVV2 and PIN always at hand with Clipperz."}
+ ],
+ 'fields': [
+ {label:"Τύπος Κάρτας (Visa, AmEx,...)", type:'TXT'},
+ {label:"Αριθμός κάρτα", type:'TXT'},
+ {label:"Ονοματεπώνυμο κατόχου", type:'TXT'},
+ {label:"Ημερομηνία λήξης", type:'TXT'},
+ {label:"CVV2", type:'TXT'},
+ {label:"Κωδικός Αυτόματης ταμείακης μηχανης (ΑΤΜ)", type:'PWD'},
+ {label:"Ιστοσελίδα κάρτας", type:'URL'},
+ {label:"Χρήστης", type:'TXT'},
+ {label:"Κωδικός Πρόσβασης", type:'PWD'}
+ ]
+ },
+
+// Address book entry
+ 'AddressBookEntry': {
+ 'title': "Address book entry",
+ 'description': [
+ {tag:'p', html:"Clipperz could also work as your new private address book. Use this template to easily add a new entry."}
+ ],
+ 'fields': [
+ {label:"Όνομα", type:'TXT'},
+ {label:"Ηλετρονικό ταχυδρομείο", type:'TXT'},
+ {label:"Τηλέφωνο", type:'TXT'},
+ {label:"Κινητο τηλέφωνο", type:'TXT'},
+ {label:"Διεύθυνση", type:'ADDR'},
+ ]
+ },
+
+// Custom card
+ 'Custom': {
+ 'title': "Custom card",
+ 'description': [
+ {tag:'p', html:"No matter which kind of confidential data you need to protect, create a custom card to match your needs."}
+ ],
+ 'fields': [
+ {label:"Περιγραφή 1", type:'TXT'},
+ {label:"Περιγραφή 2", type:'TXT'},
+ {label:"Περιγραφή 3", type:'TXT'}
+ ]
+ }
+ },
+
+
+ 'recordFieldTypologies': {
+ 'TXT': {
+ description: 'simple text field',
+ shortDescription: '΄Κείμενο'
+ },
+ 'PWD': {
+ description: 'simple text field, with default status set to hidden',
+ shortDescription: 'Κωδικός Πρόσβασης'
+ },
+ 'URL': {
+ description: 'simple text field in edit mode, that became an active url in view mode',
+ shortDescription: 'Διεύθυνση ηλεκτρονικού ταχυδρομείου'
+ },
+ 'DATE': {
+ description: 'a value set with a calendar helper',
+ shortDescription: 'Ημερομηνία'
+ },
+ 'ADDR': {
+ description: 'just like the URL, but the active link points to Google Maps (or similar service) passing the address value as argument',
+ shortDescription: 'Διεύθυνση'
+ },
+ 'CHECK': {
+ description: 'check description',
+ shortDescription: 'check'
+ },
+ 'RADIO': {
+ description: 'radio description',
+ shortDescription: 'radio'
+ },
+ 'SELECT': {
+ description: 'select description',
+ shortDescription: 'select'
+ }
+ },
+
+// Cards block - new card - warnings
+ 'newRecordPanelGeneralExceptionTitle': "Σφάλμα",
+ 'newRecordPanelGeneralExceptionMessage': "The configuration text is not valid. Make sure to get your text from the bookmarklet pop-up and retry.",
+ 'newRecordPanelWrongBookmarkletVersionExceptionTitle': "Σφάλμα",
+ 'newRecordPanelWrongBookmarkletVersionExceptionMessage': "The configuration text has been generated by an old version of the bookmarklet. Please update your bookmarklet and retry.",
+ 'newRecordPanelExceptionPanelCloseButtonLabel': "Ακύρωση",
+
+// Cards block - delete card
+ 'mainPanelDeletingRecordPanelConfirmationTitle': "Διαγραφή επιλεγμένης κάρτας",
+ 'mainPanelDeleteRecordPanelConfirmationText': "Είστε σίγουρος ότι θέλετε να διαγράψετε την επιλεγμένη κάρτα?",
+ 'mainPanelDeleteRecordPanelConfirmButtonLabel': "Ναι",
+ 'mainPanelDeleteRecordPanelDenyButtonLabel': "Όχι",
+ 'mainPanelDeletingRecordPanelInitialTitle': "Διαγραφή επιλεγμένης κάρτας ",
+ 'mainPanelDeletingRecordPanelCompletedText': "Ολοκλήρωση",
+
+// Cards block - delete card panel
+ 'deleteRecordPanelCollectRecordDataMessageTitle': "Διαγραφή κάρτας",
+ 'deleteRecordPanelCollectRecordDataMessageText': "Φόρτωση λίστα κάρτας",
+ 'deleteRecordPanelEncryptUserDataMessageTitle': "Διαγραφή κάρτας",
+ 'deleteRecordPanelEncryptUserDataMessageText': "Local encryption of card headers",
+ 'deleteRecordPanelSendingDataToTheServerMessageTitle': "Διαγραφή κάρτας",
+ 'deleteRecordPanelSendingDataToTheServerMessageText': "Uploading encrypted card headers to Clipperz",
+ 'deleteRecordPanelUpdatingTheInterfaceMessageTitle': "Διαγραφή κάρτας",
+ 'deleteRecordPanelUpdatingTheInterfaceMessageText': "Φόρτωση επιφάνειας",
+
+// Cards block - no record selected
+ 'recordDetailNoRecordSelectedTitle': "Δεν έχει επιλεγεί κάποια κάρτα",
+ 'recordDetailNoRecordSelectedDescriptionConfig': [
+ {tag:'p', html:'Παρακαλώ επιλέξτε μια κάρτα από αυτές που βρίσκονται στα αριστερά σας'}
+ ],
+
+// Cards block - loading messages
+ 'recordDetailLoadingRecordMessage': "Downloading encrypted card from Clipperz",
+ 'recordDetailDecryptingRecordMessage': "Τοπικη αποκωδικοποίηση αρχείων κάρτας",
+ 'recordDetailLoadingRecordVersionMessage': "Φόρτωση τελευταίας έκδοσης κάρτας",
+ 'recordDetailDecryptingRecordVersionMessage': "Τοπική αποκωδικοποίηση της τελευταίας έκδοσης",
+ 'recordDetailLoadingErrorMessageTitle': "Σφάλμα στη φόρτωση της κάρτας",
+
+// Cards block - card details
+ 'recordDetailNotesLabel': "Σημειώσης",
+ 'recordDetailLabelFieldColumnLabel': "Περιγραφή πεδίου",
+ 'recordDetailDataFieldColumnLabel': "Στοιχεία πεδίου",
+ 'recordDetailTypeFieldColumnLabel': "Τύπος",
+
+ 'recordDetailSavingChangesMessagePanelInitialTitle': "Αποθήκευση κάρτας",
+
+ 'recordDetailAddFieldButtonLabel': "Προσθέστε νέο πεδίο",
+ 'recordDetailPasswordFieldHelpLabel': "Για αντιγραφή του κωδικού στο clipboard επιλέξτε τα αστεράκια και μετα Ctrl-C",
+
+ 'recordDetailDirectLoginBlockTitle': "Κωδικός Πρόσβασης",
+ 'recordDetailNewDirectLoginDescriptionConfig': [
+ {tag:'p', html:'Επικύρωση κωδικου πρόσβασης'}
+ ],
+
+ 'recordDetailDirectLoginBlockNoDirectLoginConfiguredDescriptionConfig': [
+ {tag:'p', html:"Does this card contain credentials to access an online service?"},
+ {tag:'p', html:"Use the bookmarklet to configure a “direct login” from Clipperz with just one click!"}
+ ],
+ 'recordDetailAddNewDirectLoginButtonLabel': "Προσθέστε νέο κωδικό πρόσβασης",
+
+ 'recordDetailEditButtonLabel': "Edit",
+ 'recordDetailSaveButtonLabel': "Αποθήκευση",
+ 'recordDetailCancelButtonLabel': "Ακύρωση",
+
+ 'newRecordTitleLabel': "_Νέα κάρτα_",
+
+// Cards block - save card panel
+ 'recordSaveChangesPanelCollectRecordInfoMessageTitle': "Αποθήκευση κάρτας",
+ 'recordSaveChangesPanelCollectRecordInfoMessageText': "Updating card headers",
+ 'recordSaveChangesPanelEncryptUserDataMessageTitle': "Αποθήκευση κάρτας",
+ 'recordSaveChangesPanelEncryptUserDataMessageText': "Local encryption of card headers",
+ 'recordSaveChangesPanelEncryptRecordDataMessageTitle': "Αποθήκευση κάρτας",
+ 'recordSaveChangesPanelEncryptRecordDataMessageText': "Local encryption of card's data",
+ 'recordSaveChangesPanelEncryptRecordVersionDataMessageTitle': "Αποθήκευση κάρτας",
+ 'recordSaveChangesPanelEncryptRecordVersionDataMessageText': "Local encryption of card's version data",
+ 'recordSaveChangesPanelSendingDataToTheServerMessageTitle': "Αποθήκευση κάρτας",
+ 'recordSaveChangesPanelSendingDataToTheServerMessageText': "Uploading encrypted card's header to Clipperz",
+ 'recordSaveChangesPanelUpdatingTheInterfaceMessageTitle': "Αποθήκευση κάρτας",
+ 'recordSaveChangesPanelUpdatingTheInterfaceMessageText': "Φόρτωση επιφάνειας",
+
+// Exit page
+ 'exitConfig': [
+ {tag:'h2', html:'<b>Goodbye! Thanks for using Clipperz.</b>'},
+
+ {tag:'ul', children:[
+ {tag:'li', children:[
+ {tag:'h3', html:'Remember:'},
+ {tag:'ul', children:[
+ {tag:'li', children:[{tag:'span', html:'Bookmark this page to safely connect to Clipperz in the future (if you haven\'t already done it)'}]},
+ {tag:'li', children:[{tag:'span', html:'Clipperz will never send you an email, because we never asked your email address (and we never will), so never open an email that says it\'s from Clipperz'}]}
+ ]}
+ ]}
+ ]},
+ {tag:'p', html:""},
+ {tag:'p', html:"In 10 seconds you will be redirected to a Wikipedia page where you can read about a major security issue ..."}
+ ],
+
+//-------------------------------------------------------------------
+// Miscellaneous strings
+//-------------------------------------------------------------------
+
+// 'DWRUtilLoadingMessage': "Φόρτωση δεδομένων ...",
+ 'comingSoon': "Σύντομα κοντά σας ...",
+ 'panelCollectingEntryopyMessageText': "Collecting entropy",
+ 'directLoginConfigurationCheckBoxFieldSelectedValue': "Ναι",
+ 'directLoginConfigurationCheckBoxFieldNotSelectedValue': "Όχι",
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+});
+
diff --git a/frontend/beta/js/Clipperz/PM/Strings/Strings_en-CA.js b/frontend/beta/js/Clipperz/PM/Strings/Strings_en-CA.js
new file mode 100644
index 0000000..50fa7e5
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Strings/Strings_en-CA.js
@@ -0,0 +1,43 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+//=============================================================================
+//
+// E N G L I S H C A N A D I A N ( en_CA )
+//
+//=============================================================================
+
+Clipperz.PM.Strings.Languages['en-ca'] = MochiKit.Base.merge(Clipperz.PM.Strings.Languages['en-us'], {
+
+// 'forumHeaderLinkLabel': "forum-CA",
+
+// 'recordMenuLabel': "cards-CA",
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+}); \ No newline at end of file
diff --git a/frontend/beta/js/Clipperz/PM/Strings/Strings_en-GB.js b/frontend/beta/js/Clipperz/PM/Strings/Strings_en-GB.js
new file mode 100644
index 0000000..ea55650
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Strings/Strings_en-GB.js
@@ -0,0 +1,43 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+//=============================================================================
+//
+// E N G L I S H B R I T I S H ( en_GB )
+//
+//=============================================================================
+
+Clipperz.PM.Strings.Languages['en-gb'] = MochiKit.Base.merge(Clipperz.PM.Strings.Languages['en-us'], {
+
+// 'forumHeaderLinkLabel': "forum-GB",
+
+// 'recordMenuLabel': "cards-GB",
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+}); \ No newline at end of file
diff --git a/frontend/beta/js/Clipperz/PM/Strings/Strings_en-US.js b/frontend/beta/js/Clipperz/PM/Strings/Strings_en-US.js
new file mode 100644
index 0000000..c0dd6d0
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Strings/Strings_en-US.js
@@ -0,0 +1,1259 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. 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 = {}; }
+
+//=============================================================================
+//
+// E N G L I S H A M E R I C A N ( en_US )
+//
+//=============================================================================
+
+Clipperz.PM.Strings.Languages['en-us'] = {
+
+// Login page - description
+'clipperzServiceDescription': "\
+ <!-- FIX CSS DONE --> \
+ <h2>Keep it to yourself!</h2>\
+ <ul>\
+ <li>\
+ <h3>Clipperz is:</h3>\
+ <ul>\
+ <li><p>a secure and simple password manager</p></li>\
+ <li><p>an effective single sign-on solution</p></li>\
+ <li><p>a digital vault for your personal data</p></li>\
+ </ul>\
+ </li>\
+ <li>\
+ <h3>With Clipperz you can:</h3>\
+ <ul>\
+ <li><p>store and manage your passwords and online credentials</p></li>\
+ <li><p>login to your web services without entering any username or password</p></li>\
+ <li><p>protect all your sensitive data: codes for burglar alarms, PINs, credit card numbers, …</p></li>\
+ <li><p>share secrets with family members and associates (coming soon)</p></li>\
+ </ul>\
+ </li>\
+ <li>\
+ <h3>Clipperz benefits:</h3>\
+ <ul>\
+ <li><p>free and completely anonymous</p></li>\
+ <li><p>access it any time from any computer</p></li>\
+ <li><p>no software to download and nothing to install</p></li>\
+ <li><p>avoid keeping secrets on your PC or on paper</p></li>\
+ </ul>\
+ </li>\
+ <li>\
+ <h3>Clipperz security:</h3>\
+ <ul>\
+ <li><p>your secrets are locally encrypted by your browser before being uploaded to Clipperz</p></li>\
+ <li><p>the encryption key is a passphrase known only to you</p></li>\
+ <li><p>Clipperz hosts your sensitive data in encrypted form and could never actually access the data in its plain form</p></li>\
+ <li><p>Clipperz is built upon standard encryption schemes, nothing fancies or homemade</p></li>\
+ <li><p>you can review the source code anytime you like, but you need to know nothing about cryptography to be an happy user!</p></li>\
+ </ul>\
+ </li>\
+ <li>\
+ <a href=\"http://www.clipperz.com\" target=\"_blank\">Learn more</a>\
+ </li>\
+ </ul>",
+
+
+'loginFormTitle': "login with your Clipperz account",
+'loginFormUsernameLabel': "username",
+'loginFormPassphraseLabel': "passphrase",
+'loginFormDontHaveAnAccountLabel': "don\'t have an account?",
+'loginFormCreateOneLabel': "create one",
+'loginFormForgotYourCredentialsLabel': "forgot your credentials?",
+'loginFormAarghThatsBadLabel': "aargh! that\'s bad!",
+'loginFormAfraidOfMaliciousScriptsLabel': "afraid of malicious scripts?",
+'loginFormVerifyTheCodeLabel': "verify the code",
+'loginFormButtonLabel': "Login",
+'loginFormOneTimePasswordCheckboxLabel': "use a one-time passphrase",
+'loginFormOneTimePasswordCheckboxDescription': "",
+
+// Login page - language selection
+'loginPanelSwithLanguageDescription': "<h5>Switch to your preferred language</h5>",
+
+// Login page - browser compatibility
+'browserCompatibilityDescription': "<p>Have a better and safer Clipperz experience with Firefox. However Clipperz works just fine also with Opera, Safari and MS Internet Explorer!</p>",
+
+// Login with OTP - message panel
+'OTPloginMessagePanelInitialTitle': "Logging in using a one-time passphrase",
+'OTPloginMessagePanelInitialText': "Sending OTP credentials …",
+'OTPloginMessagePanelLoadingTitle': "Logging in using a one-time passphrase",
+'OTPloginMessagePanelLoadingText': "Fetching encrypted authentication data from the server …",
+'OTPloginMessagePanelProcessingTitle': "Logging in using a one-time passphrase",
+'OTPloginMessagePanelProcessingText': "Local decryption of authentication data",
+
+// Regular login - message panel
+'loginMessagePanelInitialTitle': "Logging in …",
+'loginMessagePanelInitialText': "---",
+'loginMessagePanelInitialButtonLabel': "Cancel",
+'loginMessagePanelConnectedTitle': "Connected",
+'loginMessagePanelConnectedText': "Done",
+'loginMessagePanelFailureTitle': "Error",
+'loginMessagePanelFailureText': "Login failed",
+'loginMessagePanelFailureButtonLabel': "Close",
+
+// Regular login - message panel - connection
+'connectionLoginSendingCredentialsMessageTitle': "Verifying credentials",
+'connectionLoginSendingCredentialsMessageText': "Sending credentials",
+'connectionLoginCredentialsVerificationMessageTitle': "Verifying credentials",
+'connectionLoginCredentialsVerificationMessageText': "Performing SRP authentication",
+'connectionLoginDoneMessageTitle': "Verifying credentials",
+'connectionLoginDoneMessageText': "Connected",
+
+// Regular login - message panel - user
+'userLoginPanelUpgradingUserCredentialsMessageTitle': "Verifying credentials",
+'userLoginPanelUpgradingUserCredentialsMessageText': "Upgrading your credentials to a new authentication schema",
+'userLoginPanelConnectedMessageTitle': "User authenticated",
+'userLoginPanelConnectedMessageText': "Successfully logged in",
+'userLoginPanelTryingAnOlderConnectionSchemaMessageTitle': "Verifying credentials",
+'userLoginPanelTryingAnOlderConnectionSchemaMessageText': "Trying an older authentication schema",
+'userLoginPanelLoadingUserDataMessageTitle': "User authenticated",
+'userLoginPanelLoadingUserDataMessageText': "Downloading encrypted card headers from Clipperz",
+'userLoginPanelDecryptingUserDataMessageTitle': "User authenticated",
+'userLoginPanelDecryptingUserDataMessageText': "Local decryption of card headers",
+'userLoginPanelDecryptingUserStatisticsMessageTitle': "User authenticated",
+'userLoginPanelDecryptingUserStatisticsMessageText': "Local decryption of usage statistics",
+
+// Registration page - splash alert
+'splashAlertTitle': "Welcome to Clipperz!",
+'splashAlertText': "\
+ <!-- FIX CSS DONE! --> \
+ <p>Some security advice</p>\
+ <ul>\
+ <li><p>Storing your data at Clipperz is as secure as the passphrase you choose to protect them. Nobody can access them unless they know your passphrase.</p></li>\
+ <li><p>If you are going to use Clipperz for safeguarding sensitive and critical information please make sure to use a strong passphrase. The longer the better!</p></li>\
+ <li><p>Clipperz will not be able to recover a lost passphrase!</p></li>\
+ </ul>\
+ <p>For any further information, please refer to <a href=\"http://www.clipperz.com\" target=\"_blank\">Clipperz</a> website.</p>",
+'splashAlertCloseButtonLabel': "Ok",
+
+// Registration page - form
+'registrationFormTitle': "create your account",
+'registrationFormUsernameLabel': "username",
+'registrationFormPassphraseLabel': "passphrase",
+'registrationFormRetypePassphraseLabel': "re-enter passphrase",
+'registrationFormSafetyCheckLabel': "I understand that Clipperz will not be able to recover a lost passphrase.",
+'registrationFormTermsOfServiceCheckLabel': "I have read and agreed to the <a href='http://www.clipperz.com/terms_of_service' target='_blank'>Terms of Service</a>.",
+'registrationFormDoYouAlreadyHaveAnAccountLabel': "do you already have an account?",
+'registrationFormSimplyLoginLabel': "simply login",
+'registrationFormButtonLabel': "Register",
+
+// Registration page - warning messages
+'registrationFormWarningMessageNotMatchingPassphrases': "Your passphrases don't match, please re-type them.",
+'registrationFormWarningMessageSafetyCheckNotSelected': "Please read and check all the boxes below.",
+'registrationFormWarningMessageTermsOfServiceCheckNotSelected': "You need to agree to the Terms of Service.",
+
+// Registration page - message panel
+'registrationMessagePanelInitialTitle': "Creating account …",
+'registrationMessagePanelInitialText': "---",
+'registrationMessagePanelInitialButtonLabel': "Cancel",
+'registrationMessagePanelRegistrationDoneTitle': "Registration",
+'registrationMessagePanelRegistrationDoneText': "Done",
+'registrationMessagePanelFailureTitle': "Registration failed",
+'registrationMessagePanelFailureButtonLabel': "Close",
+
+// Registration page - message panel - connection
+'connectionRegistrationSendingRequestMessageText': "Verifying credentials",
+'connectionRegistrationSendingCredentialsMessageText': "Sending credentials",
+
+// Registration page - splash panel
+'registrationSplashPanelTitle': "Security advice",
+'registrationSplashPanelDescription': "<p>These are your Clipperz credentials, take good care of them. Clipperz will never display your username and passphrase a second time!</p>",
+'registrationSplashPanelUsernameLabel': "username",
+'registrationSplashPanelPassphraseLabel': "passphrase",
+
+'registrationSplashPanelShowPassphraseButtonLabel': "show passphrase",
+
+// Header links
+'donateHeaderLinkLabel': "donate",
+'creditsHeaderLinkLabel': "credits",
+'feedbackHeaderLinkLabel': "feedback",
+'helpHeaderLinkLabel': "help",
+'forumHeaderLinkLabel': "forum",
+
+// Menu labels
+'recordMenuLabel': "cards",
+'accountMenuLabel': "account",
+'dataMenuLabel': "data",
+'contactsMenuLabel': "contacts",
+'toolsMenuLabel': "tools",
+'logoutMenuLabel': "logout",
+'lockMenuLabel': "lock",
+
+// Lock dialog
+'lockTitle': "The account is locked",
+'lockDescription': "<p>To unlock your account, please enter your passphrase.</p>",
+'unlockButtonLabel': "Unlock",
+
+// Account panel - change passphrase
+'changePasswordTabLabel': "Change your passphrase",
+'changePasswordTabTitle': "Change your passphrase",
+
+'changePasswordFormUsernameLabel': "username",
+'changePasswordFormOldPassphraseLabel': "old passphrase",
+'changePasswordFormNewPassphraseLabel': "new passphrase",
+'changePasswordFormRetypePassphraseLabel': "re-enter new passphrase",
+'changePasswordFormSafetyCheckboxLabel': "I understand that Clipperz will not be able to recover a lost passphrase.",
+'changePasswordFormSubmitLabel': "Change passphrase",
+
+// Account panel - change passphrase - warning messages
+'changePasswordFormWrongUsernameWarning': "Wrong username",
+'changePasswordFormWrongPassphraseWarning': "Wrong passphrase",
+'changePasswordFormWrongRetypePassphraseWarning': "Your passphrases don't match, please re-type them.",
+'changePasswordFormSafetyCheckWarning': "Please read and check the box below.",
+
+// Account panel - change passphrase - progress dialog
+'changePasswordFormProgressDialogTitle': "Changing user credentials",
+'changePasswordFormProgressDialogEmptyText': "---",
+'changePasswordFormProgressDialogConnectedMessageTitle': "Connected",
+'changePasswordFormProgressDialogConnectedMessageText': "Done",
+'changePasswordFormProgressDialogErrorMessageTitle': "Error",
+'changePasswordFormProgressDialogErrorMessageText': "Credentials change failed!",
+
+'changeCredentialsPanelEncryptingDataMessageTitle': "Changing your passphrase",
+'changeCredentialsPanelEncryptingDataMessageText': "Local encryption of card headers",
+'changeCredentialsPanelCreatingNewCredentialsMessageTitle': "Changing your passphrase",
+'changeCredentialsPanelCreatingNewCredentialsMessageText': "Updating your credentials",
+'changeCredentialsPanelSendingNewCredentialsToTheServerMessageTitle': "Changing your passphrase",
+'changeCredentialsPanelSendingNewCredentialsToTheServerMessageText': "Uploading your encrypted credentials to Clipperz",
+'changeCredentialsPanelDoneMessageTitle': "Changing your passphrase",
+'changeCredentialsPanelDoneMessageText': "Done",
+
+// Account panel - OTP
+'manageOTPTabLabel': "Manage your one-time passphrases",
+'manageOTPTabTitle': "Manage your one-time passphrases",
+
+'manageOTPTabDescription': "\
+ <p>A one-time passphrase works like your regular passphrase, but can be used only once.</p>\
+ <p>If the same passphrase is used again at a later stage in a login attempt it will be rejected and the login process will fail.</p>\
+ <p>Immediately after a successful login, your one-time passphrase will be deleted preventing any fraudulent access.</p>\
+ <p>One-time passphrases are an excellent choice if one is concerned about keyloggers or spyware infections that may be collecting data from compromised machines.</p>\
+ <p><b>It's strongly advisable to use one-time passphrases when accessing Clipperz from public terminals, such as Internet cafes and libraries.</b></p>",
+
+// Account panel - OTP - OTP table
+'oneTimePasswordReadOnlyMessage': "\
+ <h6>Sorry!</h6>\
+ <p>You cannot manage your one-time passphrases when using the offline version of Clipperz.</p>",
+
+'oneTimePasswordLoadingMessage': "\
+ <h6>Loading data</h6>\
+ <p>Please wait …</p>",
+
+'oneTimePasswordNoPasswordAvailable': "\
+ <h6>No one-time passphrase available</h6>\
+ <p>Click the “New” button above to add one-time passphrases to your account.</p>",
+
+'createNewOTPButtonLabel': "New",
+'deleteOTPButtonLabel': "Delete",
+'printOTPButtonLabel': "Print",
+
+'disabledOneTimePassword_warning': "disabled",
+
+'oneTimePasswordSelectionLink_selectLabel': "Select:",
+'oneTimePasswordSelectionLink_all': "all",
+'oneTimePasswordSelectionLink_none': "none",
+'oneTimePasswordSelectionLink_used': "used",
+'oneTimePasswordSelectionLink_unused': "unused",
+
+//Account panel - OTP - saving new OTP dialog
+'saveOTP_encryptUserDataTitle': "Saving one-time passphrase",
+'saveOTP_encryptUserDataText': "Processing new OTP credentials …",
+'saveOTP_encryptOTPDataTitle': "Saving one-time passphrase",
+'saveOTP_encryptOTPDataText': "Local encryption of authentication data …",
+'saveOTP_sendingDataTitle': "Saving one-time passphrase",
+'saveOTP_sendingDataText': "Sending authentication data to the server …",
+'saveOTP_updatingInterfaceTitle': "Saving one-time passphrase",
+'saveOTP_updatingInterfaceText': "Updating interface",
+
+// Account panel - preferences
+'accountPreferencesLabel': "Preferences",
+'accountPreferencesTabTitle': "Preferences",
+
+'accountPreferencesLanguageTitle': "Language",
+'accountPreferencesLanguageDescription': "<p>Choose your preferred language from the list below.</p>",
+
+'showDonationReminderPanelTitle': "Donation reminders",
+'showDonationReminderPanelDescription': "<p>Show donation reminders</p>",
+
+'saveUserPreferencesFormSubmitLabel': "Save",
+'cancelUserPreferencesFormSubmitLabel': "Cancel",
+
+// Account panel - preferences - saving dialog
+'accountPreferencesSavingPanelTitle_Step1': "Saving preferences",
+'accountPreferencesSavingPanelText_Step1': "Local encryption of your preferences",
+'accountPreferencesSavingPanelTitle_Step2': "Saving preferences",
+'accountPreferencesSavingPanelText_Step2': "Sending encrypted preferences to Clipperz",
+
+// Account panel - login history
+'accountLoginHistoryLabel': "Login history",
+'loginHistoryTabTitle': "Login history",
+
+'loginHistoryReadOnlyMessage': "\
+ <h6>Sorry!</h6>\
+ <p>The login history is not available while using the offline version of Clipperz.</p>",
+
+'loginHistoryLoadingMessage': "\
+ <h6>Loading data</h6>\
+ <p>Please wait …</p>",
+
+'loginHistoryLoadedMessage': "\
+ <h6>Your latest 10 logins</h6>\
+ <p></p>",
+
+'loginHistoryIPLabel': "IP",
+'loginHistoryTimeLabel': "date",
+'loginHistoryCurrentSessionText': "current session",
+'loginHistoryReloadButtonLabel': "Reload login history",
+
+// Account panel - delete account
+'deleteAccountTabLabel': "Delete your account",
+'deleteAccountTabTitle': "Delete your account",
+
+'deleteAccountFormUsernameLabel': "username",
+'deleteAccountFormPassphraseLabel': "passphrase",
+'deleteAccountFormSafetyCheckboxLabel': "I understand that all my data will be deleted and that this action is irreversible.",
+'deleteAccountFormSubmitLabel': "Delete my account",
+
+//Account panel - delete account - warnings
+'deleteAccountFormWrongUsernameWarning': "Wrong username",
+'deleteAccountFormWrongPassphraseWarning': "Wrong passphrase",
+'deleteAccountFormSafetyCheckWarning': "Please read and check the box below.",
+
+//Account panel - delete account - confirmation
+'accountPanelDeletingAccountPanelConfirmationTitle': "ATTENTION",
+'accountPanelDeleteAccountPanelConfirmationText': "Are your sure you want to delete your account?",
+'accountPanelDeleteAccountPanelConfirmButtonLabel': "Yes",
+'accountPanelDeleteAccountPanelDenyButtonLabel': "No",
+
+//Account panel - delete account - confirmation
+'accountPanelDeletingAccountPanelProgressTitle': "Deleting the account data",
+'accountPanelDeletingAccountPanelProgressText': "The operation could take long, please be patient.",
+
+//Data panel - offline copy
+'offlineCopyTabLabel': "Offline copy",
+'offlineCopyTabTitle': "Offline copy",
+
+'offlineCopyTabDescription': "\
+ <!-- FIX CSS DONE! --> \
+ <p>With just one click you can dump all your encrypted data from Clipperz servers to your hard disk and create a read-only offline version of Clipperz to be used when you are not connected to the Internet.</p>\
+ <p>The read-only version is as secure as the read-and-write one and will not expose your data to higher risks since they both share the same code and security architecture.</p>\
+ <ol>\
+ <li><p>Click the link below to start the download.</p></li>\
+ <li><p>The browser will ask you what to do with the “Clipperz_YYYYMMDD.html” file. Save it on your hard disk.</p></li>\
+ <li><p>Double click on the downloaded file to launch the offline version in your browser.</p></li>\
+ <li><p>Enter the usual username and passphrase.</p></li>\
+ </ol>",
+
+'offlineCopyDownloadLinkLabel': "Download",
+
+// Data panel - offline copy - not updated
+'offlineCopyDownloadWarning': "\
+ <!-- FIX CSS DONE! --> \
+ <h4><a href=\"#\" id=\"offlineCopyDownloadWarningLink\">Update your “offline copy”!</a></h4>\
+ <p>You have recently created or modified one or more cards, it would be wise to download a new copy of the offline version.</p>",
+
+'offlineCopyDownloadOk': "",
+
+// Data panel - sharing
+'sharingTabLabel': "Sharing",
+'sharingTabTitle': "Sharing",
+
+'sharingTabDescription': "\
+ <p>Quite often a confidential piece of information needs to be shared with one or more persons.</p>\
+ <p>This could be as simple as giving your colleague the access code of your voice mailbox when you are out of the office, or as complicated as enabling the entitled heirs to access your safe deposit box at the local bank when you pass on.</p>\
+ <p>Clipperz can make sharing your secrets a secure and straightforward process.</p>\
+ <p></p>\
+ <p><b>Coming soon …</b></p>",
+
+// Data panel - import
+'importTabLabel': "Import",
+'importTabTitle': "Import",
+
+'importTabDescription': "<p>You can bulk import data to your Clipperz account from several file formats.</p>",
+
+// Data panel - export
+'printingTabLabel': "Export",
+'printingTabTitle': "Export",
+
+'printingTabDescription': "\
+ <h5>Printing</h5>\
+ <p>Click on the link below to open a new window displaying all your cards in a printable format.</p>\
+ <p>If you are going to print for backup purposes, please consider the safer option provided by the “offline copy”.</p>",
+
+'printingLinkLabel': "Printable version",
+
+'exportTabDescription': "\
+ <h5>Exporting to JSON</h5>\
+ <p>JSON enables a “lossless” export of your cards. All the information will be preserved, including direct login configurations.</p>\
+ <p>This custom format it’s quite convenient if you need to move some of all of your cards to a different Clipperz account. Or if you want to restore a card that has been accidentally deleted.</p>\
+ <p>Click on the link below to start the export process.</p>",
+
+'exportLinkLabel': "Export to JSON",
+
+'exportDataInProgressDescription': "<h4>Exporting, please wait while your data are being processed …</h4>",
+
+'exportDataDescription': "\
+ <h4>Instructions</h4>\
+ <p>Copy the text below to your favorite editor and save it. (e.g. “clipperz_export_20071217.json”)</p>",
+
+// Contacts panel
+'contactsTabLabel': "Contacts",
+'contactsTabTitle': "Contacts",
+
+//Tools panel - password generator
+'passwordGeneratorTabLabel': "Password generator",
+'bookmarkletTabLabel': "Bookmarklet",
+'compactTabLabel': "Compact edition",
+'httpAuthTabLabel': "HTTP authentication",
+
+'passwordGeneratorTabTitle': "Password generator",
+'bookmarkletTabTitle': "Bookmarklet",
+'compactTabTitle': "Compact edition",
+'httpAuthTabTitle': "HTTP authentication",
+
+
+// Tools panel - password generator - description
+'paswordGeneratorTabDescription': "<p></p>",
+'passwordGeneratorTabButtonLabel': "Generate password",
+
+// Tools panel - bookmarklet
+'bookmarkletTabLabel': "Bookmarklet",
+'bookmarkletTabTitle': "Bookmarklet",
+
+'bookmarkletTabDescription': "\
+ <!-- FIX CSS DONE! --> \
+ <p>A bookmarklet is a simple “one-click” tool that can perform very useful tasks. It can be saved and used like a normal web page bookmark.</p>\
+ <p>The Clipperz bookmarklet will help you to quickly create new cards and new “direct logins” within existing cards.</p>\
+ <p><b>Please note that the bookmarklet does not include any information related to your account (e.g. your username or passphrase), the bookmarklet is a general tool containing the same code for every Clipperz user.</b></p>\
+ <h3>How to install the bookmarklet</h3>\
+ <h>Firefox, Camino, Opera, Safari</h5>\
+ <ol>\
+ <li><p>Make sure that the “Bookmarks Bar” is displayed by selecting “View > Toolbars > Bookmarks”, or similar menu items, from the browser menu.</p></li>\
+ <li><p>Drag and drop the “Add to Clipperz” link below to the bookmark bar.</p></li>\
+ </ol>\
+ \
+ <h5>Internet Explorer</h5>\
+ <ol>\
+ <li><p>Make sure that the “Links” toolbar is displayed by selecting “View > Toolbars > Links” from the browser menu.</p></li>\
+ <li><p>Right-click on the “Add to Clipperz” link below.</p></li>\
+ <li><p>Select “Add to favorites” from the contextual menu.</p></li>\
+ <li><p>Click “Yes” for any security message that pops up.</p></li>\
+ <li><p>Open the “Links” folder and click “OK”</p></li>\
+ </ol>",
+
+'bookmarkletTabBookmarkletTitle': "Add to Clipperz",
+
+// Tools panel - bookmarklet - instructions
+'bookmarkletTabInstructions': "\
+ <!-- FIX CSS DONE! --> \
+ <h3>How to create a new card inclusive of a “direct login” link to an online service</h3>\
+ <ol>\
+ <li><p>Open the web page where the login form is hosted. (this is the page where you usually enter your sign-in credentials)</p></li>\
+ <li><p>Launch the bookmarklet by clicking on it: a pop-up window will appear over the web page.</p></li>\
+ <li><p>Copy to the clipboard the content of the large text area within the pop-up. (ctrl-C)</p></li>\
+ <li><p>Enter your Clipperz account and click on the <b>Add new card</b> button.</p></li>\
+ <li><p>Select the “Direct login” template and paste the content of the clipboard to the large text area in the form. (ctrl-V)</p></li>\
+ <li><p>Press the <b>Create</b> button, complete and review the details, then click <b>Save</b>.</p></li>\
+ </ol>\
+ \
+ <h3>How to add a “direct login” link to an existing card</h3>\
+ <ol>\
+ <li><p>Same as above.</p></li>\
+ <li><p>Same as above.</p></li>\
+ <li><p>Same as above.</p></li>\
+ <li><p>Enter your Clipperz account and select the card containing the credentials for the web service you just visited and click the <b>Edit</b> button.</p></li>\
+ <li><p>Paste the content of the clipboard to the large text area in the “Direct logins” section. (ctrl-V)</p></li>\
+ <li><p>Press the <b>Add direct login</b> button, review the details and then click <b>Save</b>.</p></li>\
+ </ol>\
+ \
+ <p></p>\
+ <p>Further information about the bookmarklet are <a href=\"http://www.clipperz.com/support/user_guide/bookmarklet\" target=\"_blank\">available here</a>.</p>",
+
+// Tools panel - Compact - instructions
+'compactTabDescription': "\
+ <!-- FIX CSS DONE! --> \
+ <p>Clipperz Compact is a special version of Clipperz designed to be opened in the Firefox sidebar.</p>\
+ <p>Its purpose is to keep your collection of “direct logins” always at hand. Read more <a href=\"http://www.clipperz.com/support/user_guide/clipperz_compact\", target=\"blank\">here</a></p>\
+ \
+ <h3>How to launch Clipperz Compact in the sidebar</h3>\
+ <ol>\
+ <li><p>Get Firefox! Sidebars are only available in Firefox and you need to switch to Firefox in order to enjoy the convenience of Clipperz Compact.</p></li>\
+ <li>\
+ <p>Add the following URL to Firefox bookmarks, or even better, drag it to the bookmark bar.</p>\
+ <div id=\"compactLinkBox\"><a href=\"https://www.clipperz.com/beta/index.html?compact\" target=\"_search\">Clipperz Compact</a></div>\
+ </li>\
+ <li><p>Change the properties of the bookmark so that “load this bookmark in the sidebar” is checked.</p></li>\
+ </ol>\
+ \
+ <h5>Added bonus: Clipperz Compact works also in Opera’s panel.</h5>",
+
+// Tools panel - HTTP authentication - instructions
+'httpAuthTabDescription': "\
+ <!-- FIX CSS DONE! --> \
+ <p>HTTP authentication is a method designed to allow a web browser to provide credentials – in the form of a username and password – including them in a website address (HTTP or HTTPS URL).</p>\
+ <p>Nowadays it is rarely used, but it can still be found on small, private websites. You can tell that a website is protected by HTTP authentication when the browser displays a pop-up window to enter username and password.</p>\
+ <p>Unfortunately the Clipperz bookmarklet does not work on websites that use HTTP authentication. However you can still create a “direct login”.</p>\
+ \
+ <h3>How to create a “direct login” for a website that uses HTTP authentication</h3>\
+ <ol>\
+ <li><p>Store website URL, username and password in a new card.</p></li>\
+ <li><p>Copy the configuration below and paste it to the large text area in the “Direct logins” section of the new card.</p></li>\
+ <li><p>Press the <b>Add direct login</b> button, bind URL, username and password fields and then click <b>Save</b>.</p></li>\
+ </ol>\
+ \
+ <h5><a href=\"http://support.microsoft.com/kb/834489\" target=\"_blank\">Warning: Internet Explorer does not support HTTP authentication.</a></h5>",
+
+// Direct logins block
+'mainPanelDirectLoginBlockLabel': "Direct logins",
+'directLinkReferenceShowButtonLabel': "show",
+
+// Direct logins - blank slate
+'mainPanelDirectLoginBlockDescription': "\
+ <!-- FIX CSS DONE! --> \
+ <p>Add “direct logins” to sign in to your web accounts without typing usernames and passwords!</p>\
+ <p>“Direct logins” greatly enhance your password security since you can:</p>\
+ <ul>\
+ <li><p>conveniently adopt and enter complex passwords;</p></li>\
+ <li><p>never re-use the same and easy-to-guess password.</p></li>\
+ </ul>\
+ <p>Simple and quick configuration with the <b>Clipperz bookmarklet</b>.</p>\
+ <a href=\"http://www.clipperz.com/support/user_guide/direct_logins\" target=\"_blank\">Learn more about “direct logins”</a>",
+
+// Cards block
+'mainPanelRecordsBlockLabel': "Cards",
+'mainPanelAddRecordButtonLabel': "Add new card",
+'mainPanelRemoveRecordButtonLabel': "Delete card",
+
+// Cards block - filter tabs
+'mainPanelRecordFilterBlockAllLabel': "all",
+'mainPanelRecordFilterBlockTagsLabel': "tags",
+'mainPanelRecordFilterBlockSearchLabel': "search",
+
+// Cards block - blank slate
+'recordDetailNoRecordAtAllTitle': "Welcome to Clipperz!",
+'recordDetailNoRecordAtAllDescription': "\
+ <h5>Get started by adding cards to your account.</h5>\
+ <p>Cards are simple and flexible forms where you can store your passwords and any other confidential data.</p>\
+ <p>Cards could contain credentials for accessing a web site, the combination of your bicycle lock, details of your credit card, …</p>\
+ \
+ <h5>Don't forget the Clipperz bookmarklet!</h5>\
+ <p>Before you start, install the “Add to Clipperz” bookmarklet: it will make creating cards easier and more fun.</p>\
+ <p>Go to the “Tools” tab to discover how to install it and how it use it.</p>\
+ <p></p>\
+ <p>Then simply click the <b>\"Add new card\"</b> button and enjoy your Clipperz account.</p>\
+ <p></p>\
+ <a href=\"http://www.clipperz.com/support/user_guide/managing_cards\" target=\"_blank\">Learn more about creating and managing cards</a>",
+
+// Cards block - new card wizard - bookmarklet configuration
+'newRecordWizardTitleBox': "\
+ <h5>Please select a template</h5>\
+ <p>Cards are simple and flexible forms where you can store passwords or any other confidential data.</p>\
+ <p>Start choosing one of the templates below. You can always customize your cards later by adding or removing fields.</p>",
+
+'newRecordWizardBookmarkletConfigurationTitle': "Direct login",
+'newRecordWizardBookmarkletConfigurationDescription': "\
+ <p>Paste below the configuration code generated by the Clipperz bookmarklet.</p>\
+ <p>A new card complete with a direct login to your web account will be created.</p>",
+
+'newRecordWizardCreateButtonLabel': "Create",
+'newRecordWizardCancelButtonLabel': "Cancel",
+
+// Create new card - Donation splash
+'donateSplashPanelTitle': "Support Clipperz, make a donation today!",
+'donateSplashPanelDescription': "\
+ <!-- FIX CSS DONE! --> \
+ <p>A few good reasons to make a donation:</p>\
+ <ul>\
+ <li><p>support the development of new features</p></li>\
+ <li><p>keep Clipperz free</p></li>\
+ <li><p>show appreciation for our hard work</p></li>\
+ </ul>\
+ <p>For any further information, please visit our <a href=\"http://www.clipperz.com/donations\" target=\"_blank\">Donations page</a>.</p>\
+ <p><b>Ready to donate?</b></p>",
+
+'donateCloseButtonLabel': "Not yet",
+'donateDonateButtonLabel': "Yes",
+
+// Card templates
+'recordTemplates': {
+
+//Web password
+ 'WebAccount': {
+ 'title': "Web password",
+ 'description': "<p>A simple card to store login credentials for your online services.</p>",
+ 'fields': [
+ {label:"Web address", type:'URL'},
+ {label:"Username or email", type:'TXT'},
+ {label:"Password", type:'PWD'}
+ ]
+ },
+
+//Bank account
+ 'BankAccount': {
+ 'title': "Bank account",
+ 'description': "<p>Safely store your bank account number and online banking credentials.</p>",
+ 'fields': [
+ {label:"Bank", type:'TXT'},
+ {label:"Account number", type:'TXT'},
+ {label:"Bank website", type:'URL'},
+ {label:"Online banking ID", type:'TXT'},
+ {label:"Online banking password", type:'PWD'}
+ ]
+ },
+
+// Credit card
+ 'CreditCard': {
+ 'title': "Credit card",
+ 'description': "<p>Card number, expire date, CVV2 and PIN always at hand with Clipperz.</p>",
+ 'fields': [
+ {label:"Type (Visa, AmEx, …)", type:'TXT'},
+ {label:"Number", type:'TXT'},
+ {label:"Owner name", type:'TXT'},
+ {label:"Expiry date", type:'TXT'},
+ {label:"CVV2", type:'TXT'},
+ {label:"PIN", type:'PWD'},
+ {label:"Card website", type:'URL'},
+ {label:"Username", type:'TXT'},
+ {label:"Password", type:'PWD'}
+ ]
+ },
+
+// Address book entry
+ 'AddressBookEntry': {
+ 'title': "Address book entry",
+ 'description': "<p>Clipperz could also work as your new private address book. Use this template to easily add a new entry.</p>",
+ 'fields': [
+ {label:"Name", type:'TXT'},
+ {label:"Email", type:'TXT'},
+ {label:"Phone", type:'TXT'},
+ {label:"Mobile", type:'TXT'},
+ {label:"Address", type:'ADDR'},
+ ]
+ },
+
+//Custom card
+ 'Custom': {
+ 'title': "Custom card",
+ 'description': "<p>No matter which kind of confidential data you need to protect, create a custom card to match your needs.</p>",
+ 'fields': [
+ {label:"Label 1", type:'TXT'},
+ {label:"Label 2", type:'TXT'},
+ {label:"Label 3", type:'TXT'}
+ ]
+ }
+},
+
+
+'recordFieldTypologies': {
+ 'TXT': {
+ description: "simple text field",
+ shortDescription: "text"
+ },
+ 'PWD': {
+ description: "simple text field, with default status set to hidden",
+ shortDescription: "password"
+ },
+ 'URL': {
+ description: "simple text field in edit mode, that became an active url in view mode",
+ shortDescription: "web address"
+ },
+ 'DATE': {
+ description: "a value set with a calendar helper",
+ shortDescription: "date"
+ },
+ 'ADDR': {
+ description: "just like the URL, but the active link points to Google Maps (or similar service) passing the address value as argument",
+ shortDescription: "street address"
+ },
+ 'CHECK': {
+ description: "check description",
+ shortDescription: "check"
+ },
+ 'RADIO': {
+ description: "radio description",
+ shortDescription: "radio"
+ },
+ 'SELECT': {
+ description: "select description",
+ shortDescription: "select"
+ }
+},
+
+// Cards block - new card - warnings
+'newRecordPanelGeneralExceptionTitle': "Error",
+'newRecordPanelGeneralExceptionMessage': "The configuration text is not valid. Make sure to get your text from the bookmarklet pop-up and retry.",
+'newRecordPanelWrongBookmarkletVersionExceptionTitle': "Error",
+'newRecordPanelWrongBookmarkletVersionExceptionMessage': "The configuration text has been generated by an old version of the bookmarklet. Please update your bookmarklet and retry.",
+'newRecordPanelExceptionPanelCloseButtonLabel': "Cancel",
+
+// Cards block - delete card
+'mainPanelDeletingRecordPanelConfirmationTitle': "Deleting selected card",
+'mainPanelDeleteRecordPanelConfirmationText': "Do your really want to delete the selected card?",
+'mainPanelDeleteRecordPanelConfirmButtonLabel': "Yes",
+'mainPanelDeleteRecordPanelDenyButtonLabel': "No",
+'mainPanelDeletingRecordPanelInitialTitle': "Deleting selected card",
+'mainPanelDeletingRecordPanelInitialText': "---",
+'mainPanelDeletingRecordPanelCompletedText': "Done",
+
+// Cards block - delete card panel
+'deleteRecordPanelCollectRecordDataMessageTitle': "Delete card",
+'deleteRecordPanelCollectRecordDataMessageText': "Updating card list",
+'deleteRecordPanelEncryptUserDataMessageTitle': "Delete card",
+'deleteRecordPanelEncryptUserDataMessageText': "Local encryption of card headers",
+'deleteRecordPanelSendingDataToTheServerMessageTitle': "Delete card",
+'deleteRecordPanelSendingDataToTheServerMessageText': "Uploading encrypted card headers to Clipperz",
+'deleteRecordPanelUpdatingTheInterfaceMessageTitle': "Delete card",
+'deleteRecordPanelUpdatingTheInterfaceMessageText': "Updating the interface",
+
+// Cards block - no record selected
+'recordDetailNoRecordSelectedTitle': "No card selected",
+'recordDetailNoRecordSelectedDescription': "<p>Please select a card from the list on the left.</p>",
+
+// Cards block - loading messages
+'recordDetailLoadingRecordMessage': "Downloading encrypted card from Clipperz",
+'recordDetailDecryptingRecordMessage': "Local decryption of card\'s data",
+'recordDetailLoadingRecordVersionMessage': "Downloading latest card version",
+'recordDetailDecryptingRecordVersionMessage': "Local decryption of latest version",
+'recordDetailLoadingErrorMessageTitle': "Error while downloading the card",
+
+// Cards block - card details
+'recordDetailNotesLabel': "Notes",
+'recordDetailLabelFieldColumnLabel': "Field label",
+'recordDetailDataFieldColumnLabel': "Field data",
+'recordDetailTypeFieldColumnLabel': "Type",
+
+'recordDetailSavingChangesMessagePanelInitialTitle': "Saving card",
+'recordDetailSavingChangesMessagePanelInitialText': "---",
+
+'recordDetailRemoveFieldButtonLabel': "-",
+'recordDetailAddFieldButtonLabel': "Add new field",
+'recordDetailPasswordFieldHelpLabel': "click the stars to select the password and then Ctrl-C to copy",
+
+'recordDetailPasswordFieldScrambleLabel': "scramble",
+'recordDetailPasswordFieldUnscrambleLabel': "unscramble",
+
+'recordDetailDirectLoginBlockTitle': "Direct logins",
+'recordDetailNewDirectLoginDescription': "<p>Direct login configuration</p>",
+
+'recordDetailDirectLoginBlockNoDirectLoginConfiguredDescription': "\
+ <p>Does this card contain credentials to access an online service?</p>\
+ <p>Use the bookmarklet to configure a “direct login” from Clipperz with just one click!</p>",
+
+'recordDetailDeleteDirectLoginButtonLabel': "-",
+'recordDetailAddNewDirectLoginButtonLabel': "Add new direct login",
+
+'recordDetailEditButtonLabel': "Edit",
+'recordDetailSaveButtonLabel': "Save",
+'recordDetailCancelButtonLabel': "Cancel",
+
+'newRecordTitleLabel': "_new card_",
+'newDirectLoginLabelSuffix': "",
+
+// Cards block - save card panel
+'recordSaveChangesPanelCollectRecordInfoMessageTitle': "Save card",
+'recordSaveChangesPanelCollectRecordInfoMessageText': "Updating card headers",
+'recordSaveChangesPanelEncryptUserDataMessageTitle': "Save card",
+'recordSaveChangesPanelEncryptUserDataMessageText': "Local encryption of card headers",
+'recordSaveChangesPanelEncryptRecordDataMessageTitle': "Save card",
+'recordSaveChangesPanelEncryptRecordDataMessageText': "Local encryption of card's data",
+'recordSaveChangesPanelEncryptRecordVersionDataMessageTitle': "Save card",
+'recordSaveChangesPanelEncryptRecordVersionDataMessageText': "Local encryption of card's version data",
+'recordSaveChangesPanelSendingDataToTheServerMessageTitle': "Save card",
+'recordSaveChangesPanelSendingDataToTheServerMessageText': "Uploading encrypted card's header to Clipperz",
+'recordSaveChangesPanelUpdatingTheInterfaceMessageTitle': "Save card",
+'recordSaveChangesPanelUpdatingTheInterfaceMessageText': "Updating the interface",
+
+// Password Generator strings
+'passwordGeneratorPanelTitle': "Password generator",
+'passwordGeneratorPanelOkLabel': "Ok",
+'passwordGeneratorPanelCancelLabel': "Cancel",
+
+'passwordGeneratorLowercaseLabel': "abc",
+'passwordGeneratorUppercaseLabel': "ABC",
+'passwordGeneratorNumberLabel': "012",
+'passwordGeneratorSymbolLabel': "@#$",
+
+'passwordGeneratorLengthLabel': "length:",
+
+
+//Miscellaneous strings
+
+//'DWRUtilLoadingMessage': "Loading data …",
+'comingSoon': "coming soon …",
+'panelCollectingEntryopyMessageText': "Collecting entropy",
+'directLoginConfigurationCheckBoxFieldSelectedValue': "Yes",
+'directLoginConfigurationCheckBoxFieldNotSelectedValue': "No",
+
+
+
+// NEW - Import panel
+'importFormats': {
+ 'CSV': {
+ 'label': "CSV",
+ 'description': "<p>A widely recognized file format that stores tabular data. Several password managers can export data to this format.</p>"
+ },
+ 'Excel': {
+ 'label': "Excel",
+ 'description': "<p>The popular spreadsheet from Microsoft. Storing passwords in Excel files is very common but not advisable.</p>"
+ },
+ 'KeePass': {
+ 'label': "KeePass",
+ 'description': "<p>The custom TXT file created by KeePass password manager.</p>"
+ },
+ 'PasswordPlus': {
+ 'label': "Password Plus",
+ 'description': "<p>The custom CSV format produced by Password Plus, a password manager mostly used on mobile devices.</p>"
+ },
+ 'Roboform': {
+ 'label': "RoboForm",
+ 'description': "<p>The special HTML file created by Roboform password manager when displaying Passcard and Safenotes for printing.</p>"
+ },
+ 'ClipperzExport': {
+ 'label': "JSON",
+ 'description': "<p>The file created by Clipperz itself in JSON format. It preserves all information contained in your cards, even direct login configurations.</p>"
+ }
+},
+
+// JSON
+'Clipperz_ImportWizard_Title': "JSON import",
+'importOptions_clipperz_description': "<p>Open the JSON file exported from Clipperz in a text editor. Then copy and paste its content to the text area below.</p>",
+
+// CSV
+'CSV_ImportWizard_Title': "CSV import",
+'importOptions_csv_description_': "\
+ <p>Open the CSV file in a text editor. Then copy and paste its content to the text area below.</p>\
+ <p>Please select the special characters used within your file.</p>",
+
+// Excel
+'Excel_ImportWizard_Title': "Excel import",
+'importOptions_excel_description_': "<p>Open the Excel file and select the cells you want to import. Then copy and paste them to the text area below.</p>",
+
+// KeePass
+'KeePass_ImportWizard_Title': "KeePass import",
+'importOptions_keePass_description_': "<p>Open the TXT file created by Keepass in a text editor. Then copy and paste its content to the text area below.</p>",
+
+// PasswordPlus
+'PasswordPlus_ImportWizard_Title': "Password Plus import",
+'importOptions_passwordPlus_description': "<p>Open the CSV file created by PasswordPlus in a text editor. Then copy and paste its content to the text area below.</p>",
+
+// RoboForm
+'RoboForm_ImportWizard_Title': "RoboForm import",
+'importOptions_roboForm_description': "<p>Open the HTML file created by RoboForm in a text editor. Then copy and paste its content to the text area below.</p>",
+
+
+'importData_parsingDataTitle': "Import",
+'importData_parsingDataText': "Parsing data …",
+
+'importData_previewingDataTitle': "Import",
+'importData_previewingDataText': "Processing data …",
+
+'importData_processingDataTitle': "Import",
+'importData_processingDataText': "Creating new cards …",
+
+'ImportWizard': {
+ 'EDIT': "edit",
+ 'PREVIEW': "preview",
+ 'IMPORT': "import",
+
+ 'KEEPASS_SETTINGS': "settings",
+
+ 'CSV_EDIT': "paste",
+ 'CSV_COLUMNS': "columns",
+ 'CSV_HEADER': "labels",
+ 'CSV_TITLE': "titles",
+ 'CSV_NOTES': "notes",
+ 'CSV_FIELDS': "types",
+
+ 'EXCEL_EDIT': "edit"
+},
+
+'CSV_ImportWizard_Columns': "<p>Select the columns you want to import.</p>",
+'CSV_ImportWizard_Header': "<p>If the first row of the CSV file contains field labels, tick off the checkbox below.</p>",
+'CSV_ImportWizard_Header_Settings_firstRowHeaderLabel': "Use the first row as labels?",
+'CSV_ImportWizard_Title': "<p>Select the column that contains titles of the cards you are importing. (mandatory)</p>",
+'CSV_ImportWizard_Notes': "<p>Select the column that represents a \"notes\" field. (optional)</p>",
+'CSV_ImportWizard_Notes_Settings_noSelectionLabel': "\"notes\" field not present",
+'CSV_ImportWizard_Fields': "<p>Select the correct type for each column from the drop down lists.</p>",
+'CSV_ImportWizard_Fields_MissingLabelWarning': "Missing label",
+
+'importData_importConfirmation_title': "Import",
+'importData_importConfirmation_text': "Do you want to import __numberOfRecords__ cards?",
+
+
+// Vulnerability warning
+'VulnerabilityWarning_Panel_title': "Vulnerability warning",
+'VulnerabilityWarning_Panel_message': "The action as been aborted due to a catched vulnerability",
+'VulnerabilityWarning_Panel_buttonLabel': "Close",
+
+
+
+// All the loginInfo panel infos
+
+'WELCOME_BACK': "Welcome back!",
+
+'currentConnectionText': "You are connected from ip&nbsp;__ip__, apparently from __country__, using __browser__ on __operatingSystem__.",
+'latestConnectionText': "Your latest connection was __elapsedTimeDescription__ (__time__) from ip&nbsp;__ip__, apparently from __country__, using __browser__ on __operatingSystem__.",
+
+'fullLoginHistoryLinkLabel': "show login history",
+
+'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",
+
+__syntaxFix__: "syntax fix"
+
+}
diff --git a/frontend/beta/js/Clipperz/PM/Strings/Strings_es-ES.js b/frontend/beta/js/Clipperz/PM/Strings/Strings_es-ES.js
new file mode 100644
index 0000000..1541d5f
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Strings/Strings_es-ES.js
@@ -0,0 +1,480 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+Clipperz.PM.Strings.Languages['es-ES'.toLowerCase()] = MochiKit.Base.merge(Clipperz.PM.Strings.Languages['en-us'], {
+'clipperzServiceDescription': "<h2>Guárdelo usted mismo!</h2> <ul> <li> <h3>Clipperz es:</h3> <ul> <li> <p>un simple y seguro administrador de contraseñas</p> </li> <li> <p>una efectiva y simple solución de logueo</p> </li> <li> <p>un maletín digital para sus datos confidenciales</p> </li> </ul> </li> <li> <h3>Con Clipperz usted puede:</h3> <ul> <li> <p>administrar y almacenar en línea sus contraseñas y credenciales digitales</p> </li> <li> <p>ingresar en sus servicios web sin ningún nombre de usuario o contraseña</p> </li> <li> <p>protejer todos sus datos sensibles: códigos de alarmas, PINs y números de tarjetas de crédito, &hellip;</p> </li> <li> <p>compartir secretos con sus familiares y socios</p> </li> </ul> </li> <li> <h3>Beneficios de Clipperz:</h3> <ul> <li> <p>es gratis y completamente anónimo</p> </li> <li> <p>con acceso en cualquier momento y desde cualquier ordenador</p> </li> <li> <p>no necesita instalar o descargar ningún programa</p> </li> <li> <p>no necesita guardar secretos en papel o en el ordenador</p> </li> </ul> </li> <li> <h3>Seguridad de Clipperz:</h3> <ul> <li> <p>sus secretos son localmente encriptados por su navegador antes de ser almacenados en Clipperz</p> </li> <li> <p>la llave de encriptación es una frase clave conocida solo por usted</p> </li> <li> <p>Clipperz almacena sus datos de manera encriptada y nunca accede a ellos en forma de texto plano</p> </li> <li> <p>Clipperz esta basado en esquemas estándares de encriptación, no hemos inventado nada</p> </li> <li> <p>usted puede revisar el código todas las veces que lo desee, ¡ pero no necesita conocer algo de encriptación para ser un usuario feliz!</p> </li> </ul> </li> <li> <a href=\"http://www.clipperz.com\" target=\"_blank\">Aprender más</a> </li> </ul> ",
+'loginFormTitle': "ingrese con su usuario Clipperz",
+'loginFormUsernameLabel': "usuario",
+'loginFormPassphraseLabel': "frase clave",
+'loginFormDontHaveAnAccountLabel': "¿no tiene una cuenta?",
+'loginFormCreateOneLabel': "crear una",
+'loginFormForgotYourCredentialsLabel': "¿perdió sus credenciales?",
+'loginFormAarghThatsBadLabel': "¡Ahhh! ¡eso es malo!",
+'loginFormAfraidOfMaliciousScriptsLabel': "¿evitar scripts maliciosos?",
+'loginFormVerifyTheCodeLabel': "verificar el código",
+'loginFormButtonLabel': "Ingresar",
+'loginFormOneTimePasswordCheckboxLabel': "usar una frase clave desechable",
+'loginPanelSwithLanguageDescription': "<h5>Cambiar a su lenguaje preferido</h5> ",
+'browserCompatibilityDescription': "<p>Obtenga una mejor y más segura experiencia con Firefox. De todas maneras Clipperz funciona también con Opera y MS Explorer!</p> ",
+'OTPloginMessagePanelInitialTitle': "Ingresar usando una frase clave desechable",
+'OTPloginMessagePanelInitialText': "Enviando credenciales OTP ...",
+'OTPloginMessagePanelLoadingTitle': "Ingresar usando una frase clave desechable",
+'OTPloginMessagePanelLoadingText': "Descargando datos de autenticación encriptados desde el servidor ...",
+'OTPloginMessagePanelProcessingTitle': "Ingresar usando una frase clave desechable",
+'OTPloginMessagePanelProcessingText': "Desencriptación local de datos de autenticación ...",
+'loginMessagePanelInitialTitle': "Ingresando ...",
+'loginMessagePanelInitialButtonLabel': "Cancelar",
+'loginMessagePanelConnectedTitle': "Conectado",
+'loginMessagePanelConnectedText': "Hecho",
+'loginMessagePanelFailureTitle': "Error",
+'loginMessagePanelFailureText': "Ingreso fallido",
+'loginMessagePanelFailureButtonLabel': "Cerrar",
+'connectionLoginSendingCredentialsMessageTitle': "Verificando credenciales",
+'connectionLoginSendingCredentialsMessageText': "Enviando credenciales",
+'connectionLoginCredentialsVerificationMessageTitle': "Verificando credenciales",
+'connectionLoginCredentialsVerificationMessageText': "Realizando una autenticación SRP",
+'connectionLoginDoneMessageTitle': "Verificando credenciales",
+'connectionLoginDoneMessageText': "Conectado",
+'userLoginPanelUpgradingUserCredentialsMessageTitle': "Verificando credenciales",
+'userLoginPanelUpgradingUserCredentialsMessageText': "Actualizando sus credenciales al nuevo esquema de autenticación",
+'userLoginPanelConnectedMessageTitle': "Usuario autenticado",
+'userLoginPanelConnectedMessageText': "Exitosamente logueado",
+'userLoginPanelTryingAnOlderConnectionSchemaMessageTitle': "Verifying credentials",
+'userLoginPanelTryingAnOlderConnectionSchemaMessageText': "Probando un esquema de autenticación antiguo",
+'userLoginPanelLoadingUserDataMessageTitle': "Usuario autenticado",
+'userLoginPanelLoadingUserDataMessageText': "Descargando encabezamientos encriptados desde Clipperz",
+'userLoginPanelDecryptingUserDataMessageTitle': "Usuario autenticado",
+'userLoginPanelDecryptingUserDataMessageText': "Desencriptación local de datos",
+'userLoginPanelDecryptingUserStatisticsMessageTitle': "Usuario autenticado",
+'userLoginPanelDecryptingUserStatisticsMessageText': "Desencriptación local de estadísticas de uso",
+'splashAlertTitle': "¡Bienvenido a Clipperz!",
+'splashAlertText': "<p>Algunas advertencias sobre seguridad</p> <ul> <li> <p>Almacenar sus datos en Clipperz es tan seguro como la frase clave que usted elija para protegerlos. Nadie puede acceder a ellos a no ser que conozca la frase clave.</p> </li> <li> <p>Si usted va a usar Clipperz para guardar información sensible y crítica, esté seguro de elegir una frase clave fuerte. ¡Cuanto más larga mejor!</p> </li> <li> <p>Clipperz no le permitirá recuperar una frase clave perdida.</p> </li> </ul> <p>Si necesita más información, por favor visite el sitio de <a href=\"http://www.clipperz.com\" target=\"_blank\">Clipperz</a>.</p> ",
+'splashAlertCloseButtonLabel': "Aceptar",
+'registrationFormTitle': "Abrir su cuenta",
+'registrationFormUsernameLabel': "usuario",
+'registrationFormPassphraseLabel': "frase clave",
+'registrationFormRetypePassphraseLabel': "reingrese la frase clave",
+'registrationFormSafetyCheckLabel': "Yo entiendo que Clipperz no me permite recuperar frases clave perdidas",
+'registrationFormTermsOfServiceCheckLabel': "He leído y estoy de acuerdo con los <a href='http://www.clipperz.com/terms_of_service' target='_blank'>Términos de Servicio</a>.",
+'registrationFormDoYouAlreadyHaveAnAccountLabel': "¿usted ya tiene una cuenta?",
+'registrationFormSimplyLoginLabel': "ingreso simple",
+'registrationFormButtonLabel': "Registrarse",
+'registrationFormWarningMessageNotMatchingPassphrases': "Su frase clave no coincide, por favor reescríbala.",
+'registrationFormWarningMessageSafetyCheckNotSelected': "Por favor, lea y chequee todas las casillas debajo.",
+'registrationFormWarningMessageTermsOfServiceCheckNotSelected': "Usted necesita estar de acuerdo con los Términos de Servicio.",
+'registrationMessagePanelInitialTitle': "Creando cuenta ...",
+'registrationMessagePanelInitialButtonLabel': "Cancelar",
+'registrationMessagePanelRegistrationDoneTitle': "Registración",
+'registrationMessagePanelRegistrationDoneText': "Hecho",
+'registrationMessagePanelFailureTitle': "Registración fallada",
+'registrationMessagePanelFailureButtonLabel': "Cerrar",
+'connectionRegistrationSendingRequestMessageText': "Verificando credenciales",
+'connectionRegistrationSendingCredentialsMessageText': "Enviando credenciales",
+'registrationSplashPanelTitle': "Aviso de seguridad",
+'registrationSplashPanelDescriptionConfig': "<p>Estas son sus credenciales de Clipperz, cuídelas. ¡Clipperz nunca más le mostrará su cuenta y frase clave por segunda vez!</p> ",
+'registrationSplashPanelUsernameLabel': "usuario",
+'registrationSplashPanelPassphraseLabel': "frase clave",
+'registrationSplashPanelShowPassphraseButtonLabel': " mostrar frase clave",
+'donateHeaderLinkLabel': "donaciones",
+'creditsHeaderLinkLabel': "créditos",
+'feedbackHeaderLinkLabel': "contacto",
+'helpHeaderLinkLabel': "ayuda",
+'forumHeaderLinkLabel': "foro",
+'recordMenuLabel': "tarjetas",
+'accountMenuLabel': "cuenta",
+'dataMenuLabel': "datos",
+'contactsMenuLabel': "contactos",
+'toolsMenuLabel': "herramientas",
+'logoutMenuLabel': "salir",
+'lockMenuLabel': "bloquear",
+'lockTitle': "La cuenta está bloqueada",
+'lockDescriptionConfig': "<p>Para desbloquear su cuenta, por favor ingrese su frase clave</p> ",
+'unlockButtonLabel': "desbloquear",
+'changePasswordTabLabel': "Cambiar su frase clave",
+'changePasswordTabTitle': "Cambiar su frase clave",
+'changePasswordFormUsernameLabel': "usuario",
+'changePasswordFormOldPassphraseLabel': "frase clave anterior",
+'changePasswordFormNewPassphraseLabel': "nueva frase clave",
+'changePasswordFormRetypePassphraseLabel': "reingrese su nueva frase clave",
+'changePasswordFormSafetyCheckboxLabel': "Yo entiendo que Clipperz no me permite recuperar una frase clave perdida.",
+'changePasswordFormSubmitLabel': "Cambiar",
+'changePasswordFormWrongUsernameWarning': "Usuario incorrecto",
+'changePasswordFormWrongPassphraseWarning': "Frase clave incorrecta",
+'changePasswordFormWrongRetypePassphraseWarning': "Sus frases claves no coinciden, por favor reescríbalas.",
+'changePasswordFormSafetyCheckWarning': "Por favor lea y seleccione la casilla de abajo.",
+'changePasswordFormProgressDialogTitle': "Cambiando credenciales de usuario",
+'changePasswordFormProgressDialogConnectedMessageTitle': "Conectado",
+'changePasswordFormProgressDialogConnectedMessageText': "Hecho",
+'changePasswordFormProgressDialogErrorMessageTitle': "Error",
+'changePasswordFormProgressDialogErrorMessageText': "¡Cambio de credenciales fallado!",
+'changeCredentialsPanelEncryptingDataMessageTitle': "Cambiando su frase clave",
+'changeCredentialsPanelEncryptingDataMessageText': "Encriptación local de encabezados de tarjetas",
+'changeCredentialsPanelCreatingNewCredentialsMessageTitle': "Cambiando su frase clave",
+'changeCredentialsPanelCreatingNewCredentialsMessageText': "Actualizando su credenciales",
+'changeCredentialsPanelSendingNewCredentialsToTheServerMessageTitle': "Cambiando su frase clave",
+'changeCredentialsPanelSendingNewCredentialsToTheServerMessageText': "Subiendo sus credenciales encriptadas a Clipperz",
+'changeCredentialsPanelDoneMessageTitle': "Cambiando su frase clave",
+'changeCredentialsPanelDoneMessageText': "Hecho",
+'manageOTPTabLabel': "Administrar su frases clave desechables",
+'manageOTPTabTitle': "Administrar su frases clave desechables",
+'manageOTPTabDescription': "<p>Una frase clave desechable uso funciona como una frase clave regular, pero puede ser usada solo una vez.</p> <p>Si las misma frase clave es usada nuevamente en un segundo intento de acceso, esta será rechazada y el proceso de acceso fallará.</p> <p>Inmediatamente después de un acceso exitoso, su on-time frase clave será borrada previniendo accesos fraudulentos.</p> <p>Frases claves desechables son una excelente elección para protegerse de keyloggers y spywares, que pueden recolectar datos desde máquinas comprometidas.</p> <p> <b>Le recomendamos muy fuertemente que use frases claves desechables uso cuando acceda a Clipperz desde terminales públicas, como Internet Cafés, Cybercafés y bibliotecas.</b> </p> ",
+'oneTimePasswordReadOnlyMessage': "<h6>¡Disculpe!</h6> <p>Usted no puede usar su frases clave desechables mientras usa la versión fuera de línea de Clipperz.</p> ",
+'oneTimePasswordLoadingMessage': "<h6>Cargando datos</h6> <p>Por favor espere ...</p> ",
+'oneTimePasswordNoPasswordAvailable': "<h6>No hay frase clave desechables disponible</h6> <p>Haga click en el botón “Nueva” para agregar una frase clave desechables a su cuenta.</p> ",
+'createNewOTPButtonLabel': "Nueva",
+'deleteOTPButtonLabel': "Borrar",
+'printOTPButtonLabel': "Imprimir",
+'disabledOneTimePassword_warning': "desabilitado",
+'oneTimePasswordSelectionLink_selectLabel': "Seleccionar:",
+'oneTimePasswordSelectionLink_all': "todo",
+'oneTimePasswordSelectionLink_none': "ninguna",
+'oneTimePasswordSelectionLink_used': "usada",
+'oneTimePasswordSelectionLink_unused': "sin uso",
+'saveOTP_encryptUserDataTitle': "Guardando frase clave desechable",
+'saveOTP_encryptUserDataText': "Procesando nuevas credenciales OTP ...",
+'saveOTP_encryptOTPDataTitle': "Guardando frase clave desechable",
+'saveOTP_encryptOTPDataText': "Encriptación local de datos de autenticación ...",
+'saveOTP_sendingDataTitle': "Guardando frase clave desechable",
+'saveOTP_sendingDataText': "Enviando datos de autenticación al servidor ...",
+'saveOTP_updatingInterfaceTitle': "Guardando frase clave desechable",
+'saveOTP_updatingInterfaceText': "Actualizando interface ...",
+'accountPreferencesLabel': "Preferencias",
+'accountPreferencesTabTitle': "Preferencias",
+'accountPreferencesLanguageTitle': "Seleccione el lenguaje",
+'accountPreferencesLanguageDescription': "<p>Elija su lenguaje preferido de la siguiente lista.<p> ",
+'showDonationReminderPanelTitle': "Recordatorios de donaciones",
+'showDonationReminderPanelDescription': "<p>Mostrar recordatorios de donaciones</p> ",
+'accountPreferencesInterfaceTitle': "Personalización de la interface",
+'accountPreferencesInterfaceDescription': "<p>Ajuste Clipperz a sus necesidades.</p> ",
+'saveUserPreferencesFormSubmitLabel': "Guardar",
+'cancelUserPreferencesFormSubmitLabel': "Cancelar",
+'accountPreferencesSavingPanelTitle_Step1': "Guardando preferencias",
+'accountPreferencesSavingPanelText_Step1': "Encriptación local de sus preferencias",
+'accountPreferencesSavingPanelTitle_Step2': "Guardando preferencias",
+'accountPreferencesSavingPanelText_Step2': "Enviando preferencias encriptadas a Clipperz",
+'accountLoginHistoryLabel': "Historial de accesos",
+'loginHistoryTabTitle': "Historial de accesos",
+'loginHistoryReadOnlyMessage': "<h6>¡Perdón!</h6> <p>El historial de acceso no está disponible mientras usa la versión fuera de línea de Clipperz.</p> ",
+'loginHistoryLoadingMessage': "<h6>Cargando datos</h6> <p>Por favor espere ...</p> ",
+'loginHistoryLoadedMessage': "<h6>Sus últimos 10 accesos</h6> <p> </p> ",
+'loginHistoryIPLabel': "IP",
+'loginHistoryTimeLabel': "fecha",
+'loginHistoryCurrentSessionText': "sesión actual",
+'loginHistoryReloadButtonLabel': "Refrescar historial de acceso",
+'deleteAccountTabLabel': "Borrar su cuenta",
+'deleteAccountTabTitle': "Borrar su cuenta",
+'deleteAccountFormUsernameLabel': "usuario",
+'deleteAccountFormPassphraseLabel': "frase clave",
+'deleteAccountFormSafetyCheckboxLabel': "Yo entiendo que todos mis datos serán borrados y que esta acción es irreversible.",
+'deleteAccountFormSubmitLabel': "Borrar mi cuenta",
+'deleteAccountFormWrongUsernameWarning': "Usuario incorrecto",
+'deleteAccountFormWrongPassphraseWarning': "Frase clave incorrecta",
+'deleteAccountFormSafetyCheckWarning': "Por favor, léa y marque la opción debajo.",
+'accountPanelDeletingAccountPanelConfirmationTitle': "ATENCIÓN",
+'accountPanelDeleteAccountPanelConfirmationText': "¿Esta Ud. seguro que desea borrar esta cuenta?",
+'accountPanelDeleteAccountPanelConfirmButtonLabel': "Sí",
+'accountPanelDeleteAccountPanelDenyButtonLabel': "No",
+'offlineCopyTabLabel': "Copia fuera de línea",
+'offlineCopyTabTitle': "Copia fuera de línea",
+'offlineCopyTabDescription': "<p>Con solo un clik usted puede descargar todos sus datos encriptados desde los servidores de Clipperz a su disco rígido y crear una versión solo-lectura fuera de línea para ser usada cuando usted no está conectado a Internet.</p> <p>La versión solo-lectura es tan segura como la lectura-escritura y no expondrá sus datos a mayores riegos desde el momento que ambas comparten el mismo código y arquitectura de seguridad.</p> <ol> <li> <p>Haga click en el link debajo para comenzar la descarga.</p> </li> <li> <p>El navegador le preguntará que hacer con el archivo “Clipperz_YYYYMMDD.html”. Guárdelo en su disco rígido.</p> </li> <li> <p>Haga doble click en el archivo descargado para ejecutar la versión fuera de línea en su navegador.</p> </li> <li> <p>Ingrese el usuario y la frase clave habitual.</p> </li> </ol> ",
+'offlineCopyDownloadLinkLabel': "Descargar",
+'offlineCopyDownloadWarning': "<h4> <a href=\"#\" id=\"offlineCopyDownloadWarningLink\">¡Actualize su “copia fuera de línea”!</a> </h4> <p>Usted ha recientemente creado o modificado una o más tarjetas, podría ser necesario que realize una nueva “copia fuera de línea”.</p> ",
+'sharingTabLabel': "Compartir",
+'sharingTabTitle': "Compartir",
+'sharingTabDescription': "<p>Muy frecuentemente una pieza de información confidencial necesita ser compartida con una o más personas.</p> <p>Esto debería ser tan simple como darle a sus colegas el accese al código de su casilla de voz cuando está fuera de la oficina, o tan complicado con habilitarles a sus herederos el derecho de acceder a su caja de seguridad en su banco.</p> <p>Clipperz puede permitirle compartir sus secretos de una forma segura y directa.</p> <p> </p> <p> <b>Proximamente ...</b> </p> ",
+'importTabLabel': "Importar",
+'importTabTitle': "Importar",
+'importTabDescription': "<p> <b>Proximamente ...</b> </p> ",
+'printingTabLabel': "Exportar",
+'printingTabTitle': "Exportar",
+'printingTabDescription': "<p> <b>Imprima sus datos</b> </p> <p>Haciendo click en el enlace que sigue se abrirá una nueva ventana mostrando todas sus tarjetas en un formato imprimible.</p> <p>Si usted está imprimiendo con propósitos de respaldo, por favor considere la opción más segura provista por la creación de una “copia fuera de línea”.</p> ",
+'printingLinkLabel': "Versión imprimible",
+'contactsTabLabel': "Contactos",
+'contactsTabTitle': "Contactos",
+'passwordGeneratorTabLabel': "Generador de contraseñas",
+'passwordGeneratorTabTitle': "Generador de contraseñas",
+'paswordGeneratorTabDescriptionConfig': "<p> </p> ",
+'passwordGeneratorTabButtonLabel': "Generar contraseña",
+'bookmarkletTabLabel': "Bookmarklet",
+'bookmarkletTabTitle': "Bookmarklet",
+'bookmarkletTabDescription': "<p>Un bookmarklet es una simple herramienta de \"un click\" que puede realizar tareas muy útiles. Este puede ser grabado y usado como un marcador normal de una página web.</p> <p>El Clipperz bookmarklet le ayudará a usted a crear rapidamente tarjetas nuevas y accesos directos dentro de las tarjetas existentes.</p> <p> <b>Por favor tenga en cuenta que el bookmarklet no incluye ninguna información relacionadas con su cuenta (ej: su nombre de usuario o clave), el bookmarklet es una herramienta general que contiene el mismo código para todos los usuarios de Clipperz.</b> </p> <h3>How to install the bookmarklet</h3> <h5>Firefox, Camino, Opera, Safari</h5> <ol> <li> <p>Asegúrese que la “Barra de marcadores” está mostrada seleccionando “Ver > Barra de herramientas > Barra de marcadores”, menú similar, desde el menú del navegador.</p> </li> <li> <p>Arrastre el enlace “Agregar a Clipperz” sobre la barra de marcadores.</p> </li> </ol> <h5>Internet Explorer</h5> <ol> <li> <p>Asegúrese que la barra “Vínculos” es mostrada seleccionando “Ver > Barra de Herramientas > Herramientas > Vínculos” desde el menú del navegador.</p> </li> <li> <p>Haga click con el botón derecho del mouse en el link “Agregar a Clipperz”.</p> </li> <li> <p>Seleccione “Agregar a favoritos” desde el menú contextual.</p> </li> <li> <p>Haga click en “Si” o “Acepto” a cualquier advertencia de seguridad que le aparezca.</p> </li> <li> <p>Abra la carpeta “Vínculos” y haga click en “OK”</p> </li> </ol> ",
+'bookmarkletTabBookmarkletTitle': "Agregar a Clipperz",
+'bookmarkletTabInstructions': "<h3>Como crear una nueva tarjeta que incluya un enlace de “acceso directo” a un servicio en línea.</h3> <ol> <li> <p>Abra una página web dónde el formulario de logueo está almacenado (es la página donde usualmente ingresa sus credenciales firmadas)</p> </li> <li> <p>Ejecute el bookmarklet haciendo click en éste: una ventana emergente (pop-up) aparecerá sobre la página web.</p> </li> <li> <p>Copie al portapapeles el contenido de todo el texto dentro de la ventana emergente (pop-up) (Ctrl-C)</p> </li> <li> <p>Ingrese en su cuenta Clipperz y haga click en el botón <b>Agregar nueva tarjeta</b>.</p> </li> <li> <p>Seleccione la plantilla “Acceso directo” y pegue el contenido del portapapeles en el formulario (Ctrl-V)</p> </li> <li> <p>Haga click en el botón <b>Crear</b>, revise los datos y luego haga click en <b>Guardar</b>.</p> </li> </ol> <h3>Cómo agregar un enlace “acceso directo” a una tarjeta existente</h3> <ol> <li> <p>Igual que arriba.</p> </li> <li> <p>Igual que arriba.</p> </li> <li> <p>Igual que arriba.</p> </li> <li> <p>Ingrese en su cuenta Clipperz y seleccione una tarjeta conteniendo las credenciales de un servicio web que usted visitó y haga click en el botón <b>Editar</b>.</p> </li> <li> <p>Pegue el contenido del portapapeles en el área de texto de la sección “Acceso directo” (Ctrl-V)</p> </li> <li> <p>Haga click en el botón <b>Agregar acceso directo</b>, revise los detalles y luego haga click en <b>Guardar</b>.</p> </li> </ol> <p> </p> <p>Más información sobre bookmarklet está <a href=\"http://www.clipperz.com/support/user_guide/bookmarklet\" target=\"_blank\">disponible aquí</a>.</p> ",
+'mainPanelDirectLoginBlockLabel': "Accesos directos",
+'directLinkReferenceShowButtonLabel': "ver",
+'mainPanelDirectLoginBlockDescription': "<p>¡ Agregar “accesos directos” para ingresar en sus cuentas de la web sin necesidad de escribir nombres de usuarios o claves!</p> <p>“Accesos directos” incrementa notablemente la seguridad de sus claves desde que ud. puede:</p> <ul> <li> <p>usar claves complejas con comodidad;</p> </li> <li> <p>nunca más reusar la misma clave simple.</p> </li> </ul> <p> </p> <a href=\"http://www.clipperz.com/support/user_guide/direct_logins\" target=\"_blank\">Apreender más sobre “accesos directos”</a> ",
+'mainPanelRecordsBlockLabel': "Tarjetas",
+'mainPanelAddRecordButtonLabel': "Agregar tarjeta nueva",
+'mainPanelRemoveRecordButtonLabel': "Borrar tarjeta",
+'mainPanelRecordFilterBlockAllLabel': "todo",
+'mainPanelRecordFilterBlockTagsLabel': "tags",
+'mainPanelRecordFilterBlockSearchLabel': "buscar",
+'recordDetailNoRecordAtAllTitle': "¡Bienvenido a Clipperz!",
+'recordDetailNoRecordAtAllDescription': "<h5>Comienze agregando tarjetas a su cuenta.</h5> <p>Tarjetas son formularios simples y flexibles donde Usted puede almacenar sus claves y cualquier otro dato confidencial.</p> <p>Tarjetas pueden contener credenciales para acceder a un sitio web, la conbinación del candado de su bicicleta, detalles de su tarjeta de crédito, ....</p> <h5>¡No olvide los bookmarklet!</h5> <p>Antes de comenzar, instale el “Agregar a Clipperz” bookmarklet: esta hará la creación de tarjetas más fácil y más divertida.</p> <p>Vaya al marcador “herramientas” para descubrir como instalar y usarlo.</p> <p> </p> <p>Luego simplemente haga click en el botón “Agregar nueva tarjeta” y disfrute su cuenta Clipperz.</p> <p> </p> <a href=\"http://www.clipperz.com/support/user_guide/managing_cards\" target=\"_blank\">Apreender más acerca de la creación y administración de las tarjetas</a> ",
+'newRecordWizardTitleBox': "<h5>Por favor seleccione una plantilla</h5> <p>Tarjetas son formularios simples y flexibles donde usted puede almacenar claves y cualquier otro dato confidencial.</p> <p>Comienze eligiendo una de las plantillas que se encuentran debajo. Usted siempre puede personalizar sus tarjetas más tarde agregando o borrando campos.</p> ",
+'newRecordWizardBookmarkletConfigurationTitle': "Acceso directo",
+'newRecordWizardBookmarkletConfigurationDescription': "<p>Pegue debajo el código de configuración generado por el bookmarklet Clipperz.</p> <p>Una nueva tarjeta con un acceso directo a su cuenta web será creada.</p> ",
+'newRecordWizardCreateButtonLabel': "Crear",
+'newRecordWizardCancelButtonLabel': "Cancelar",
+'donateSplashPanelTitle': "¡Apoye a Clipperz, haga una donación hoy!",
+'donateSplashPanelDescription': "<p>Una pocas buenas razones para hacer una donación:</p> <ul> <li> <p>apoyar el desarrollo de nuevas utilidades</p> </li> <li> <p>mantener Clipperz gratuito</p> </li> <li> <p>mostrar su aprecio por nuestro duro trabajo</p> </li> </ul> <p>Por cualquier información adicional, por favor visite nuestra <a href=\"http://www.clipperz.com/donations\" target=\"_blank\">página de donaciones</a>.</p> <p> <b>¿Listo para hacer una donación?</b> </p> ",
+'donateCloseButtonLabel': "No todavía",
+'donateDonateButtonLabel': "Si",
+'recordTemplates': {
+ 'WebAccount': {
+ 'title': "Contraseña web",
+ 'description': "<p>Una simple tarjeta para almacenar sus credenciales de acceso a sus servicios online.</p> ",
+ 'fields': {
+ 'URL': "Dirección web",
+ 'TXT': "Usuario o correo electrónico",
+ 'PWD': "Contraseña"
+ }
+ },
+ 'BankAccount': {
+ 'title': "Cuenta bancaria",
+ 'description': "<p>Almacene en forma segura su número de cuenta bancaria y credenciales de servicios bancarios en línea.</p> ",
+ 'fields': {
+ 'TXT': "Banco",
+ 'TXT': "Número de cuenta",
+ 'URL': "Sitio web del Banco",
+ 'TXT': "ID del servicio bancario en línea",
+ 'PWD': "Contraseña del servicio bancario en línea"
+ }
+ },
+ 'CreditCard': {
+ 'title': "Tarjeta de crédito",
+ 'description': "<p>Número de tarjeta, fecha de vencimiento, CVV2 y PIN siempre a mano con Clipperz.</p> ",
+ 'fields': {
+ 'TXT': "Tipo (Visa, AmEx, ...)",
+ 'TXT': "Número",
+ 'TXT': "Nombre del propietario",
+ 'TXT': "Fecha de vencimiento",
+ 'TXT': "CVV2",
+ 'PWD': "PIN cajero automático",
+ 'URL': "Sitio web tarjeta",
+ 'TXT': "Usuario",
+ 'PWD': "Contraseña"
+ }
+ },
+ 'AddressBookEntry': {
+ 'title': "Libreta de direcciones",
+ 'description': "<p>Clipperz puede también funcionar como su nueva libreta privada de direcciones. Use esta plantilla para crear fácilmente nuevas entradas.</p> ",
+ 'fields': {
+ 'TXT': "Nombre",
+ 'TXT': "Correo electrónico",
+ 'TXT': "Teléfono",
+ 'TXT': "Móvil",
+ 'ADDR': "Dirección"
+ }
+ },
+ 'Custom': {
+ 'title': " Tarjeta personalizada",
+ 'description': "<p>No importa que tipo de dato confidencial usted necesita proteger, puede crear la tarjeta que necesite.</p> ",
+ 'fields': {
+ 'TXT': "Etiqueta 1",
+ 'TXT': "Etiqueta 2",
+ 'TXT': "Etiqueta 3"
+ }
+ }
+},
+'recordFieldTypologies': {
+ 'TXT': {
+ 'description': "simple text field",
+ 'shortDescription': "texto"
+ },
+ 'PWD': {
+ 'description': "simple text field, with default status set to hidden",
+ 'shortDescription': "contraseña"
+ },
+ 'URL': {
+ 'description': "simple text field in edit mode, that became an active url in view mode",
+ 'shortDescription': "dirección web"
+ },
+ 'DATE': {
+ 'description': "a value set with a calendar helper",
+ 'shortDescription': "fecha"
+ },
+ 'ADDR': {
+ 'description': "just like the URL, but the active link points to Google Maps (or similar service) passing the address value as argument",
+ 'shortDescription': "dirección postal"
+ },
+ 'CHECK': {
+ 'description': "check description",
+ 'shortDescription': "check"
+ },
+ 'RADIO': {
+ 'description': "radio description",
+ 'shortDescription': "radio"
+ },
+ 'SELECT': {
+ 'description': "select description",
+ 'shortDescription': "select"
+ }
+},
+'newRecordPanelGeneralExceptionTitle': "Error",
+'newRecordPanelGeneralExceptionMessage': "El texto de configuración no es válido. Asegúrese que toma su texto desde la ventana emergente del bookmarklet.",
+'newRecordPanelWrongBookmarkletVersionExceptionTitle': "Error",
+'newRecordPanelWrongBookmarkletVersionExceptionMessage': "El texto de configuración ha sido generado por una versión anterior de bookmarklet. Por favor actualize su bookmarklet y pruebe nuevamente.",
+'newRecordPanelExceptionPanelCloseButtonLabel': "Cancelar",
+'mainPanelDeletingRecordPanelConfirmationTitle': "Eliminando tarjeta seleccionada",
+'mainPanelDeleteRecordPanelConfirmationText': "¿Desea realmente eliminar la tarjeta seleccionada?",
+'mainPanelDeleteRecordPanelConfirmButtonLabel': "Sí",
+'mainPanelDeleteRecordPanelDenyButtonLabel': "No",
+'mainPanelDeletingRecordPanelInitialTitle': "Eliminando tarjeta seleccionada",
+'mainPanelDeletingRecordPanelCompletedText': "Hecho",
+'deleteRecordPanelCollectRecordDataMessageTitle': "Eliminar tarjeta",
+'deleteRecordPanelCollectRecordDataMessageText': "Actualizando lista de tarjetas",
+'deleteRecordPanelEncryptUserDataMessageTitle': "Eliminar tarjeta",
+'deleteRecordPanelEncryptUserDataMessageText': "Encriptación local de encabezamiento de tarjetas",
+'deleteRecordPanelSendingDataToTheServerMessageTitle': "Eliminar tarjeta",
+'deleteRecordPanelSendingDataToTheServerMessageText': "Subiendo encabezamiento de tarjetas encriptadas a Clipperz",
+'deleteRecordPanelUpdatingTheInterfaceMessageTitle': "Eliminar tarjeta",
+'deleteRecordPanelUpdatingTheInterfaceMessageText': "Actualizando interface",
+'recordDetailNoRecordSelectedTitle': "No hay tarjetas seleccionadas",
+'recordDetailNoRecordSelectedDescription': "<p>Por favor seleccione una tarjeta de la lista de la izquierda.</p> ",
+'recordDetailLoadingRecordMessage': "Descargando tarjetas encriptadas desde Clipperz",
+'recordDetailDecryptingRecordMessage': "Desencriptación local de los datos de las tarjetas",
+'recordDetailLoadingRecordVersionMessage': "Descargando última versión de la tarjeta",
+'recordDetailDecryptingRecordVersionMessage': "Desencriptación local de la última versión",
+'recordDetailLoadingErrorMessageTitle': "Error mientras descargaba la tarjeta",
+'recordDetailNotesLabel': "Notas",
+'recordDetailLabelFieldColumnLabel': "Campo título",
+'recordDetailDataFieldColumnLabel': "Campo de datos",
+'recordDetailTypeFieldColumnLabel': "Tipo",
+'recordDetailSavingChangesMessagePanelInitialTitle': "Guardando tarjeta",
+'recordDetailAddFieldButtonLabel': "Agregar nuevo campo",
+'recordDetailPasswordFieldHelpLabel': "para copiar la contraseña al portapapeles, haga click en la estrella y luego Ctrl-C",
+'recordDetailPasswordFieldScrambleLabel': "ocultar",
+'recordDetailPasswordFieldUnscrambleLabel': "mostrar",
+'recordDetailDirectLoginBlockTitle': "Acceso directos",
+'recordDetailNewDirectLoginDescription': "<p>Configuración de los accesos directos</p> ",
+'recordDetailDirectLoginBlockNoDirectLoginConfiguredDescription': "<p>¿Esta tarjeta contiene credenciales para acceder a un servicio en línea?</p> <p>¡Use los bookmarklet para configurar un \"acceso directo\" desde Clpperz con solo un click!</p> ",
+'recordDetailAddNewDirectLoginButtonLabel': "Agregar nuevo acceso directo",
+'recordDetailEditButtonLabel': "Editar",
+'recordDetailSaveButtonLabel': "Guardar",
+'recordDetailCancelButtonLabel': "Cancelar",
+'newRecordTitleLabel': "_nueva tarjeta_",
+'recordSaveChangesPanelCollectRecordInfoMessageTitle': "Guardar tarjeta",
+'recordSaveChangesPanelCollectRecordInfoMessageText': "Actualizando encabezamiento de tarjetas",
+'recordSaveChangesPanelEncryptUserDataMessageTitle': "Guardar tarjeta",
+'recordSaveChangesPanelEncryptUserDataMessageText': "Encriptación local de encabezamiento de tarjetas",
+'recordSaveChangesPanelEncryptRecordDataMessageTitle': "Guardar tarjeta",
+'recordSaveChangesPanelEncryptRecordDataMessageText': "Encriptación local de los datos de la tarjeta",
+'recordSaveChangesPanelEncryptRecordVersionDataMessageTitle': "Guardar tarjeta",
+'recordSaveChangesPanelEncryptRecordVersionDataMessageText': "Encriptación local de la versión de los datos de la tarjeta",
+'recordSaveChangesPanelSendingDataToTheServerMessageTitle': "Guardar tarjeta",
+'recordSaveChangesPanelSendingDataToTheServerMessageText': "Subiendo encabezamiento de tarjeta encriptada a Clipperz",
+'recordSaveChangesPanelUpdatingTheInterfaceMessageTitle': "Guardar tarjeta",
+'recordSaveChangesPanelUpdatingTheInterfaceMessageText': "Actualizando la interface",
+'passwordGeneratorPanelTitle': "Generador de contraseñas",
+'passwordGeneratorPanelOkLabel': "Ok",
+'passwordGeneratorPanelCancelLabel': "Cancelar",
+'passwordGeneratorLengthLabel': "longitud:",
+//'DWRUtilLoadingMessage': "Cargando datos ...",
+'comingSoon': "próximamente ...",
+'panelCollectingEntryopyMessageText': "Recogiendo entropía",
+'directLoginConfigurationCheckBoxFieldSelectedValue': "Sí",
+'directLoginConfigurationCheckBoxFieldNotSelectedValue': "No",
+'WELCOME_BACK': "¡Bienvenido!",
+'currentConnectionText': "Usted está ahora conectado desde ip&nbsp;__ip__, aparentemente desde __country__, usando __browser__ en __operatingSystem__.",
+'latestConnectionText': "Su última conexión fue __elapsedTimeDescription__ (__time__) desde ip&nbsp;__ip__, aparentemente desde __country__, usando __browser__ en __operatingSystem__.",
+'fullLoginHistoryLinkLabel': "mostrar historial de acceso",
+'elapsedTimeDescriptions': {
+ 'MORE_THAN_A_MONTH_AGO': "más de un mes atrás",
+ 'MORE_THAN_A_WEEK_AGO': "más de una semana atrás",
+ 'MORE_THAN_*_WEEKS_AGO': "más de __elapsed__ semanas atrás",
+ 'YESTERDAY': "ayer",
+ '*_DAYS_AGO': "__elapsed__ días atrás",
+ 'ABOUT_AN_HOUR_AGO': "about an hour ago",
+ '*_HOURS_AGO': "__elapsed__ hours ago",
+ 'JUST_A_FEW_MINUTES_AGO': "hace unos minutos",
+ 'ABOUT_*_MINUTES_AGO': "hace __elapsed__ minutos atrás"
+},
+'unknown_ip': "desconocida",
+'calendarStrings': {
+ 'months': {
+ '0': "Enero",
+ '1': "Febrero",
+ '2': "Marzo",
+ '3': "Abril",
+ '4': "Mayo",
+ '5': "Junio",
+ '6': "Julio",
+ '7': "Agosto",
+ '8': "Setiembre",
+ '9': "Octubre",
+ '10': "Noviembre",
+ '11': "Diciembre"
+ },
+ 'shortMonths': {
+ '0': "Ene",
+ '1': "Feb",
+ '2': "Mar",
+ '3': "Abr",
+ '4': "May",
+ '5': "Jun",
+ '6': "Jul",
+ '7': "Ago",
+ '8': "Set",
+ '9': "Oct",
+ '10': "Nov",
+ '11': "Dic"
+ },
+ 'days': {
+ '0': "Domingo",
+ '1': "Lunes",
+ '2': "Martes",
+ '3': "Miércoles",
+ '4': "Jueves",
+ '5': "Viernes",
+ '6': "Sábado"
+ },
+ 'shortDays': {
+ '0': "Dom",
+ '1': "Lun",
+ '2': "Mar",
+ '3': "Mie",
+ '4': "Jue",
+ '5': "Vie",
+ '6': "Sab"
+ },
+ 'veryShortDays': {
+ '0': "Do",
+ '1': "Lu",
+ '2': "Ma",
+ '3': "Mi",
+ '4': "Ju",
+ '5': "Vi",
+ '6': "Sa"
+ },
+ 'amDesignation': "am",
+ 'pmDesignation': "pm"
+},
+
+__syntaxFix__: "syntax fix"
+});
diff --git a/frontend/beta/js/Clipperz/PM/Strings/Strings_fr-FR.js b/frontend/beta/js/Clipperz/PM/Strings/Strings_fr-FR.js
new file mode 100644
index 0000000..c137fb8
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Strings/Strings_fr-FR.js
@@ -0,0 +1,362 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+Clipperz.PM.Strings.Languages['fr-FR'.toLowerCase()] = MochiKit.Base.merge(Clipperz.PM.Strings.Languages['en-us'], {
+'clipperzServiceDescription': "<h2>Gardez le pour vous!</h2> <ul> <li> <h3>Clipperz est:</h3> <ul> <li> <p>un gestionnaire de mots de passe sécurisé</p> </li> <li> <p>une solution fiable d’authentification unique</p> </li> <li> <p>une chambre forte numérique pour vos données confidentielles</p> </li> </ul> </li> <li> <h3>Avec Clipperz vous pouvez:</h3> <ul> <li> <p>enregistrer et gérer vos mots de passe et autres informations d'identification en ligne</p> </li> <li> <p>vous identifier sur vos sites web sans avoir besoin de saisir votre nom d’utilisateur ou votre mot de passe</p> </li> <li> <p>protéger toutes vos données sensibles: codes d’alarmes, PINs (téléphone portable), carte de crédits, &hellip;</p> </li> <li> <p>partager certaines données confidentielles avec vos proches et vos associés (bientôt disponible!)</p> </li> </ul> </li> <li> <h3>Les avantages de Clipperz:</h3> <ul> <li> <p>c'est gratuit et totalement anonyme</p> </li> <li> <p>accéder à vos données depuis n’importe quel ordinateur</p> </li> <li> <p>vous n'avez besoin d'aucun logiciel et rien n'est à installer sur votre poste</p> </li> <li> <p>cela vous évite de garder des mots de passe sur votre PC ou sur des bouts de papier</p> </li> </ul> </li> <li> <h3>La sécurité de Clipperz:</h3> <ul> <li> <p>vos mots de passe sont localement chiffrés par votre navigateur avant d’être téléchargé à Clipperz</p> </li> <li> <p>la clé de cryptage est une phrase secrète détenue uniquement par vous même</p> </li> <li> <p>héberge vos données sensibles dans des formulaires cryptés et ne peuvent être consultées directement en clair</p> </li> <li> <p>est développé sur des standard de cryptage réputé sans aucune fantaisie ni de bricolage fait maison</p> </li> <li> <p>vous pouvez consulter le code source autant que vous le souhaitez</p> </li> </ul> </li> <li> <a href=\"http://www.clipperz.com\" target=\"_blank\">Plus d’informations</a> </li> </ul> ",
+'loginFormTitle': "identifiez-vous avec votre compte Clipperz",
+'loginFormUsernameLabel': "nom d’utilisateur",
+'loginFormPassphraseLabel': "phrase secrète",
+'loginFormDontHaveAnAccountLabel': "vous n’avez pas de compte?",
+'loginFormCreateOneLabel': "créez votre compte",
+'loginFormForgotYourCredentialsLabel': "vous avez oublié votre certificat?",
+'loginFormAarghThatsBadLabel': "c’est fort dommage pour vous!",
+'loginFormAfraidOfMaliciousScriptsLabel': "vous avez peur des script malicieux?",
+'loginFormVerifyTheCodeLabel': "vérifiez le code",
+'loginFormButtonLabel': "S’identifer",
+'loginPanelSwithLanguageDescription': "<p>Sélectionnez votre langue préféré</p> ",
+'browserCompatibilityDescription': "<p>Have a better and safer Clipperz experience with Firefox. However Clipperz works just fine also with Opera and MS Internet Explorer!</p> ",
+'loginMessagePanelInitialTitle': "En cours d’identification ...",
+'loginMessagePanelInitialButtonLabel': "Annuler",
+'loginMessagePanelConnectedTitle': "Connecté",
+'loginMessagePanelConnectedText': "Terminé",
+'loginMessagePanelFailureTitle': "Erreur",
+'loginMessagePanelFailureText': "Identification échoué",
+'loginMessagePanelFailureButtonLabel': "Fermer",
+'connectionLoginSendingCredentialsMessageTitle': "Vérification des identifiants",
+'connectionLoginSendingCredentialsMessageText': "Envoi des identifiants",
+'connectionLoginCredentialsVerificationMessageTitle': "Vérification des identifiants",
+'connectionLoginCredentialsVerificationMessageText': "Authentification SRP en cours",
+'connectionLoginDoneMessageTitle': "Vérification des identifiants",
+'connectionLoginDoneMessageText': "Connecté",
+'userLoginPanelUpgradingUserCredentialsMessageTitle': "Vérification des identifiants",
+'userLoginPanelUpgradingUserCredentialsMessageText': "Mise à jour de vos identifiants à un nouveau schéma d’authentification",
+'userLoginPanelConnectedMessageTitle': "Utilisateur identifié",
+'userLoginPanelConnectedMessageText': "Vous vous êtes identifié avec succès",
+'userLoginPanelTryingAnOlderConnectionSchemaMessageTitle': "Vérification des identifiants",
+'userLoginPanelTryingAnOlderConnectionSchemaMessageText': "Nous essayons un ancien schéma d’authentification",
+'userLoginPanelLoadingUserDataMessageTitle': "Utilisateur identifié",
+'userLoginPanelLoadingUserDataMessageText': "Téléchargement des cartes d’en-têtes chiffrés depuis Clipperz",
+'userLoginPanelDecryptingUserDataMessageTitle': "Utilisateur identifié",
+'userLoginPanelDecryptingUserDataMessageText': "Décryptage local des en-têtes chiffrés",
+'userLoginPanelDecryptingUserStatisticsMessageTitle': "Utilisateur identifié",
+'userLoginPanelDecryptingUserStatisticsMessageText': "Décryptage local des statistiques",
+'splashAlertTitle': "Bienvenue sur Clipperz!",
+'splashAlertText': "<p>Conseils de sécurité</p> <ul> <li> <p>Le stockage de vos mots de passe sur Clipperz est aussi sécurisé que la phrase que vous avez sélectionnée pour les protéger. Personne ne peux y accéder tant que personne ne connait votre phrase secrète.</p> </li> <li> <p>Si vous allez utiliser Clipperz pour sauvegarder des informations sensibles et critiques assurez-vous d’utiliser une phrase secrète compliquée. Plus elle sera longue mieux ce sera!</p> </li> <li> <p>Clipperz ne sera pas capable de récupérer votre phrase secrète!</p> </li> </ul> <p>Pour toute autre information, veuillez vous référer au site <a href=\"http://www.clipperz.com\" target=\"_blank\">Clipperz</a>.</p> ",
+'splashAlertCloseButtonLabel': "Ok",
+'registrationFormTitle': "créer votre compte",
+'registrationFormUsernameLabel': "nom d’utilisateur",
+'registrationFormPassphraseLabel': "phrase secrète",
+'registrationFormRetypePassphraseLabel': "re-saisissez votre phrase secrète",
+'registrationFormSafetyCheckLabel': "J’accepte que Clipperz ne pourra pas récupérer ma phrase secrète.",
+'registrationFormTermsOfServiceCheckLabel': "J’ai lu et j’accepte les <a href='http://www.clipperz.com/terms_of_service' target='_blank'>Conditions d’Utilisation du Service</a>.",
+'registrationFormDoYouAlreadyHaveAnAccountLabel': "avez-vous déjà un compte?",
+'registrationFormSimplyLoginLabel': "identifiez-vous",
+'registrationFormButtonLabel': "S’inscrire",
+'registrationFormWarningMessageNotMatchingPassphrases': "Vos phrases secrètes ne correspondent pas, veuillez les saisir à nouveau.",
+'registrationFormWarningMessageSafetyCheckNotSelected': "Veuillez lire et cocher les cases-à-cocher ci-dessous.",
+'registrationFormWarningMessageTermsOfServiceCheckNotSelected': "Vous devez accepter les “Conditions d’Utilisation du Service”.",
+'registrationMessagePanelInitialTitle': "Création du compte en cours ...",
+'registrationMessagePanelInitialButtonLabel': "Annuler",
+'registrationMessagePanelRegistrationDoneTitle': "Enregistrement",
+'registrationMessagePanelRegistrationDoneText': "Terminé",
+'registrationMessagePanelFailureTitle': "Enregistrement échoué",
+'registrationMessagePanelFailureButtonLabel': "Fermer",
+'connectionRegistrationSendingRequestMessageText': "Vérification en cours des identifiants",
+'connectionRegistrationSendingCredentialsMessageText': "Envoi des identifiants",
+'registrationSplashPanelTitle': "Conseils de sécurité",
+'registrationSplashPanelDescription': "<p>Ce sont vos identifiants Clipperz, gardez les biens. Clipperz ne va plus jamais vous montrer votre nom d’utilisateur et votre phrase secrète!</p> ",
+'registrationSplashPanelUsernameLabel': "nom d’utilisateur",
+'registrationSplashPanelPassphraseLabel': "phrase secrète",
+'registrationSplashPanelShowPassphraseButtonLabel': "afficher la phrase secrète",
+'donateHeaderLinkLabel': "faites un don",
+'creditsHeaderLinkLabel': "crédits",
+'feedbackHeaderLinkLabel': "votre avis",
+'helpHeaderLinkLabel': "aide",
+'forumHeaderLinkLabel': "forum",
+'recordMenuLabel': "cartes",
+'accountMenuLabel': "compte",
+'dataMenuLabel': "données",
+'contactsMenuLabel': "contacts",
+'toolsMenuLabel': "outils",
+'logoutMenuLabel': "déconnexion",
+'lockMenuLabel': "verrouiller",
+'lockTitle': "Le compte est verrouillé",
+'lockDescription': "<p>Pour déverrouiller votre compte, veuillez saisir votre phrase secrète</p> ",
+'unlockButtonLabel': "Déverrouiller",
+'changePasswordTabLabel': "Changer votre phrase secrète",
+'changePasswordTabTitle': "Changer votre phrase secrète",
+'changePasswordFormUsernameLabel': "nom d’utilisateur",
+'changePasswordFormOldPassphraseLabel': "ancienne phrase secrète",
+'changePasswordFormNewPassphraseLabel': "nouvelle phrase secrète",
+'changePasswordFormRetypePassphraseLabel': "re-saisissez phrase secrète",
+'changePasswordFormSafetyCheckboxLabel': "Je sais que Clipperz ne pourra pas récupérer ma phrase secrète.",
+'changePasswordFormSubmitLabel': "Changer ma phrase secrète",
+'changePasswordFormWrongUsernameWarning': "Nom d’utilisateur incorrect",
+'changePasswordFormWrongPassphraseWarning': "Phrase secrète incorrect",
+'changePasswordFormWrongRetypePassphraseWarning': "Votre phrase secrète ne correspond pas, veuillez la saisir à nouveau",
+'changePasswordFormSafetyCheckWarning': "Veuillez lire et cocher la case-à-cocher ci-dessous",
+'changePasswordFormProgressDialogTitle': "Changement des identifiants utilisateurs",
+'changePasswordFormProgressDialogConnectedMessageTitle': "Connecté",
+'changePasswordFormProgressDialogConnectedMessageText': "Terminé",
+'changePasswordFormProgressDialogErrorMessageTitle': "Erreur",
+'changePasswordFormProgressDialogErrorMessageText': "Changement de identifiants échoué!",
+'changeCredentialsPanelEncryptingDataMessageTitle': "Changement de votre phrase secrète",
+'changeCredentialsPanelEncryptingDataMessageText': "Cryptage local des identifiants",
+'changeCredentialsPanelCreatingNewCredentialsMessageTitle': "Modifier votre phrase secrète",
+'changeCredentialsPanelCreatingNewCredentialsMessageText': "Mettre à jour vos identifiants",
+'changeCredentialsPanelSendingNewCredentialsToTheServerMessageTitle': "Modifier votre phrase secrète",
+'changeCredentialsPanelSendingNewCredentialsToTheServerMessageText': "Téléchargement de vos identifiants sur Clipperz.com",
+'changeCredentialsPanelDoneMessageTitle': "Modifier votre phrase secrète",
+'changeCredentialsPanelDoneMessageText': "Terminé",
+'manageOTPTabLabel': "Mettre à jour votre phrase secrète à usage unique",
+'manageOTPTabTitle': "Mettre à jour votre phrase secrète à usage unique",
+'manageOTPTabDescription': "<p>Une phrase secrète à usage unique fonctionne comme votre phrase secrète habituelle, mais elle ne peut être utilisé qu'une seule fois.</p> <p>Si la phrase secrète est utilisé de nouveau et que vous tenté de vous identifier à nouveau, vous serez rejeté et le processus d'identification échouera.</p> <p>Juste après une identification correcte, votre phrase secrète à usage unique sera effacée pour interdire tout accès frauduleux.</p> <p>Les phrases secrètes à usage unique sont un excellent choix si vous craignez qu'un logiciel espion ne vole vos données après avoir infecté votre machine.</p> <p> <b>Il est fortement recommandé d'utiliser des phrases secrètes à usage unique lorsque vous accédez à Clipperz depuis un terminal public, comme un cybercafé ou une borne Internet.</b> </p> ",
+'accountPreferencesLabel': "Préférences",
+'accountPreferencesTabTitle': "Préférences",
+'accountPreferencesLanguageTitle': "Choix de la langue",
+'accountPreferencesLanguageDescription': "<p>Choisissez la langue d'affichage de Clipperz dans la liste suivante.</p> ",
+'accountPreferencesInterfaceTitle': "Personnalisation de l'interface",
+'accountPreferencesInterfaceDescription': "<p>Ajustez l'interface de Clipperz à vos besoins.</p> ",
+'saveUserPreferencesFormSubmitLabel': "Enregistrer",
+'cancelUserPreferencesFormSubmitLabel': "Annuler",
+'accountPreferencesSavingPanelTitle_Step1': "Enregistrement des préférences",
+'accountPreferencesSavingPanelText_Step1': "Chiffrement local de vos préférences",
+'accountPreferencesSavingPanelTitle_Step2': "Enregistrement des préférences",
+'accountPreferencesSavingPanelText_Step2': "Transmission des préférences chiffrées au serveur",
+'deleteAccountTabLabel': "Supprimer votre compte",
+'deleteAccountTabTitle': "Supprimer votre compte",
+'deleteAccountFormUsernameLabel': "nom d’utilisateur",
+'deleteAccountFormPassphraseLabel': "phrase secrète",
+'deleteAccountFormSafetyCheckboxLabel': "Je sais que toute mes données seront supprimés et que cette action sera irréversible.",
+'deleteAccountFormSubmitLabel': "Supprimer mon compte",
+'deleteAccountFormWrongUsernameWarning': "Nom d’utilisateur incorrect",
+'deleteAccountFormWrongPassphraseWarning': "Phrase secrète incorrect",
+'deleteAccountFormSafetyCheckWarning': "Veuillez lire et cocher la case-à-cocher ci-dessous.",
+'accountPanelDeletingAccountPanelConfirmationTitle': "ATTENTION",
+'accountPanelDeleteAccountPanelConfirmationText': "Êtes-vous sûr de vouloir supprimer ce compte?",
+'accountPanelDeleteAccountPanelConfirmButtonLabel': "Oui",
+'accountPanelDeleteAccountPanelDenyButtonLabel': "Non",
+'offlineCopyTabLabel': "Copie locale",
+'offlineCopyTabTitle': "Copie locale",
+'offlineCopyTabDescription': "<p>D'un seul click, vous pouvez télécharger toutes vos données chiffrées des serveurs Clipperz sur votre disque dur, créant ainsi une version déconnecté de Clipperz utilisable lorsque vous n'êtes pas connectés à Internet.</p> <p>Cette version en lecture seule est aussi sécurisée que la version en lecture-écriture, et n'expose pas vos données à un risque plus élevé. Elles partagent en effet le même code et la même architecture de sécurité.</p> <ol> <li> <p>Cliquez sur le liens ci-dessous pour lancer le téléchargement.</p> </li> <li> <p>Votre navigateur vous demandera que faire du fichier “Clipperz_YYYYMMDD.html”. Sauvez le sur votre disque dur.</p> </li> <li> <p>Puis double-cliquez sur le fichier téléchargé pour lancer la version déconnectée dans votre navigateur.</p> </li> <li> <p>Utilisez vos nom d’utilisateur et phrase secrète habituels.</p> </li> </ol> ",
+'offlineCopyDownloadLinkLabel': "Télécharger",
+'sharingTabLabel': "Partager",
+'sharingTabTitle': "Partager",
+'sharingTabDescription': "<p>De temps en temps il est nécessaire de partager des parties de vos informations confidentiels avec une ou plusieurs personnes.</p> <p>Cela pourrait être aussi simple que l’octroi à un collègue de votre code d’accès à votre messagerie vocale quand vous êtes hors du bureau, ou aussi compliqués que la permission d’ayant droit aux héritiers pour avoir accès à votre boîte de coffre-fort à la banque locale.</p> <p>Clipperz vous permez donc de partager vos mots de passe grâce à un processe sûr et direct.</p> <p> </p> <p> <b>Prochainement disponible ...</b> </p> ",
+'importTabLabel': "Importer",
+'importTabTitle': "Importer",
+'importTabDescription': "<p> <b>Prochainement disponible ...</b> </p> ",
+'printingTabLabel': "Exporter",
+'printingTabTitle': "Exporter",
+'printingTabDescription': "<p> <b>Version d’impression</b> </p> <p>En cliquant sur ce bouton vous ouvrirez une fenêtre contenant vos en-têtes cryptés dans un format d’impression.</p> <p>Si vous imprimez pour des raisons de sauvegarde personnel, veuillez vous tourner vers une solution plus sécurisé comme la version “Copie locale”.</p> ",
+'printingLinkLabel': "Version imprimable",
+'contactsTabLabel': "Contacts",
+'contactsTabTitle': "Contacts",
+'passwordGeneratorTabLabel': "Générateur de mot de passe",
+'bookmarkletTabLabel': "Bookmarklet",
+'passwordGeneratorTabTitle': "Générateur de mot de passe",
+'bookmarkletTabTitle': "Bookmarklet",
+'paswordGeneratorTabDescription': "<p> </p> ",
+'passwordGeneratorTabButtonLabel': " Générer un mot de passe",
+'bookmarkletTabDescription': "<p>Un bookmarklet est un outil “clique unique” simple qui peut exécuter des tâches très utiles. Il peut être sauvegardé et utilisé comme un signet de page Web normal.</p> <p>Le bookmarklet Clipperz vous aidera à rapidement créer de nouvelles cartes et des nouveaux “accès directs” avec vos cartes existantes.</p> <p> <b>Notez s’il vous plaît que le bookmarklet n’inclut pas d’informations liées à votre compte (par exemple votre nom d’utilisateur ou votre phrase secrète), le bookmarklet est un outil général contenant le même code pour chaque utilisateur Clipperz.</b> </p> <div> <p>Pour installer le bookmarklet <b>glissez & déposez</b> le lien ci-dessous dans votre bar de navigation.</p> </div> ",
+'bookmarkletTabBookmarkletTitle': "Ajouter à Clipperz",
+'bookmarkletTabInstructions': "<h3>Comment créer une carte comprenant un lien de “accès direct” à un service en ligne</h3> <ol> <li> <p>Ouvrir la page Web où le site affiche un formulaire d’identification. (C’est la page où vous entrez d’habitude vos informations d'identification)</p> </li> <li> <p>Lancer le bookmarklet en cliquant dessus : une fenêtre contextuelle apparait alors sur la page Web.</p> </li> <li> <p>Copier dans le presse-papiers le contenu du grand secteur de texte dans le menu contextuel. (Ctrl-C)</p> </li> <li> <p>Entrer dans votre compte Clipperz et cliquer sur <b>“Ajouter une nouvelle carte”</b>.</p> </li> <li> <p>Coller le presse-papiers dans la zone de texte et rajouter un titre (facultatif). (Ctrl-V)</p> </li> <li> <p>Cliquer sur le bouton <b>“Créer”</b>, repassez en revu les détails et cliquer <b>“Sauver”</b>. De plus amples informations sont disponibles <a href=\"http://www.clipperz.com/support/user_guide/bookmarklet\" target=\"_blank\">ici</a>.</p> </li> </ol> <h3>Comment ajouter un lien de “accès direct” à une carte existante</h3> <ol> <li> <p>Idem que précédemment.</p> </li> <li> <p>Idem que précédemment..</p> </li> <li> <p>Idem que précédemment.</p> </li> <li> <p>Entrer dans votre compte Clipperz et sélectionner la carte crypté qui contient les identifiants pour le service web que vous venez tout juste de visiter et cliquer sur <b>“Modifier”</b>.</p> </li> <li> <p>Coller le presse-papier dans la zone de texte <b>“Accès directs”</b>. (ctrl-V)</p> </li> <li> <p>Cliquer sur <b>“Ajouter un accès direct”</b>, repassez en revu les détails et cliquer <b>“Sauver”</b>.</p> </li> </ol> ",
+'mainPanelDirectLoginBlockLabel': "Accès directs",
+'directLinkReferenceShowButtonLabel': "voir",
+'mainPanelDirectLoginBlockDescription': "<p>Ajouter une “accès direct” pour vous identifier sans avoir besoin de taper vos identifiants de connexions!</p> <p>Les “accès directs” augmente considérablement la sécurité de vos mots passes dans la mesure où vous pouvez:</p> <ul> <li> <p>adopter et saisir des mots de passe complexes;</p> </li> <li> <p>ne réutilisez le même mot de passe et ne mettez plus de mots de passe facile à deviner.</p> </li> </ul> <p>Simple et rapide à configurer avec le Clipperz <b>bookmarklet</b>.</p> <a href=\"http://www.clipperz.com/support/user_guide/direct_logins\" target=\"_blank\">Pour en savoir plus sur les “accès directs”</a> ",
+'mainPanelRecordsBlockLabel': "Cartes",
+'mainPanelAddRecordButtonLabel': "Ajouter une nouvelle carte",
+'mainPanelRemoveRecordButtonLabel': "Supprimer une carte",
+'mainPanelRecordFilterBlockAllLabel': "tous",
+'mainPanelRecordFilterBlockTagsLabel': "tags",
+'mainPanelRecordFilterBlockSearchLabel': "chercher",
+'recordDetailNoRecordAtAllTitle': "Bienvenue sur Clipperz!",
+'recordDetailNoRecordAtAllDescription': "<h5>Commencez par ajouter des cartes à votre compte.</h5> <p>Les cartes sont des formulaires flexibles ou vous pouvez enregistrer vos mots de passe et autres informations confidentielles.</p> <p>Par exemple, une carte peut contenir les informations d\"identification pour un site web, la combinaison de votre antivol de bicyclette, les détails de votre carte bancaire, ...</p> <h5>N'oubliez pas le bookmarklet!</h5> <p>Avant de commencer, installez le bookmarklet “Ajouter à Clipperz”: il rends la création de carte plus facile et amusante.</p> <p>Allez à l'onglet “outils” pour découvrir comment l'installer et l'utiliser.</p> <p> </p> <p>Ensuite, cliquez tout simplement sur le bouton “Ajouter une nouvelle carte” et profitez de votre compte Clipperz.</p> <p> </p> <a href=\"http://www.clipperz.com/support/user_guide/managing_cards\" target=\"_blank\">En savoir plus sur la création et la gestion des cartes.</a> ",
+'newRecordWizardTitleBox': "<h5>Choisissez un modèle</h5> <p>Les cartes sont des formulaires flexibles ou vous pouvez enregistrer vos mots de passe et autres informations confidentielles.</p> <p>Commencez par choisir un des modèles ci-dessous. Vous pourrez toujours adapter vos cartes plus tard en ajoutant ou supprimant des champs.</p> ",
+'newRecordWizardBookmarkletConfigurationTitle': "Accès directs",
+'newRecordWizardBookmarkletConfigurationDescriptionConfig': "<p>Collez ici le code de configuration généré par le bookmarlet Clipperz.</p> <p>Cela créera une nouvelle carte avec un accès direct à votre site web.</p> ",
+'newRecordWizardCreateButtonLabel': "Créer",
+'newRecordWizardCancelButtonLabel': "Annuler",
+'recordTemplates': {
+ 'WebAccount': {
+ 'title': "Mot de passe web",
+ 'description': "<p>Une carte toute simple pour enregistrer les informations d'identification de vos services en ligne.</p> ",
+ 'fields': {
+ 'URL': "Adresse web",
+ 'TXT': "Nom d'utilisateur ou email",
+ 'PWD': "Mot de passe"
+ }
+ },
+ 'BankAccount': {
+ 'title': "Compte bancaire",
+ 'description': "<p>Enregistrer de façon sécurisée vos numéros de compte bancaire et vos identifiants de service bancaire en ligne.</p> ",
+ 'fields': {
+ 'TXT': "Banque",
+ 'TXT': "N° de compte",
+ 'URL': "Adresse web du site",
+ 'TXT': "Identifiant",
+ 'PWD': "Mot de passe"
+ }
+ },
+ 'CreditCard': {
+ 'title': "Carte bancaire",
+ 'description': "<p>Ayez toujours sous la main votre numéro de carte, la date d'expiration, le code de contrôle et le code secret avec Clipperz</p> ",
+ 'fields': {
+ 'TXT': "Type (Visa, AmEx, ...)",
+ 'TXT': "Numéro",
+ 'TXT': "Nom du porteur",
+ 'TXT': "Date de validité",
+ 'TXT': "Code de contrôle",
+ 'PWD': "Code secret",
+ 'URL': "Site web",
+ 'TXT': "Identifiant",
+ 'PWD': "Mot de passe"
+ }
+ },
+ 'AddressBookEntry': {
+ 'title': "Carnet d'adresse",
+ 'description': "<p>Clipperz peux aussi être utilisé comme un nouveau carnet d'adresse privé. Utilisez ce modèle pour ajouter des contacts facilement.</p> ",
+ 'fields': {
+ 'TXT': "Nom",
+ 'TXT': "Adresse eMail",
+ 'TXT': "Téléphone",
+ 'TXT': "Mobile",
+ 'ADDR': "Adresse"
+ }
+ },
+ 'Custom': {
+ 'title': "Carte personnalisée",
+ 'description': "<p>Quelles que soient les données confidentielles que vous souhaitez protéger, créez une carte personnalisée adaptée à vos besoins.</p> ",
+ 'fields': {
+ 'TXT': "Titre du champ 1",
+ 'TXT': "Titre du champ 2",
+ 'TXT': "Titre du champ 3"
+ }
+ }
+},
+'recordFieldTypologies': {
+ 'TXT': {
+ 'description': "simple text field",
+ 'shortDescription': "texte"
+ },
+ 'PWD': {
+ 'description': "simple text field, with default status set to hidden",
+ 'shortDescription': "mot de passe"
+ },
+ 'URL': {
+ 'description': "simple text field in edit mode, that became an active url in view mode",
+ 'shortDescription': "adresse de site web"
+ },
+ 'DATE': {
+ 'description': "a value set with a calendar helper",
+ 'shortDescription': "date"
+ },
+ 'ADDR': {
+ 'description': "just like the URL, but the active link points to Google Maps (or similar service) passing the address value as argument",
+ 'shortDescription': "adresse"
+ },
+ 'CHECK': {
+ 'description': "check description",
+ 'shortDescription': "check"
+ },
+ 'RADIO': {
+ 'description': "radio description",
+ 'shortDescription': "radio"
+ },
+ 'SELECT': {
+ 'description': "select description",
+ 'shortDescription': "select"
+ }
+},
+'newRecordPanelGeneralExceptionTitle': "Erreur",
+'newRecordPanelGeneralExceptionMessage': "Le code de configuration n'est pas valide. Copiez le depuis la fenêtre du bookmarklet, et essayez à nouveau.",
+'newRecordPanelWrongBookmarkletVersionExceptionTitle': "Erreur",
+'newRecordPanelWrongBookmarkletVersionExceptionMessage': "Ce code de configuration provient d'un ancien bookmarklet. Mettez votre bookmarklet à jour, puis essayez de nouveau.",
+'newRecordPanelExceptionPanelCloseButtonLabel': "Annuler",
+'mainPanelDeletingRecordPanelConfirmationTitle': "Suppression de la carte sélectionnée",
+'mainPanelDeleteRecordPanelConfirmationText': "Voulez vous vraiment supprimer la carte sélectionnée?",
+'mainPanelDeleteRecordPanelConfirmButtonLabel': "Oui",
+'mainPanelDeleteRecordPanelDenyButtonLabel': "Non",
+'mainPanelDeletingRecordPanelInitialTitle': "Suppression de la carte",
+'mainPanelDeletingRecordPanelCompletedText': "Terminé",
+'deleteRecordPanelCollectRecordDataMessageTitle': "Supprimer la carte",
+'deleteRecordPanelCollectRecordDataMessageText': "Mise à jour de la liste des cartes",
+'deleteRecordPanelEncryptUserDataMessageTitle': "Supprimer la carte",
+'deleteRecordPanelEncryptUserDataMessageText': "Chiffrement local des en-têtes de carte",
+'deleteRecordPanelSendingDataToTheServerMessageTitle': "Supprimer la carteDelete card",
+'deleteRecordPanelSendingDataToTheServerMessageText': "Transmission des en-têtes chiffrées à Clipperz",
+'deleteRecordPanelUpdatingTheInterfaceMessageTitle': "Supprimer la carte",
+'deleteRecordPanelUpdatingTheInterfaceMessageText': "Mise à jour de l'interface",
+'recordDetailNoRecordSelectedTitle': "Aucune carte sélectionnée",
+'recordDetailNoRecordSelectedDescription': "<p>Veuillez selectionner une carte dans la liste de gauche.</p> ",
+'recordDetailLoadingRecordMessage': "Téléchargement de la carte chiffrée depuis Clipperz",
+'recordDetailDecryptingRecordMessage': "Déchiffrement local des informations de la carte",
+'recordDetailLoadingRecordVersionMessage': "Téléchargement de la dernière version de la carte",
+'recordDetailDecryptingRecordVersionMessage': "Déchiffrement local de la dernière version",
+'recordDetailLoadingErrorMessageTitle': "Erreur lors du téléchargement de la carte",
+'recordDetailNotesLabel': "Notes",
+'recordDetailLabelFieldColumnLabel': "Titre du champ",
+'recordDetailDataFieldColumnLabel': "Données du champ",
+'recordDetailTypeFieldColumnLabel': "Type",
+'recordDetailSavingChangesMessagePanelInitialTitle': "Enregistrement de la carte",
+'recordDetailAddFieldButtonLabel': "Ajouter un champ",
+'recordDetailPasswordFieldHelpLabel': "pour copier le mot de passe, cliquez sur les étoiles, puis Ctrl-C",
+'recordDetailPasswordFieldScrambleLabel': "dissimuler",
+'recordDetailPasswordFieldUnscrambleLabel': "en clair",
+'recordDetailDirectLoginBlockTitle': "Accès directs",
+'recordDetailNewDirectLoginDescription': "<p>Configuration de l'accès direct</p> ",
+'recordDetailDirectLoginBlockNoDirectLoginConfiguredDescription': "<p>Cette carte contient-elle des informations d'identification pour un service en ligne?</p> <p>Utilisez le bookmarklet pour configurer un “accès direct” depuis Clipperz en un seul click!</p> ",
+'recordDetailAddNewDirectLoginButtonLabel': "Ajouter un accès direct",
+'recordDetailEditButtonLabel': "Modifier",
+'recordDetailSaveButtonLabel': "Sauver",
+'recordDetailCancelButtonLabel': "Annuler",
+'newRecordTitleLabel': "_nouvelle carte_",
+'recordSaveChangesPanelCollectRecordInfoMessageTitle': "Enregistrement de la carte",
+'recordSaveChangesPanelCollectRecordInfoMessageText': "Updating card headers",
+'recordSaveChangesPanelEncryptUserDataMessageTitle': "Sauvegarde de la carte",
+'recordSaveChangesPanelEncryptUserDataMessageText': "Cryptage local des en-têtes chiffrés",
+'recordSaveChangesPanelEncryptRecordDataMessageTitle': "Sauvegarde de la carte",
+'recordSaveChangesPanelEncryptRecordDataMessageText': "Cryptage local des en-têtes chiffrés",
+'recordSaveChangesPanelEncryptRecordVersionDataMessageTitle': "Sauvegarde de la carte",
+'recordSaveChangesPanelEncryptRecordVersionDataMessageText': "Cryptage local des données de version de la carte",
+'recordSaveChangesPanelSendingDataToTheServerMessageTitle': "Sauvegarde de la carte",
+'recordSaveChangesPanelSendingDataToTheServerMessageText': "Téléchargement des cartes d’en-têtes chiffrés depuis Clipperz",
+'recordSaveChangesPanelUpdatingTheInterfaceMessageTitle': "Sauvegarde de la carte",
+'recordSaveChangesPanelUpdatingTheInterfaceMessageText': "Mise à jour de l'interface",
+'passwordGeneratorPanelTitle': "Générateur de mot de passe",
+'passwordGeneratorPanelOkLabel': "Ok",
+'passwordGeneratorPanelCancelLabel': "Annuler",
+'passwordGeneratorLengthLabel': "longueur:",
+//'DWRUtilLoadingMessage': "Chargement des données ...",
+'comingSoon': "Bientôt en ligne ...",
+'panelCollectingEntryopyMessageText': "Rassemblement d'entropie",
+'directLoginConfigurationCheckBoxFieldSelectedValue': "Oui",
+'directLoginConfigurationCheckBoxFieldNotSelectedValue': "Non",
+
+__syntaxFix__: "syntax fix"
+});
diff --git a/frontend/beta/js/Clipperz/PM/Strings/Strings_he-IL.js b/frontend/beta/js/Clipperz/PM/Strings/Strings_he-IL.js
new file mode 100644
index 0000000..3bdfe19
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Strings/Strings_he-IL.js
@@ -0,0 +1,40 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+//=============================================================================
+//
+// H E B R E W (he_IL)
+//
+//=============================================================================
+
+Clipperz.PM.Strings.Languages['he-il'] = MochiKit.Base.merge(Clipperz.PM.Strings.Languages['en-us'], {
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+});
+
diff --git a/frontend/beta/js/Clipperz/PM/Strings/Strings_it-IT.js b/frontend/beta/js/Clipperz/PM/Strings/Strings_it-IT.js
new file mode 100644
index 0000000..51c0d03
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Strings/Strings_it-IT.js
@@ -0,0 +1,694 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+Clipperz.PM.Strings.Languages['it-IT'.toLowerCase()] = MochiKit.Base.merge(Clipperz.PM.Strings.Languages['en-us'], {
+'clipperzServiceDescription': "<h2>Tienilo per te!</h2> <ul> <li> <h3>Clipperz è:</h3> <ul> <li> <p>un archivio semplice e sicuro per le tue password</p> </li> <li> <p>un canale di accesso unificato a tutti i tuoi servizi online</p> </li> <li> <p>una cassaforte digitale per tutti i tuoi dati riservati</p> </li> </ul> </li> <li> <h3>Con Clipperz puoi:</h3> <ul> <li> <p>memorizzare e gestire le password e le credenziali di accesso dei tuoi servizi online</p> </li> <li> <p>accedere ai tuoi servizi online con un solo click senza bisogno di inserire username o password</p> </li> <li> <p>proteggere tutte le tue informazioni confidenziali: codice dell&#x27;allarme di casa, dati delle carte di credito, …</p> </li> <li> <p>condividere dati riservati con i tuoi familiari o colleghi (disponibile a breve)</p> </li> </ul> </li> <li> <h3>I vantaggi di Clipperz:</h3> <ul> <li> <p>gratuito e completamente anonimo</p> </li> <li> <p>accessibile da qualsiasi computer</p> </li> <li> <p>nessun software da scaricare e niente da installare</p> </li> <li> <p>mai più informazioni riservate sul tuo PC o sulla carta!</p> </li> </ul> </li> <li> <h3>La sicurezza di Clipperz:</h3> <ul> <li> <p>i dati sono criptati dal tuo browser prima di essere inviati a Clipperz</p> </li> <li> <p>la chiave per decriptare i dati è conosciuta soltanto da te</p> </li> <li> <p>Clipperz riceve e memorizza solo i tuoi dati criptati e non ha nessuna possibilità di accedere alla versione in chiaro</p> </li> <li> <p>Clipperz utilizza solo sistemi crittografici standard, senza nessuna velleità di inventare e proporre nuovi algoritmi non validati dalla comunità scientifica</p> </li> <li> <p>tutto il codice di Clipperz è disponibile e può essere analizzato in qualsiasi momento, ma non serve essere un esperto di crittografia per apprezzare la sicurezza e la comodità di Clipperz!</p> </li> </ul> </li> <li><a href=\"http://www.clipperz.com\" target=\"_blank\">Maggiori informazioni su Clipperz (in inglese)</a> </li> </ul> ",
+'loginFormTitle': "accedi a Clipperz",
+'loginFormUsernameLabel': "Utente",
+'loginFormPassphraseLabel': "frase segreta",
+'loginFormDontHaveAnAccountLabel': "non ti sei ancora registrato?",
+'loginFormCreateOneLabel': "registrati adesso",
+'loginFormForgotYourCredentialsLabel': "hai perso i dati di accesso?",
+'loginFormAarghThatsBadLabel': "aargh! questo non è bello!",
+'loginFormAfraidOfMaliciousScriptsLabel': "non ti fidi?",
+'loginFormVerifyTheCodeLabel': "controlla il codice",
+'loginFormButtonLabel': "Accedi",
+'loginFormOneTimePasswordCheckboxLabel': "usa un codice “usa e getta”",
+'loginFormOneTimePasswordCheckboxDescription': "",
+'loginPanelSwithLanguageDescription': "<h5>Seleziona la tua lingua preferita</h5> ",
+'browserCompatibilityDescription': "<p>Clipperz consiglia Firefox per una maggiore sicurezza. Clipperz supporta anche Opera ed Internet Explorer.</p> ",
+'OTPloginMessagePanelInitialTitle': "Accesso con codice “usa e getta”",
+'OTPloginMessagePanelInitialText': "Invio delle credenziali OTP ...",
+'OTPloginMessagePanelLoadingTitle': "Accesso con codice “usa e getta”",
+'OTPloginMessagePanelLoadingText': "Caricamento dei dati di autenticazione criptati ...",
+'OTPloginMessagePanelProcessingTitle': "Accesso con codice “usa e getta”",
+'OTPloginMessagePanelProcessingText': "Decodifica locale dei dati di autenticazione ...",
+'loginMessagePanelInitialTitle': "Connessione in corso ...",
+'loginMessagePanelInitialText': "---",
+'loginMessagePanelInitialButtonLabel': "Annulla",
+'loginMessagePanelConnectedTitle': "Connesso",
+'loginMessagePanelConnectedText': "Fatto",
+'loginMessagePanelFailureTitle': "Errore",
+'loginMessagePanelFailureText': "Connessione fallita",
+'loginMessagePanelFailureButtonLabel': "Chiudi",
+'connectionLoginSendingCredentialsMessageTitle': "Verifica delle credenziali",
+'connectionLoginSendingCredentialsMessageText': "Invio delle credenziali",
+'connectionLoginCredentialsVerificationMessageTitle': "Verifica delle credenziali",
+'connectionLoginCredentialsVerificationMessageText': "Esecuzione dell&#x27;autenticazione SRP ...",
+'connectionLoginDoneMessageTitle': "Verifica delle credenziali",
+'connectionLoginDoneMessageText': "Connesso",
+'userLoginPanelUpgradingUserCredentialsMessageTitle': "Verifica delle credenziali",
+'userLoginPanelUpgradingUserCredentialsMessageText': "Aggiornamento delle credenziali ad un nuovo schema di autenticazione",
+'userLoginPanelConnectedMessageTitle': "Utente autenticato",
+'userLoginPanelConnectedMessageText': "Autenticazione eseguita con successo",
+'userLoginPanelTryingAnOlderConnectionSchemaMessageTitle': "Verifica delle credenziali",
+'userLoginPanelTryingAnOlderConnectionSchemaMessageText': "Tentativo con vecchio schema di autenticazione",
+'userLoginPanelLoadingUserDataMessageTitle': "Utente autenticato",
+'userLoginPanelLoadingUserDataMessageText': "Scarica le intestazioni criptate delle schede da Clipperz",
+'userLoginPanelDecryptingUserDataMessageTitle': "Utente autenticato",
+'userLoginPanelDecryptingUserDataMessageText': "Decodifica locale dell&#x27;intestazione delle schede",
+'userLoginPanelDecryptingUserStatisticsMessageTitle': "Utente autenticato",
+'userLoginPanelDecryptingUserStatisticsMessageText': "Decodifica locale delle statistiche d&#x27;uso",
+'splashAlertTitle': "Benvenuto a Clipperz!",
+'splashAlertText': "<p>Alcuni consigli per la sicurezza</p> <ul> <li> <p>La sicurezza dei tuoi dati dipende da quanto è sicura la frase segreta che usi per proteggerli. Nessuno può accedervi a meno che non conosca la frase segreta.</p> </li> <li> <p>Se hai intenzione di usare Clipperz per conservare informazioni sensibili e riservate, scegli attentamente una frase segreta complessa. Più è lunga, maggiore è la sicurezza!</p> </li> <li> <p>E non dimenticare che Clipperz non è in grado di recuperare la tua frase segreta in caso di smarrimento!</p> </li> </ul> <p>Per maggiori informazioni sulla sicurezza, consulta il sito <a href=\"http://www.clipperz.com\" target=\"_blank\">Clipperz</a> (in lingua inglese).</p> ",
+'splashAlertCloseButtonLabel': "Ok",
+'registrationFormTitle': "crea il tuo utente",
+'registrationFormUsernameLabel': "Utente",
+'registrationFormPassphraseLabel': "frase segreta",
+'registrationFormRetypePassphraseLabel': "ripeti frase segreta",
+'registrationFormSafetyCheckLabel': "Sono consapevole che Clipperz non è in grado di recuperare una frase segreta dimenticata.",
+'registrationFormTermsOfServiceCheckLabel': "Dichiaro di aver letto e di accettare i <a href=\"http://www.clipperz.com/terms_of_service\" target=\"_blank\">Termini del Servizio</a> .",
+'registrationFormDoYouAlreadyHaveAnAccountLabel': "sei già un utente registrato?",
+'registrationFormSimplyLoginLabel': "accedi subito",
+'registrationFormButtonLabel': "Registrati",
+'registrationFormWarningMessageNotMatchingPassphrases': "Le frasi segrete non corrispondono, ripeti l&#x27;inserimento.",
+'registrationFormWarningMessageSafetyCheckNotSelected': "Leggi e spunta le condizioni sotto riportate.",
+'registrationFormWarningMessageTermsOfServiceCheckNotSelected': "Per procedere devi accettare i Termini del Servizio.",
+'registrationMessagePanelInitialTitle': "Registrazione in corso ...",
+'registrationMessagePanelInitialText': "---",
+'registrationMessagePanelInitialButtonLabel': "Annulla",
+'registrationMessagePanelRegistrationDoneTitle': "Registrazione",
+'registrationMessagePanelRegistrationDoneText': "Fatto",
+'registrationMessagePanelFailureTitle': "Registrazione fallita",
+'registrationMessagePanelFailureButtonLabel': "Chiudi",
+'connectionRegistrationSendingRequestMessageText': "Verifica delle credenziali",
+'connectionRegistrationSendingCredentialsMessageText': "Invio delle credenziali",
+'registrationSplashPanelTitle': "Avviso di sicurezza",
+'registrationSplashPanelDescription': "<p>Queste sono le tue credenziali di accesso a Clipperz, conservale con cura. Il tuo utente ed la tua frase segreta non ti verranno mostrati una seconda volta!</p> ",
+'registrationSplashPanelUsernameLabel': "Utente",
+'registrationSplashPanelPassphraseLabel': "frase segreta",
+'registrationSplashPanelShowPassphraseButtonLabel': "mostra la frase segreta",
+'donateHeaderLinkLabel': "donazioni",
+'creditsHeaderLinkLabel': "credits",
+'feedbackHeaderLinkLabel': "scrivici",
+'helpHeaderLinkLabel': "aiuto",
+'forumHeaderLinkLabel': "forum",
+'recordMenuLabel': "Schede",
+'accountMenuLabel': "profilo",
+'dataMenuLabel': "dati",
+'contactsMenuLabel': "Contatti",
+'toolsMenuLabel': "strumenti",
+'logoutMenuLabel': "esci",
+'lockMenuLabel': "blocca",
+'lockTitle': "Utente bloccato",
+'lockDescription': "<p>Per sbloccare il tuo utente inserisci la frase segreta</p> ",
+'unlockButtonLabel': "Sblocca",
+'changePasswordTabLabel': "Cambia la tua frase segreta",
+'changePasswordTabTitle': "Cambia la tua frase segreta",
+'changePasswordFormUsernameLabel': "Utente",
+'changePasswordFormOldPassphraseLabel': "attuale frase segreta",
+'changePasswordFormNewPassphraseLabel': "nuova frase segreta",
+'changePasswordFormRetypePassphraseLabel': "ripeti nuova frase segreta",
+'changePasswordFormSafetyCheckboxLabel': "Sono consapevole che Clipperz non è in grado di recuperare una frase segreta dimenticata.",
+'changePasswordFormSubmitLabel': "Cambia frase segreta",
+'changePasswordFormWrongUsernameWarning': "Utente errato",
+'changePasswordFormWrongPassphraseWarning': "Frase segreta errata",
+'changePasswordFormWrongRetypePassphraseWarning': "Le frasi segrete non corrispondono, ripeti l&#x27;inserimento.",
+'changePasswordFormSafetyCheckWarning': "Leggi e spunta le condizioni sotto riportate.",
+'changePasswordFormProgressDialogTitle': "Aggiornamento credenziali",
+'changePasswordFormProgressDialogEmptyText': "---",
+'changePasswordFormProgressDialogConnectedMessageTitle': "Connesso",
+'changePasswordFormProgressDialogConnectedMessageText': "Fatto",
+'changePasswordFormProgressDialogErrorMessageTitle': "Errore",
+'changePasswordFormProgressDialogErrorMessageText': "Aggiornamento credenziali fallito!",
+'changeCredentialsPanelEncryptingDataMessageTitle': "Cambio della frase segreta",
+'changeCredentialsPanelEncryptingDataMessageText': "Cripta localmente l&#x27;intestazione delle schede",
+'changeCredentialsPanelCreatingNewCredentialsMessageTitle': "Cambio della frase segreta",
+'changeCredentialsPanelCreatingNewCredentialsMessageText': "Aggiornamento delle credenziali",
+'changeCredentialsPanelSendingNewCredentialsToTheServerMessageTitle': "Cambio della frase segreta",
+'changeCredentialsPanelSendingNewCredentialsToTheServerMessageText': "Carica le intestazioni criptate delle schede su Clipperz",
+'changeCredentialsPanelDoneMessageTitle': "Cambio della frase segreta",
+'changeCredentialsPanelDoneMessageText': "Fatto",
+'manageOTPTabLabel': "Codici di accesso “usa e getta”",
+'manageOTPTabTitle': "Codici di accesso “usa e getta”",
+'manageOTPTabDescription': "<p>I codici di accesso e “usa e getta” funzionano come la tua normale frase segreta, ma possono essere utilizzate una sola volta.</p> <p>Se lo stesso codice “usa e getta” viene utilizzato per tentare ulteriori accessi il processo di autenticazione fallirà.</p> <p>Infatti, dopo il primo utilizzo, il codice “usa e getta” verrà immediatamente disattivato e cancellato prevenendo così eventuali accessi non autorizzati.</p> <p>L&#x27;utilizzo di codici “usa e getta” è una scelta consigliata per chi teme che il computer dal quale sta accedendo a Clipperz non sia sicuro a causa di software quali keyloggers e spyware che potrebbero registrare le proprie credenziali di accesso.</p> <p><b>E&#x27; caldamente consigliato l&#x27;utilizzo di codici “usa e getta” quando ci si collega a Clipperz da terminali pubblici quali Internet Cafe e biblioteche.</b> </p> ",
+'oneTimePasswordReadOnlyMessage': "<h6>Attenzione!</h6> <p>Non è possibilie accedere ai propri codici “usa e getta” quando si utilizza la versione offline di Clipperz.</p> ",
+'oneTimePasswordLoadingMessage': "<h6>Caricamento dati</h6> <p>Si prega di attendere ...</p> ",
+'oneTimePasswordNoPasswordAvailable': "<h6>Nessun codice “usa e getta” disponibile</h6> <p>Per creare codici “usa e getta” clicca sul pulsante “Nuovo” che trovi qui sopra.</p> ",
+'deleteOTPButtonLabel': "Elimina",
+'printOTPButtonLabel': "Stampa",
+'disabledOneTimePassword_warning': "disabilitato",
+'oneTimePasswordSelectionLink_selectLabel': "Seleziona:",
+'oneTimePasswordSelectionLink_none': "nessuno",
+'oneTimePasswordSelectionLink_used': "utilizzati",
+'oneTimePasswordSelectionLink_unused': "disponibili",
+'saveOTP_encryptUserDataTitle': "Registrazione del nuovo codice “usa e getta”",
+'saveOTP_encryptUserDataText': "Elaborazione delle credenziali OTP ...",
+'saveOTP_encryptOTPDataTitle': "Registrazione del nuovo codice “usa e getta”",
+'saveOTP_encryptOTPDataText': "Codifica locale dei dati di autenticazione ...",
+'saveOTP_sendingDataTitle': "Registrazione del nuovo codice “usa e getta”",
+'saveOTP_sendingDataText': "Invio dei dati di autenticazione criptati ...",
+'saveOTP_updatingInterfaceTitle': "Registrazione del nuovo codice “usa e getta”",
+'saveOTP_updatingInterfaceText': "Aggiornamento dell&#x27;interfaccia",
+'accountPreferencesLabel': "Preferenze",
+'accountPreferencesTabTitle': "Preferenze",
+'accountPreferencesLanguageTitle': "Selezione della lingua",
+'accountPreferencesLanguageDescription': "<p>Scegli la lingua preferita dall&#x27;elenco sottostante.</p> ",
+'showDonationReminderPanelTitle': "Promemoria donazioni",
+'showDonationReminderPanelDescription': "<p>Mostra i promemopria per le donazioni</p> ",
+'saveUserPreferencesFormSubmitLabel': "Salva",
+'cancelUserPreferencesFormSubmitLabel': "Annulla",
+'accountPreferencesSavingPanelTitle_Step1': "Salvataggio preferenze",
+'accountPreferencesSavingPanelText_Step1': "Cripta localmente le preferenze",
+'accountPreferencesSavingPanelTitle_Step2': "Salvataggio preferenze",
+'accountPreferencesSavingPanelText_Step2': "Carica preferenze criptate su Clipperz",
+'accountLoginHistoryLabel': "Registro degli accessi",
+'loginHistoryTabTitle': "Registro degli accessi",
+'loginHistoryReadOnlyMessage': "<h6>Attenzione!</h6> <p>Il registro degli accessi non è disponibile quando si utilizza la versione offline di Clipperz</p> ",
+'loginHistoryLoadingMessage': "<h6>Caricamento dati</h6> <p>Si prega di attendere ...</p> ",
+'loginHistoryLoadedMessage': "<h6>I tuoi ultimi 10 accessi</h6> <p> </p> ",
+'loginHistoryIPLabel': "IP",
+'loginHistoryTimeLabel': "data",
+'loginHistoryCurrentSessionText': "sessione corrente",
+'loginHistoryReloadButtonLabel': "Aggiorna il registro degli accessi",
+'deleteAccountTabLabel': "Cancella il tuo utente",
+'deleteAccountTabTitle': "Cancella il tuo utente",
+'deleteAccountFormUsernameLabel': "Utente",
+'deleteAccountFormPassphraseLabel': "frase segreta",
+'deleteAccountFormSafetyCheckboxLabel': "Sono consapevole che tutti miei dati verranno cancellati e che questa azione è irreversibile.",
+'deleteAccountFormSubmitLabel': "Cancella il mio utente",
+'deleteAccountFormWrongUsernameWarning': "Utente errato",
+'deleteAccountFormWrongPassphraseWarning': "Frase segreta errata",
+'deleteAccountFormSafetyCheckWarning': "Leggi e spunta le condizioni sotto riportate.",
+'accountPanelDeletingAccountPanelConfirmationTitle': "ATTENZIONE",
+'accountPanelDeleteAccountPanelConfirmationText': "Sei sicuro di voler cancellare il tuo utente?",
+'offlineCopyTabLabel': "Copia offline",
+'offlineCopyTabTitle': "Copia offline",
+'offlineCopyTabDescription': "<p>Con un solo clic puoi trasferire tutti i tuoi dati dai server di Clipperz al tuo PC, creando una versione offline di Clipperz a cui potrai accedere quando non è disponibile un collegamento ad Internet.</p> <p>La versione offline in sola lettura è sicura quanto quella online e non espone i tuoi dati a livelli di rischio superiore in quanto entrambe condividono la medesima architettura di sicurezza.</p> <ol> <li> <p>Clicca sul link sottostante per scaricare la copia offline dei tuoi dati.</p> </li> <li> <p>Il browser ti chiederà cosa fare del file “Clipperz_YYYYMMDD.html”. Scegli di salvarlo su un disco locale.</p> </li> <li> <p>Basta un doppio click sul file appena scaricato per lanciare la versione offline di Clipperz.</p> </li> <li> <p>Accedi utilizzando le normali credenziali di accesso.</p> </li> </ol> ",
+'offlineCopyDownloadLinkLabel': "Scarica copia offline",
+'offlineCopyDownloadWarning': "<h4><a href=\"#\" id=\"offlineCopyDownloadWarningLink\">Aggiorna la tua “copia offline”!</a> </h4> <p>Una o più schede sono state recentemente create o modificate, ti consigliamo di scaricare nuovamente la tua “copia offline”.</p> ",
+'offlineCopyDownloadOk': "",
+'sharingTabLabel': "Condividi",
+'sharingTabTitle': "Condividi",
+'sharingTabDescription': "<p>Spesso è necessario condividere alcune delle proprie informazioni riservate con una o più persone.</p> <p>Può trattarsi di situazioni semplici come dare ad un collega il codice di accesso alla propria segreteria telefonica quando si va in vacanza, oppure complesse come regolare l&#x27;accesso dei legittimi eredi ai servizi di online banking utilizzati dal defunto.</p> <p>Con Clipperz la condivisione di segreti diviene un processo semplice e sicuro.</p> <p> </p> <p><b>Presto disponibile ...</b> </p> ",
+'importTabLabel': "Importa",
+'importTabTitle': "Importa",
+'importTabDescription': "<p>Presto disponibile ...</p> ",
+'printingTabLabel': "Esporta",
+'printingTabTitle': "Esporta",
+'printingTabDescription': "<h5>Stampa i tuoi dati</h5> <p>Cliccando sul link sottostante si aprirà una nuova finestra in cui verranno visualizzate tutte le tue schede in un formato idoneo alla stampa.</p> <p>Se intendi utilizzare la stampa per creare una copia di sicurezza dei tuoi dati, ti suggeriamo di considerare l&#x27;opzione più sicura fornita della “copia offline”.</p> ",
+'printingLinkLabel': "Versione stampabile",
+'contactsTabLabel': "Contatti",
+'contactsTabTitle': "Contatti",
+'passwordGeneratorTabLabel': "Generatore di password",
+'bookmarkletTabLabel': "Bookmarklet",
+'passwordGeneratorTabTitle': "Generatore di password",
+'bookmarkletTabTitle': "Bookmarklet",
+'paswordGeneratorTabDescription': "<p> </p> ",
+'passwordGeneratorTabButtonLabel': "Genera password",
+'bookmarkletTabLabel': "Bookmarklet",
+'bookmarkletTabTitle': "Bookmarklet",
+'bookmarkletTabBookmarkletTitle': "Aggiungi a Clipperz",
+'bookmarkletTabInstructions': "<h3>Come creare una scheda con “login diretto” ad un servizio online</h3> <ol> <li> <p>Aprire la pagina web che contiene la maschera di login. (ovvero la pagina dove usualmente si inseriscono nome utente e password)</p> </li> <li> <p>Cliccare sulla bookmarklet: una nuova finestrella si visualizzerà sopra la pagina.</p> </li> <li> <p>Copiare il testo di configurazione del “login diretto” contenuto nella finestrella. (ctrl-C)</p> </li> <li> <p>Accedere a Clipperz e cliccare sul pulsante <b>Aggiungi nuova scheda</b> .</p> </li> <li> <p>Selezionare il modello “Login diretto” ed incollare il testo precedentemente copiato. (ctrl-V)</p> </li> <li> <p>Cliccare sul pulsante <b>Crea</b> , completare e verificare i dettagli della scheda, quindi cliccare su <b>Salva</b> .</p> </li> </ol> <h3>Come aggiungere un “login diretto” ad una scheda esistente</h3> <ol> <li> <p>Come sopra.</p> </li> <li> <p>Come sopra.</p> </li> <li> <p>Come sopra.</p> </li> <li> <p>Accedere a Clipperz e selezionare la scheda contenente le credenziali del servizio a cui si vuole accedere con il “login diretto” e cliccare su <b>Modifica</b> .</p> </li> <li> <p>Incollare il testo precedentemente copiato nell&#x27;apposito campo presente nella sezione “Login diretti”. (ctrl-V)</p> </li> <li> <p>Cliccare il pulsante <b>Aggiungi nuovo login diretto</b> , completare e verificare i dettagli della scheda, quindi cliccare su <b>Salva</b> .</p> </li> </ol> <p> </p> <p>Ulteriori informazioni sull&#x27;utilizzo della bookmarklet sono <a href=\"http://www.clipperz.com/support/user_guide/bookmarklet\" target=\"_blank\">disponibili qui</a> .</p> ",
+'mainPanelDirectLoginBlockLabel': "Login diretti",
+'directLinkReferenceShowButtonLabel': "mostra",
+'mainPanelDirectLoginBlockDescription': "<p>Crea “login diretti” per accedere ai tuoi servizi web senza bisogno di inserire username e password!</p> <p>I “login diretti” migliorano la tua sicurezza permettendoti di:</p> <ul> <li> <p>adottare comodamente password complesse;</p> </li> <li> <p>non riutilizzare mai la stessa password.</p> </li> </ul> <p>Semplice e rapido grazie alla <b>Clipperz bookmarklet</b> .</p><a href=\"http://www.clipperz.com/support/user_guide/direct_logins\" target=\"_blank\">Ulteriori informazioni</a> ",
+'mainPanelRecordsBlockLabel': "Schede",
+'mainPanelAddRecordButtonLabel': "Aggiungi nuova scheda",
+'mainPanelRemoveRecordButtonLabel': "Elimina scheda",
+'mainPanelRecordFilterBlockTagsLabel': "tags",
+'recordDetailNoRecordAtAllTitle': "Benvenuto a Clipperz!",
+'recordDetailNoRecordAtAllDescription': "<h5>Ora puoi iniziare ad aggiungere schede con le tue informazioni riservate.</h5> <p>Le schede sono semplici moduli in cui organizzare le tue password ed ogni altro tipo di dato confidenziale.</p> <p>Le schede hanno una struttura flessibile e si adattano a contenere le informazioni più diverse: dalle password ai dettagli delle tue carte di credito!</p> <h5>Non dimenticarti di installare la bookmarklet!</h5> <p>Prima di iniziare ti consigliamo di installare la bookmarklet “Aggiungi a Clipperz”: creare nuove schede diventerà più rapido e divertente.</p> <p>Vai alla sezione “bookmarklet” per scoprire come installarla ed utilizzarla.</p> <p> </p> <p>Quando sei pronto, clicca sul pulsante <b>Aggiungi nuova scheda</b> e metti al sicuro tutte le tue informazioni più preziose.</p> <p> </p><a href=\"http://www.clipperz.com/support/user_guide/managing_cards\" target=\"_blank\">Maggiori informazioni sulla creazione e gestione delle schede (in inglese)</a> ",
+'newRecordWizardTitleBox': "<h5>Seleziona un modello di scheda</h5> <p>Le schede sono semplici moduli in cui organizzare le tue password ed ogni altro tipo di dato confidenziale.</p> <p>Scegli un modello dall&#x27;elenco sottostante. In seguito potrai sempre modificare la tua scheda aggiungendo o rimuovendo campi.</p> ",
+'newRecordWizardBookmarkletConfigurationTitle': "Login diretto",
+'newRecordWizardBookmarkletConfigurationDescription': "<p>Incolla qui sotto il codice generato dalla bookmarklet di Clipperz.</p> <p>Verrà creata una nuova scheda già completa con le informazioni per il “login diretto” al tuo servizio web.</p> ",
+'newRecordWizardCreateButtonLabel': "Crea",
+'newRecordWizardCancelButtonLabel': "Annulla",
+'donateSplashPanelTitle': "Supporta Clipperz, fai una donazione oggi!",
+'donateSplashPanelDescription': "<p>Alcune buone ragioni per fare una donazione:</p> <ul> <li> <p>supportare lo sviluppo di nuove funzionalità</p> </li> <li> <p>mantenere il servizio gratuito per tutti</p> </li> <li> <p>mostrare la tua gratitudine per il nostro duro lavoro</p> </li> </ul> <p>Per qualunque ulteriore informazione visita la <a href=\"http://www.clipperz.com/donations\" target=\"_blank\">pagina delle donazioni</a> .</p> <p><b>Pronto a donare?</b> </p> ",
+'donateCloseButtonLabel': "Non ancora",
+'recordTemplates': {
+ 'WebAccount': {
+ 'title': "Password",
+ 'description': "<p>Una scheda molto semplice per conservare le credenziali di accesso ai tuoi servizi web.</p> ",
+ 'fields': {
+ 'URL': "Indirizzo web",
+ 'TXT': "Utente o email",
+ 'PWD': "Password"
+ }
+ },
+ 'BankAccount': {
+ 'title': "Conto corrente bancario",
+ 'description': "<p>Proteggi il tuo numero di conto corrente ed i codici di accesso ai servizi di online banking.</p> ",
+ 'fields': {
+ 'TXT': "Banca",
+ 'TXT': "Conto corrente n.",
+ 'URL': "Sito web della banca",
+ 'TXT': "Online banking ID",
+ 'PWD': "Online banking password"
+ }
+ },
+ 'CreditCard': {
+ 'title': "Carta di credito",
+ 'description': "<p>Numero della carta, data di scadenza, codici CVV2 e PIN sempre a portata di mano con Clipperz.</p> ",
+ 'fields': {
+ 'TXT': "Tipo (Visa, AmEx, ...)",
+ 'TXT': "Numero",
+ 'TXT': "Titolare",
+ 'TXT': "Data di scadenza",
+ 'TXT': "CVV2",
+ 'PWD': "PIN",
+ 'URL': "Sito web della carta",
+ 'TXT': "Utente",
+ 'PWD': "Password"
+ }
+ },
+ 'AddressBookEntry': {
+ 'title': "Voce della rubrica",
+ 'description': "<p>Fai di Clipperz la tua rubrica segreta. Usa questo modello per creare una nuova voce.</p> ",
+ 'fields': {
+ 'TXT': "Nome",
+ 'TXT': "Email",
+ 'TXT': "Telefono",
+ 'TXT': "Cellulare",
+ 'ADDR': "Indirizzo"
+ }
+ },
+ 'Custom': {
+ 'title': "Scheda personalizzata",
+ 'description': "<p>Qualunque sia il tipo di informazione che desideri proteggere, Clipperz ti consente di creare una scheda su misura per i tuoi bisogni.</p> ",
+ 'fields': {
+ 'TXT': "Nome del campo 1",
+ 'TXT': "Nome del campo 2",
+ 'TXT': "Nome del campo 3"
+ }
+ }
+},
+'recordFieldTypologies': {
+ 'TXT': {
+ 'description': "simple text field"
+ },
+ 'PWD': {
+ 'description': "simple text field, with default status set to hidden",
+ 'shortDescription': "Password"
+ },
+ 'URL': {
+ 'description': "simple text field in edit mode, that became an active url in view mode",
+ 'shortDescription': "Indirizzo web"
+ },
+ 'DATE': {
+ 'description': "a value set with a calendar helper",
+ 'shortDescription': "data"
+ },
+ 'ADDR': {
+ 'description': "just like the URL, but the active link points to Google Maps (or similar service) passing the address value as argument",
+ 'shortDescription': "indirizzo stradale"
+ },
+ 'CHECK': {
+ 'description': "check description",
+ 'shortDescription': "check"
+ },
+ 'RADIO': {
+ 'description': "radio description",
+ 'shortDescription': "radio"
+ },
+ 'SELECT': {
+ 'description': "select description",
+ 'shortDescription': "Seleziona:"
+ }
+},
+'newRecordPanelGeneralExceptionTitle': "Errore",
+'newRecordPanelGeneralExceptionMessage': "Configurazione non valida. Accertati di aver utilizzato il codice quello generato dalla bookmarklet.",
+'newRecordPanelWrongBookmarkletVersionExceptionTitle': "Errore",
+'newRecordPanelWrongBookmarkletVersionExceptionMessage': "La configurazione è stato generata da una vecchia versione della bookmarklet. Sei pregato di aggiornare subito la tua bookmarklet.",
+'newRecordPanelExceptionPanelCloseButtonLabel': "Annulla",
+'mainPanelDeletingRecordPanelConfirmationTitle': "Eliminazione della scheda in corso",
+'mainPanelDeleteRecordPanelConfirmationText': "Vuoi veramente eliminare la scheda selezionata?",
+'mainPanelDeletingRecordPanelInitialTitle': "Eliminazione della scheda in corso",
+'mainPanelDeletingRecordPanelInitialText': "---",
+'mainPanelDeletingRecordPanelCompletedText': "Fatto",
+'deleteRecordPanelCollectRecordDataMessageTitle': "Elimina scheda",
+'deleteRecordPanelCollectRecordDataMessageText': "Aggiorna elenco delle schede",
+'deleteRecordPanelEncryptUserDataMessageTitle': "Elimina scheda",
+'deleteRecordPanelEncryptUserDataMessageText': "Cripta localmente l&#x27;intestazione delle schede",
+'deleteRecordPanelSendingDataToTheServerMessageTitle': "Elimina scheda",
+'deleteRecordPanelSendingDataToTheServerMessageText': "Carica le intestazioni criptate delle schede su Clipperz",
+'deleteRecordPanelUpdatingTheInterfaceMessageTitle': "Elimina scheda",
+'deleteRecordPanelUpdatingTheInterfaceMessageText': "Aggiornamento dell&#x27;interfaccia",
+'recordDetailNoRecordSelectedTitle': "Nessuna scheda selezionata",
+'recordDetailNoRecordSelectedDescription': "<p>Selezionare una scheda dall&#x27;elenco a sinistra.</p> ",
+'recordDetailLoadingRecordMessage': "Scarica scheda criptata da Clipperz",
+'recordDetailDecryptingRecordMessage': "Decodifica locale dei dati della scheda",
+'recordDetailLoadingRecordVersionMessage': "Scarica l&#x27;ultima versione della scheda",
+'recordDetailDecryptingRecordVersionMessage': "Decodifica locale dell&#x27;ultima versione",
+'recordDetailLoadingErrorMessageTitle': "Errore nello scaricamento della scheda",
+'recordDetailNotesLabel': "Note",
+'recordDetailLabelFieldColumnLabel': "Nome del campo",
+'recordDetailDataFieldColumnLabel': "Dati del campo",
+'recordDetailTypeFieldColumnLabel': "Tipo",
+'recordDetailSavingChangesMessagePanelInitialTitle': "Salvataggio scheda",
+'recordDetailSavingChangesMessagePanelInitialText': "---",
+'recordDetailRemoveFieldButtonLabel': "-",
+'recordDetailAddFieldButtonLabel': "Aggiungi nuovo campo",
+'recordDetailPasswordFieldHelpLabel': "clicca le stelline per copiare la password e poi Ctrl-C",
+'recordDetailPasswordFieldScrambleLabel': "nascondi",
+'recordDetailPasswordFieldUnscrambleLabel': "mostra",
+'recordDetailDirectLoginBlockTitle': "Login diretti",
+'recordDetailNewDirectLoginDescription': "<p>Configurazione del login diretto</p> ",
+'recordDetailDirectLoginBlockNoDirectLoginConfiguredDescription': "<p>Questa scheda contiene credenziali di accesso ad un servizio online?</p> <p>In tal caso puoi utilizzare la bookmarklet per configurare un “login diretto” da Clipperz con un solo clic!</p> ",
+'recordDetailDeleteDirectLoginButtonLabel': "-",
+'recordDetailAddNewDirectLoginButtonLabel': "Aggiungi nuovo login diretto",
+'recordDetailEditButtonLabel': "Modifica",
+'recordDetailSaveButtonLabel': "Salva",
+'recordDetailCancelButtonLabel': "Annulla",
+'newRecordTitleLabel': "_nuova scheda_",
+'newDirectLoginLabelSuffix': "",
+'recordSaveChangesPanelCollectRecordInfoMessageTitle': "Salva scheda",
+'recordSaveChangesPanelCollectRecordInfoMessageText': "Aggiorna elenco delle schede",
+'recordSaveChangesPanelEncryptUserDataMessageTitle': "Salva scheda",
+'recordSaveChangesPanelEncryptUserDataMessageText': "Cripta localmente l&#x27;intestazione delle schede",
+'recordSaveChangesPanelEncryptRecordDataMessageTitle': "Salva scheda",
+'recordSaveChangesPanelEncryptRecordDataMessageText': "Cripta localmente i dati della scheda",
+'recordSaveChangesPanelEncryptRecordVersionDataMessageTitle': "Salva scheda",
+'recordSaveChangesPanelEncryptRecordVersionDataMessageText': "Cripta localmente la versione della scheda",
+'recordSaveChangesPanelSendingDataToTheServerMessageTitle': "Salva scheda",
+'recordSaveChangesPanelSendingDataToTheServerMessageText': "Carica le intestazioni criptate delle schede su Clipperz",
+'recordSaveChangesPanelUpdatingTheInterfaceMessageTitle': "Salva scheda",
+'recordSaveChangesPanelUpdatingTheInterfaceMessageText': "Aggiornamento dell&#x27;interfaccia",
+'passwordGeneratorPanelTitle': "Generatore di password",
+'passwordGeneratorPanelOkLabel': "Ok",
+'passwordGeneratorPanelCancelLabel': "Annulla",
+'passwordGeneratorLengthLabel': "lung . :",
+//'DWRUtilLoadingMessage': "Caricamento dati",
+'comingSoon': "Presto disponibile ...",
+'panelCollectingEntryopyMessageText': "Raccolta entropia",
+'importData_parsingDataTitle': "Importa",
+'importData_previewingDataTitle': "Importa",
+'importData_processingDataTitle': "Importa",
+'ImportWizard': {
+ 'EDIT': "Modifica",
+ 'IMPORT': "Importa",
+ 'CSV_NOTES': "Note",
+ 'EXCEL_EDIT': "Modifica"
+},
+'importData_importConfirmation_title': "Importa",
+'WELCOME_BACK': "Bentornato!",
+'currentConnectionText': "Sei collegato da ip __ip__; probabilmente in __country__, utilizzando __browser__ con __operatingSystem__.",
+'latestConnectionText': "Il tuo ultimo accesso è stato __elapsedTimeDescription__ (__time__) da ip __ip__; probabilmente in __country__, utilizzando __browser__ con __operatingSystem__.",
+'fullLoginHistoryLinkLabel': "vai al registro degli accessi",
+'elapsedTimeDescriptions': {
+ 'MORE_THAN_A_MONTH_AGO': "più di un mese fa",
+ 'MORE_THAN_A_WEEK_AGO': "più di una settimana fa",
+ 'MORE_THAN_*_WEEKS_AGO': "più di __elapsed__ settimane fa",
+ 'YESTERDAY': "ieri",
+ '*_DAYS_AGO': "__elapsed__ giorni fa",
+ 'ABOUT_AN_HOUR_AGO': "circa un&#x27;ora fa",
+ '*_HOURS_AGO': "__elapsed__ ore fa",
+ 'JUST_A_FEW_MINUTES_AGO': "pochi minuti fa",
+ 'ABOUT_*_MINUTES_AGO': "circa __elapsed__ minuti fa"
+},
+'unknown_ip': "sconosciuto",
+'countries': {
+ '--': "sconosciuto",
+ 'AD': "Andorra",
+ 'AE': "Emirati arabi uniti",
+ 'AF': "Afghanistan",
+ 'AG': "Antigua e Barbuda",
+ 'AI': "Anguilla",
+ 'AL': "Albania",
+ 'AM': "Armenia",
+ 'AN': "Antille olandesi",
+ 'AO': "Angola",
+ 'AR': "Argentina",
+ 'AS': "Samoa americane",
+ 'AT': "Austria",
+ 'AU': "Australia",
+ 'AW': "Aruba",
+ 'AZ': "Azerbaigian",
+ 'BB': "Barbados",
+ 'BD': "Bangladesh",
+ 'BE': "Belgio",
+ 'BF': "Burkina-Faso",
+ 'BG': "Bulgaria",
+ 'BH': "Bahrein",
+ 'BI': "Burundi",
+ 'BJ': "Benin",
+ 'BM': "Bermuda",
+ 'BN': "Brunei",
+ 'BO': "Bolivia",
+ 'BR': "Brasile",
+ 'BS': "Bahamas",
+ 'BT': "Bhutan",
+ 'BW': "Botswana",
+ 'BY': "Bielorussia",
+ 'BZ': "Belize",
+ 'CA': "Canada",
+ 'CD': "Repubblica democratica del Congo",
+ 'CF': "Repubblica centrafricana",
+ 'CH': "Svizzera",
+ 'CK': "Isole Cook",
+ 'CL': "Cile",
+ 'CM': "Camerun",
+ 'CN': "Cina",
+ 'CO': "Colombia",
+ 'CR': "Costa Rica",
+ 'CS': "Repubblica del Montenegro",
+ 'CU': "Cuba",
+ 'CY': "Cipro",
+ 'CZ': "Repubblica ceca",
+ 'DE': "Germania",
+ 'DJ': "Gibuti",
+ 'DK': "Danimarca",
+ 'DO': "Repubblica dominicana",
+ 'DZ': "Algeria",
+ 'EC': "Ecuador",
+ 'EE': "Estonia",
+ 'EG': "Egitto",
+ 'ER': "Eritrea",
+ 'ES': "Spagna",
+ 'ET': "Etiopia",
+ 'FI': "Finlandia",
+ 'FJ': "Figi",
+ 'FM': "Micronesia",
+ 'FO': "Isole Fær Øer",
+ 'FR': "Francia",
+ 'GA': "Gabon",
+ 'GB': "Regno Unito",
+ 'GD': "Grenada",
+ 'GE': "Georgia",
+ 'GF': "Guyana francese",
+ 'GG': "Guernsey",
+ 'GH': "Ghana",
+ 'GI': "Gibilterra",
+ 'GL': "Groenlandia",
+ 'GM': "Gambia",
+ 'GP': "Guadalupa",
+ 'GR': "Grecia",
+ 'GT': "Guatemala",
+ 'GU': "Guam",
+ 'GW': "Guinea-Bissau",
+ 'GY': "Guyana",
+ 'HK': "Hong Kong",
+ 'HN': "Honduras",
+ 'HT': "Haiti",
+ 'HU': "Ungheria",
+ 'ID': "Indonesia",
+ 'IE': "Irlanda",
+ 'IL': "Israele",
+ 'IM': "Isola di Man",
+ 'IN': "India",
+ 'IO': "Territorio britannico dell&#x27;Oceano Indiano",
+ 'IQ': "Iraq",
+ 'IR': "Iran",
+ 'IS': "Islanda",
+ 'IT': "Italia",
+ 'JE': "Jersey",
+ 'JM': "Giamaica",
+ 'JO': "Giordania",
+ 'JP': "Giappone",
+ 'KE': "Kenya",
+ 'KG': "Kirghizistan",
+ 'KH': "Cambogia",
+ 'KI': "Kiribati",
+ 'KN': "Saint Kitts e Nevis",
+ 'KR': "Corea del Sud",
+ 'KW': "Kuwait",
+ 'KY': "Isole Cayman",
+ 'KZ': "Kazakistan",
+ 'LA': "Laos",
+ 'LB': "Libano",
+ 'LC': "Saint Lucia",
+ 'LI': "Liechtenstein",
+ 'LK': "Sri Lanka",
+ 'LR': "Liberia",
+ 'LS': "Lesotho",
+ 'LT': "Lituania",
+ 'LU': "Lussemburgo",
+ 'LV': "Lettonia",
+ 'LY': "Libia",
+ 'MA': "Marocco",
+ 'MC': "Monaco",
+ 'MD': "Moldova",
+ 'MG': "Madagascar",
+ 'MH': "Isole Marshall",
+ 'ML': "Mali",
+ 'MM': "Myanmar",
+ 'MN': "Mongolia",
+ 'MP': "Marianne settentrionali",
+ 'MR': "Mauritania",
+ 'MS': "Montserrat",
+ 'MT': "Malta",
+ 'MU': "Maurizio",
+ 'MV': "Maldive",
+ 'MW': "Malawi",
+ 'MX': "Messico",
+ 'MY': "Malaysia",
+ 'MZ': "Mozambico",
+ 'NA': "Namibia",
+ 'NC': "Nuova Caledonia",
+ 'NF': "Isola Norfolk",
+ 'NG': "Nigeria",
+ 'NI': "Nicaragua",
+ 'NL': "Paesi Bassi",
+ 'NO': "Norvegia",
+ 'NP': "Nepal",
+ 'NR': "Nauru",
+ 'NU': "Niue",
+ 'NZ': "Nuova Zelanda",
+ 'OM': "Oman",
+ 'PA': "Panama",
+ 'PE': "Perù",
+ 'PF': "Polinesia francese",
+ 'PG': "Papua Nuova Guinea",
+ 'PH': "Filippine",
+ 'PK': "Pakistan",
+ 'PL': "Polonia",
+ 'PR': "Puerto Rico",
+ 'PS': "Territori palestinesi",
+ 'PT': "Portogallo",
+ 'PW': "Palau",
+ 'PY': "Paraguay",
+ 'QA': "Qatar",
+ 'RO': "Romania",
+ 'RS': "Serbia",
+ 'RU': "Russia",
+ 'RW': "Ruanda",
+ 'SA': "Arabia Saudita",
+ 'SB': "Isole Salomone",
+ 'SC': "Seicelle",
+ 'SD': "Sudan",
+ 'SE': "Svezia",
+ 'SG': "Singapore",
+ 'SI': "Slovenia",
+ 'SL': "Sierra Leone",
+ 'SM': "San Marino",
+ 'SN': "Senegal",
+ 'SR': "Suriname",
+ 'SV': "El Salvador",
+ 'SY': "Siria",
+ 'SZ': "Swaziland",
+ 'TC': "Turks e Caicos",
+ 'TG': "Togo",
+ 'TH': "Thailandia",
+ 'TJ': "Tagikistan",
+ 'TM': "Turkmenistan",
+ 'TN': "Tunisia",
+ 'TO': "Tonga",
+ 'TR': "Turchia",
+ 'TV': "Tuvalu",
+ 'TW': "Taiwan",
+ 'TZ': "Tanzania",
+ 'UA': "Ucraina",
+ 'UG': "Uganda",
+ 'US': "Stati Uniti",
+ 'UY': "Uruguay",
+ 'UZ': "Uzbekistan",
+ 'VA': "Santa Sede (Stato della Città del Vaticano)",
+ 'VE': "Venezuela",
+ 'VG': "Isole Vergini britanniche",
+ 'VI': "Isole Vergini statunitensi",
+ 'VN': "Vietnam",
+ 'VU': "Vanuatu",
+ 'WS': "Samoa",
+ 'YE': "Yemen",
+ 'ZA': "Sud Africa",
+ 'ZM': "Zambia",
+ 'ZW': "Zimbabwe"
+},
+'browsers': {
+ 'UNKNOWN': "sconosciuto"
+},
+'operatingSystems': {
+ 'UNKNOWN': "sconosciuto",
+ 'MOBILE': "Cellulare"
+},
+'calendarStrings': {
+ 'months': {
+ '0': "Gennaio",
+ '1': "Febbraio",
+ '2': "Marzo",
+ '3': "Aprile",
+ '4': "Mag",
+ '5': "Giugno",
+ '6': "Luglio",
+ '7': "Agosto",
+ '8': "Settembre",
+ '9': "Ottobre",
+ '10': "Novembre",
+ '11': "Dicembre"
+ },
+ 'shortMonths': {
+ '0': "Gen",
+ '1': "Feb",
+ '2': "Mar",
+ '3': "Apr",
+ '4': "Mag",
+ '5': "Giu",
+ '6': "Lug",
+ '7': "Ago",
+ '8': "Set",
+ '9': "Ott",
+ '10': "Nov",
+ '11': "Dic"
+ },
+ 'days': {
+ '0': "Domenica",
+ '1': "Lunedì",
+ '2': "Martedì",
+ '3': "Mercoledì",
+ '4': "Giovedì",
+ '5': "Venerdì",
+ '6': "Sabato"
+ },
+ 'shortDays': {
+ '0': "Dom",
+ '2': "Mar",
+ '3': "Mer",
+ '4': "Gio",
+ '5': "Ven",
+ '6': "Sab"
+ },
+ 'veryShortDays': {
+ '1': "Lu",
+ '4': "Gi",
+ '5': "Ve"
+ }
+},
+
+__syntaxFix__: "syntax fix"
+});
diff --git a/frontend/beta/js/Clipperz/PM/Strings/Strings_ja-JP.js b/frontend/beta/js/Clipperz/PM/Strings/Strings_ja-JP.js
new file mode 100644
index 0000000..2b571b7
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Strings/Strings_ja-JP.js
@@ -0,0 +1,808 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+Clipperz.PM.Strings.Languages['ja-JP'.toLowerCase()] = MochiKit.Base.merge(Clipperz.PM.Strings.Languages['en-us'], {
+'clipperzServiceDescription': "<h2>自分で管理しよう!</h2> <ul> <li> <h3>Clipperz は</h3> <ul> <li> <p>安全でシンプルなパスワードマネージャです</p> </li> <li> <p>シングルサインオンを提供します</p> </li> <li> <p>機密情報のデジタル格納庫です</p> </li> </ul> </li> <li> <h3>Clipperz でできること</h3> <ul> <li> <p>パスワードを保管して管理できます</p> </li> <li> <p>ユーザー名やパスワードを入力せずに登録したウェブサービスにログインできます</p> </li> <li> <p>暗証番号やクレジットカード番号などあらゆる機密情報を守ります</p> </li> <li> <p>家族や信用できる相手と機密情報を共有できます(提供予定)</p> </li> </ul> </li> <li> <h3>Clipperz のよいところ</h3> <ul> <li> <p>無料で匿名利用できます</p> </li> <li> <p>いつでもどのコンピュータからでもアクセスできます</p> </li> <li> <p>ソフトウェアのダウンロードやインストールは不要です</p> </li> <li> <p>PC や紙に機密情報を残す必要がありません</p> </li> </ul> </li> <li> <h3>Clipperz のセキュリティ</h3> <ul> <li> <p>データはブラウザで暗号化されてから Clipprez に送信されます</p> </li> <li> <p>暗号化のキーはあなただけが知っているパスフレーズです</p> </li> <li> <p>保管したデータは暗号化されていて、保管中には決して中身を見ることができません</p> </li> <li> <p>標準が確立された暗号化手順を採用しています</p> </li> <li> <p>ソースコードはいつでも参照できますが、暗号化について何も知らなくても使えます</p> </li> </ul> </li> <li><a href=\"http://www.clipperz.com\" target=\"_blank\">もっと見る</a> </li> </ul> ",
+'loginFormTitle': "Clipperz のアカウントでログイン",
+'loginFormUsernameLabel': "ユーザー名",
+'loginFormPassphraseLabel': "パスフレーズ",
+'loginFormDontHaveAnAccountLabel': "アカウントを持っていない?",
+'loginFormCreateOneLabel': "新規作成",
+'loginFormForgotYourCredentialsLabel': "パスフレーズを忘れた?",
+'loginFormAarghThatsBadLabel': "それは困った!",
+'loginFormAfraidOfMaliciousScriptsLabel': "偽サイトかも?",
+'loginFormVerifyTheCodeLabel': "確認する",
+'loginFormButtonLabel': "ログイン",
+'loginFormOneTimePasswordCheckboxLabel': "ワンタイムパスフレーズ使用",
+'loginFormOneTimePasswordCheckboxDescription': "",
+'loginPanelSwithLanguageDescription': "<h5>言語設定の変更</h5> ",
+'browserCompatibilityDescription': "<p>Clipperz は Firefox に最適化されています。 しかし Clipperz は Opera や Safari そしてインターネットエクスプローラでも十分動作します。</p> ",
+'OTPloginMessagePanelInitialTitle': "ワンタイムパスフレーズでログイン中",
+'OTPloginMessagePanelInitialText': "OTP 情報送信中 ...",
+'OTPloginMessagePanelLoadingTitle': "ワンタイムパスフレーズでログイン中",
+'OTPloginMessagePanelLoadingText': "認証情報を取得中 ...",
+'OTPloginMessagePanelProcessingTitle': "ワンタイムパスフレーズでログイン中",
+'OTPloginMessagePanelProcessingText': "認証情報を復号中 ...",
+'loginMessagePanelInitialTitle': "ログイン中 ...",
+'loginMessagePanelInitialText': "---",
+'loginMessagePanelInitialButtonLabel': "キャンセル",
+'loginMessagePanelConnectedTitle': "接続完了",
+'loginMessagePanelConnectedText': "完了",
+'loginMessagePanelFailureTitle': "エラー",
+'loginMessagePanelFailureText': "ログインに失敗しました",
+'loginMessagePanelFailureButtonLabel': "閉じる",
+'connectionLoginSendingCredentialsMessageTitle': "認証確認中",
+'connectionLoginSendingCredentialsMessageText': "認証送信中",
+'connectionLoginCredentialsVerificationMessageTitle': "認証確認中",
+'connectionLoginCredentialsVerificationMessageText': "SRP 認証中",
+'connectionLoginDoneMessageTitle': "認証確認中",
+'connectionLoginDoneMessageText': "接続完了",
+'userLoginPanelUpgradingUserCredentialsMessageTitle': "認証確認中",
+'userLoginPanelUpgradingUserCredentialsMessageText': "認証更新中",
+'userLoginPanelConnectedMessageTitle': "認証完了",
+'userLoginPanelConnectedMessageText': "ログイン完了",
+'userLoginPanelTryingAnOlderConnectionSchemaMessageTitle': "認証確認中",
+'userLoginPanelTryingAnOlderConnectionSchemaMessageText': "認証復元中",
+'userLoginPanelLoadingUserDataMessageTitle': "認証完了",
+'userLoginPanelLoadingUserDataMessageText': "暗号化データを受信中",
+'userLoginPanelDecryptingUserDataMessageTitle': "認証完了",
+'userLoginPanelDecryptingUserDataMessageText': "復号中",
+'userLoginPanelDecryptingUserStatisticsMessageTitle': "認証完了",
+'userLoginPanelDecryptingUserStatisticsMessageText': "復号中",
+'splashAlertTitle': "Clipperz へようこそ",
+'splashAlertText': "<p>セキュリティアドバイス</p> <ul> <li> <p>Clipperz に保管したデータはパスフレーズによって保護されます。 パスフレーズを知らない人はデータにアクセスできません。</p> </li> <li> <p>Clipperz に重要なデータを保管するためにパスフレーズを類推されにくいものにしてください。 長いほど安全です。</p> </li> <li> <p>パスフレーズを忘れてしまったら Clipperz ではデータを復元できません。</p> </li> </ul> <p>さらに詳しくは Clipperz のサイトをごらんください。</p> ",
+'splashAlertCloseButtonLabel': "OK",
+'registrationFormTitle': "新規アカウント作成",
+'registrationFormUsernameLabel': "ユーザー名",
+'registrationFormPassphraseLabel': "パスフレーズ",
+'registrationFormRetypePassphraseLabel': "パスフレーズをもう一度",
+'registrationFormSafetyCheckLabel': "パスフレーズを忘れたら復活できないことを了承します。",
+'registrationFormTermsOfServiceCheckLabel': "利用許諾に同意します 。",
+'registrationFormDoYouAlreadyHaveAnAccountLabel': "アカウントを持っている?",
+'registrationFormSimplyLoginLabel': "すぐにログイン",
+'registrationFormButtonLabel': "登録",
+'registrationFormWarningMessageNotMatchingPassphrases': "パスフレーズの入力に誤りがあります。 再入力してください。",
+'registrationFormWarningMessageSafetyCheckNotSelected': "説明を読んで下のボックスを全てチェックしてください。",
+'registrationFormWarningMessageTermsOfServiceCheckNotSelected': "利用許諾に同意してください。",
+'registrationMessagePanelInitialTitle': "アカウント作成中 ...",
+'registrationMessagePanelInitialText': "---",
+'registrationMessagePanelInitialButtonLabel': "キャンセル",
+'registrationMessagePanelRegistrationDoneTitle': "登録",
+'registrationMessagePanelRegistrationDoneText': "完了",
+'registrationMessagePanelFailureTitle': "登録失敗",
+'registrationMessagePanelFailureButtonLabel': "閉じる",
+'connectionRegistrationSendingRequestMessageText': "認証確認中",
+'connectionRegistrationSendingCredentialsMessageText': "認証送信中",
+'registrationSplashPanelTitle': "セキュリティアドバイス",
+'registrationSplashPanelDescription': "<p>Clipperz の認証情報です。 大切に保管してください。 ユーザー名とパスフレーズは二度と表示されません。</p> ",
+'registrationSplashPanelUsernameLabel': "ユーザー名",
+'registrationSplashPanelPassphraseLabel': "パスフレーズ",
+'registrationSplashPanelShowPassphraseButtonLabel': "パスフレーズを表示",
+'donateHeaderLinkLabel': "寄付",
+'creditsHeaderLinkLabel': "クレジット",
+'feedbackHeaderLinkLabel': "フィードバック",
+'helpHeaderLinkLabel': "ヘルプ",
+'forumHeaderLinkLabel': "フォーラム",
+'recordMenuLabel': "カード",
+'accountMenuLabel': "アカウント",
+'dataMenuLabel': "データ",
+'contactsMenuLabel': "コンタクト",
+'toolsMenuLabel': "ツール",
+'logoutMenuLabel': "ログアウト",
+'lockMenuLabel': "ロック",
+'lockTitle': "アカウントはロックされました",
+'lockDescription': "<p>ロックを解除するにはパスフレーズを入力してください。</p> ",
+'unlockButtonLabel': "解除",
+'changePasswordTabLabel': "パスフレーズの変更",
+'changePasswordTabTitle': "パスフレーズの変更",
+'changePasswordFormUsernameLabel': "ユーザー名",
+'changePasswordFormOldPassphraseLabel': "今のパスフレーズ",
+'changePasswordFormNewPassphraseLabel': "新しいパスフレーズ",
+'changePasswordFormRetypePassphraseLabel': "パスフレーズをもう一度",
+'changePasswordFormSafetyCheckboxLabel': "パスフレーズを忘れたら復活できないことを了承します。",
+'changePasswordFormSubmitLabel': "変更",
+'changePasswordFormWrongUsernameWarning': "ユーザー名が違います",
+'changePasswordFormWrongPassphraseWarning': "パスフレーズが違います",
+'changePasswordFormWrongRetypePassphraseWarning': "パスフレーズの入力に誤りがあります。 再入力してください。",
+'changePasswordFormSafetyCheckWarning': "説明を読んでボックスをチェックしてください。",
+'changePasswordFormProgressDialogTitle': "認証情報を変更中",
+'changePasswordFormProgressDialogEmptyText': "---",
+'changePasswordFormProgressDialogConnectedMessageTitle': "接続完了",
+'changePasswordFormProgressDialogConnectedMessageText': "完了",
+'changePasswordFormProgressDialogErrorMessageTitle': "エラー",
+'changePasswordFormProgressDialogErrorMessageText': "変更に失敗しました",
+'changeCredentialsPanelEncryptingDataMessageTitle': "パスフレーズを変更中",
+'changeCredentialsPanelEncryptingDataMessageText': "カードヘッダ暗号化",
+'changeCredentialsPanelCreatingNewCredentialsMessageTitle': "パスフレーズを変更中",
+'changeCredentialsPanelCreatingNewCredentialsMessageText': "認証情報を送信中",
+'changeCredentialsPanelSendingNewCredentialsToTheServerMessageTitle': "パスフレーズを変更中",
+'changeCredentialsPanelSendingNewCredentialsToTheServerMessageText': "暗号化データを送信中",
+'changeCredentialsPanelDoneMessageTitle': "パスフレーズを変更中",
+'changeCredentialsPanelDoneMessageText': "完了",
+'manageOTPTabLabel': "ワンタイムパスフレーズ管理",
+'manageOTPTabTitle': "ワンタイムパスフレーズ管理",
+'manageOTPTabDescription': "<p>ワンタイムパスフレーズは通常のパスフレームと同様に機能しますが、一回限りの使い捨てパスフレーズです。</p> <p>同じパスフレーズで再度ログインすることはできません。</p> <p>不正アクセス防止のためにログインに成功したら直ちにワンタイムパスフレーズは削除されます</p> <p>ワンタイムパスフレーズはキーロガーやスパイウェアからパスフレーズを守るすばらしい機能です</p> <p><b>インターネットカフェや図書館などから Clipperz にアクセする場合にはワンタイムパスフレーズを利用することを強くお薦めします。</b> </p> ",
+'oneTimePasswordReadOnlyMessage': "<h6>ごめんなさい</h6> <p>ローカルコピー使用中はワンタイムパスフレーズを利用できません。</p> ",
+'oneTimePasswordLoadingMessage': "<h6>ロード中</h6> <p>お待ちください ...</p> ",
+'oneTimePasswordNoPasswordAvailable': "<h6>有効なワンタイムパスフレーズがありません</h6> <p>「新規」ボタンをクリックしてワンタイムパスフレーズを作成してください。</p> ",
+'createNewOTPButtonLabel': "新規",
+'deleteOTPButtonLabel': "削除",
+'printOTPButtonLabel': "印刷",
+'disabledOneTimePassword_warning': "無効",
+'oneTimePasswordSelectionLink_selectLabel': "選択:",
+'oneTimePasswordSelectionLink_all': "すべて",
+'oneTimePasswordSelectionLink_none': "解除",
+'oneTimePasswordSelectionLink_used': "使用済",
+'oneTimePasswordSelectionLink_unused': "未使用",
+'saveOTP_encryptUserDataTitle': "ワンタイムパスフレーズを保存中",
+'saveOTP_encryptUserDataText': "OTP 認証譲歩を作成中 ...",
+'saveOTP_encryptOTPDataTitle': "ワンタイムパスフレーズを保存中",
+'saveOTP_encryptOTPDataText': "暗号化データを作成中 ...",
+'saveOTP_sendingDataTitle': "ワンタイムパスフレーズを保存中",
+'saveOTP_sendingDataText': "暗号化データを送信中 ...",
+'saveOTP_updatingInterfaceTitle': "ワンタイムパスフレーズを保存中",
+'saveOTP_updatingInterfaceText': "インターフェイスを更新中 ...",
+'accountPreferencesLabel': "設定",
+'accountPreferencesTabTitle': "設定",
+'accountPreferencesLanguageTitle': "言語設定",
+'accountPreferencesLanguageDescription': "<p>リストから使用する言語を選択してください。</p> ",
+'showDonationReminderPanelTitle': "ドネーションリマインダ",
+'showDonationReminderPanelDescription': "<p>ドネーションリマインダを表示</p> ",
+'saveUserPreferencesFormSubmitLabel': "保存",
+'cancelUserPreferencesFormSubmitLabel': "キャンセル",
+'accountPreferencesSavingPanelTitle_Step1': "保存中",
+'accountPreferencesSavingPanelText_Step1': "暗号化中",
+'accountPreferencesSavingPanelTitle_Step2': "保存中",
+'accountPreferencesSavingPanelText_Step2': "送信中",
+'accountLoginHistoryLabel': "ログイン履歴",
+'loginHistoryTabTitle': "ログイン履歴",
+'loginHistoryReadOnlyMessage': "<h6>ごめんなさい</h6> <p>ローカルコピー使用中はログイン履歴を利用できません。</p> ",
+'loginHistoryLoadingMessage': "<h6>ロード中</h6> <p>お待ちください ...</p> ",
+'loginHistoryLoadedMessage': "<h6>最近 10 回のログイン</h6> <p> </p> ",
+'loginHistoryIPLabel': "IP",
+'loginHistoryTimeLabel': "日付",
+'loginHistoryCurrentSessionText': "現在のログイン",
+'loginHistoryReloadButtonLabel': "ログイン履歴を更新",
+'deleteAccountTabLabel': "アカウント削除",
+'deleteAccountTabTitle': "アカウント削除",
+'deleteAccountFormUsernameLabel': "ユーザー名",
+'deleteAccountFormPassphraseLabel': "パスフレーズ",
+'deleteAccountFormSafetyCheckboxLabel': "全てのデータが消去されて復元不可能になることを了承します。",
+'deleteAccountFormSubmitLabel': "アカウント削除",
+'deleteAccountFormWrongUsernameWarning': "ユーザー名が違います",
+'deleteAccountFormWrongPassphraseWarning': "パスフレーズが違います",
+'deleteAccountFormSafetyCheckWarning': "説明を読んでボックスをチェックしてください。",
+'accountPanelDeletingAccountPanelConfirmationTitle': "確認",
+'accountPanelDeleteAccountPanelConfirmationText': "本当にアカウントを削除しますか?",
+'accountPanelDeleteAccountPanelConfirmButtonLabel': "はい",
+'accountPanelDeleteAccountPanelDenyButtonLabel': "いいえ",
+'accountPanelDeletingAccountPanelProgressTitle': "アカウント情報削除中",
+'accountPanelDeletingAccountPanelProgressText': "しばらくお待ちください",
+'offlineCopyTabLabel': "ローカルコピー",
+'offlineCopyTabTitle': "ローカルコピー",
+'offlineCopyTabDescription': "<p>ダウンロードのリンクをクリクするとインターネットに接続していないときでも利用できる読み取り専用のローカル版をダウンロードできます。</p> <p>ローカル版はオンライン版と同じ暗号化処理がされているため、編集可能なオンライン版と同じ安全性があります。</p> <ol> <li> <p>下の「ダウンロード」をクリックします。</p> </li> <li> <p>ブラウザーが &quot;Clipperz_YYYYMMDD.html&quot; をダウンロードするか確認します。 ファイルをハードディスクに保存してください。</p> </li> <li> <p>ローカルコピーをダブルクリックして起動してください。</p> </li> <li> <p>オンライン版と同じユーザー名とパスフレーズを入力してください。</p> </li> </ol> ",
+'offlineCopyDownloadLinkLabel': "ダウンロード",
+'offlineCopyDownloadWarning': "<h4><a href=\"#\" id=\"offlineCopyDownloadWarningLink\">ローカルコピーを更新してください</a> </h4> <p>ローカルコピーを作成後に新しいカードを追加または編集しています。 最新の情報を保つためローカルコピーを更新してください。</p> ",
+'offlineCopyDownloadOk': "",
+'sharingTabLabel': "共有",
+'sharingTabTitle': "共有",
+'sharingTabDescription': "<p>暗証番号などを他人に教える必要があることは日常生活で往々にして発生します。</p> <p>同僚に留守番電話のメッセージを代わりに聞いてもらうために暗証番号を教えたり、秘書に代わりに銀行に行ってもらうために暗証番号を教えたりということはよくあることです。</p> <p>Clipperz では機密情報を安全に、そして簡単に共有できます。</p> <p> </p> <p><b>近日登場 ...</b> </p> ",
+'importTabLabel': "インポート",
+'importTabTitle': "インポート",
+'importTabDescription': "<p>コンピュータから Clipperz にデータを一括インポートできます。</p> ",
+'printingTabLabel': "エクスポート",
+'printingTabTitle': "エクスポート",
+'printingTabDescription': "<h5>印刷</h5> <p>「印刷用データ」のリンクをクリックするとウィンドウが開いて全てのデータが印刷可能な状態で表示されます。</p> <p>バックアップが目的なら、誰でも見ることができる印刷版よりは安全なローカルコピーをお薦めします。</p> ",
+'printingLinkLabel': "印刷用データ",
+'exportTabDescription': "<h5>JSON エクスポート</h5> <p>JSON はすべてのデータをエクスポートできます。 ダイレクトログインを含むすべての情報が保存されます。</p> <p>このフォーマットはすべてのデータを別の Clipperz アカウントに移動するときに便利です。 トラブルが発生したときにデータを復旧するのにも役立ちます。</p> <p>「JSON 出力」のリンクをクリックするとエクスポートが開始されます。</p> ",
+'exportLinkLabel': "JSON 出力",
+'exportDataInProgressDescription': "<h4>出力中。しばらくお待ちください ...</h4> ",
+'exportDataDescription': "<h4>利用法</h4> <p>下のテキストを任意のエディターにコピーして保存します。 (例: 「clipperz_export_20071217.json」)</p> ",
+'contactsTabLabel': "コンタクト",
+'contactsTabTitle': "コンタクト",
+'passwordGeneratorTabLabel': "パスワードジェネレータ",
+'bookmarkletTabLabel': "ブックマークレット",
+'compactTabLabel': "コンパクト版",
+'httpAuthTabLabel': "HTTP 認証",
+'passwordGeneratorTabTitle': "パスワードジェネレータ",
+'bookmarkletTabTitle': "ブックマークレット",
+'compactTabTitle': "コンパクト版",
+'httpAuthTabTitle': "HTTP 認証",
+'paswordGeneratorTabDescription': "<p> </p> ",
+'passwordGeneratorTabButtonLabel': "パスワード生成",
+'bookmarkletTabLabel': "ブックマークレット",
+'bookmarkletTabTitle': "ブックマークレット",
+'bookmarkletTabDescription': "<p>ブックマークレットはブラウザのブックマークに登録して使う小さなプログラムです。 通常のウェブページのブックマークと同じようにブラウザに登録できます。</p> <p>Clipperz のブックマークレットを使えば簡単に新規カードを追加したり、既存のカードにダイレクトログインを追加したりできます。</p> <p><b>Clipperz のブックマークレットにはユーザー名やパスフレーズなどの個人情報は含まれていません。ブックマークレットは全ユーザー共通のものです。</b> </p> <h3>ブックマークレットの登録方法</h3> <h>Firefox, Camino, Opera, Safari <ol> <li> <p>ブックマークバー(パーソナルバー)が表示されていることを確認します。 (「表示」メニュー(「表示>ツールバー」サブメニューの場合もあり)から変更できます。)</p> </li> <li> <p>下の「Clipperz に追加」をブックマークバー(パーソナルバー)にドラッグします。</p> </li> </ol> <h5>インターネットエクスプローラー</h5> <ol> <li> <p>アドレスバーが表示されていることを確認します。 (「表示>ツールバー>アドレスバー」メニューから変更できます。)</p> </li> <li> <p>下の「Clipperz に追加」を右クリックします。</p> </li> <li> <p>コンテキストメニューから「お気に入りに追加」を選択します。</p> </li> <li> <p>セキュリティ警告が表示されますので「はい」をクリックします。</p> </li> <li> <p>保存先の「リンク」フォルダーを開き「OK」をクリックします。</p> </li> </ol> ",
+'bookmarkletTabBookmarkletTitle': "Clipperz に追加",
+'bookmarkletTabInstructions': "<h3>ダイレクトログイン用の新規カードの作成方法</h3> <ol> <li> <p>保存したいサービスのログインページを開きます。 (パスワードなどを入力する画面があるところです)</p> </li> <li> <p>ブックマークレットをクリックします。 画面上にウィンドウがポップアップします。</p> </li> <li> <p>ポップアップしたウィンドウに表示された登録用コードをコピーします。 (ctrl-C)</p> </li> <li> <p>Clipperz にログインして 「新規カード追加」のボタンをクリックします。</p> </li> <li> <p>「ダイレクトログイン」のテンプレートを選んでコード入力用のスペースに先ほどコピーしたコードを貼り付けます。 (ctrl-V)</p> </li> <li> <p>「作成」ボタンをクリックして、内容を確認して「保存」ボタンをクリックします。</p> </li> </ol> <h3>既存カードへのダイレクトログインの追加方法</h3> <ol> <li> <p>上記と同じです。</p> </li> <li> <p>上記と同じです。</p> </li> <li> <p>上記と同じです。</p> </li> <li> <p>Clipperz にログインして変更したいカードを選択後「編集」ボタンをクリックします。</p> </li> <li> <p>ダイレクトログインコード用のスペースに先ほどコピーしたコードを貼り付けます。 (ctrl-V)</p> </li> <li> <p>「ダイレクトログイン追加」ボタンをクリックして、内容を確認して「保存」ボタンをクリックします。</p> </li> </ol> <p> </p> <p>ブックマークレットに関する詳しい情報はこちら。</p> ",
+'compactTabDescription': "<p>Clipprez Compact は Firefox のサイドバーで利用するようデザインされた Clipperz の特別版です。</p> <p>ダイレクトログインを常時アクセス可能にします。 さらに詳しく </p> <h3>Clipperz Compact の利用法</h3> <ol> <li> <p>Firefox を入手します。 サイドバーは Firefox だけで利用できるため、 Clipperz Compact を利用するには Firefox が必須です。</p> </li> <li> <p>下の「Clipperz Compact」 URL を Firefox のブックマークに登録します。ブックマークバーにドラッグするのが簡単です。</p> <div id=\"compactLinkBox\"><a href=\"https://www.clipperz.com/beta/index.html?compact\" target=\"_search\">Clipperz Compact</a> </div> </li> <li> <p>ブックマークを右クリックして「情報を見る」を選択後、「このブックマークをサイドバーに読み込む」にチェックを入れます。</p> </li> </ol> <h5>追加情報:Clipperz Compact は Opera のパネルでも操作します。</h5> ",
+'httpAuthTabDescription': "<p>HTTP 認証は HTML の基本機能を使ってブラウザからユーザー名とパスワードでログインする方式です。</p> <p>すでに主流ではありませんが、またプライベートなサイトなどで使われています。 HTTP 認証が必要なサイトにアクセスしようとすると、ブラウザがポップアップウィンドウを開いてユーザー名とパスワードの入力を要求してきます。</p> <p>残念ながら、 Clipperz のブックマークレットは HTTP 認証には対応していません。 しかし、ダイレクトログインを設定する方法はあります。</p> <h3>HTTP 認証サイトでのダイレクトログイン設定方法</h3> <ol> <li> <p>サイトの URL とユーザー名、パスワードを新規カードに登録します。</p> </li> <li> <p>下記の設定をコピーして、カード編集画面の「ダイレクトログイン設定」のセクションに貼り付けます。</p> </li> <li> <p>「新規ダイレクトログイン追加」ボタンをクリックして、 URL とユーザー名、パスワードを入力して保存します。</p> </li> </ol> <h5><a href=\"http://support.microsoft.com/kb/834489\" target=\"_blank\">警告:インターネットエクスプローラは HTTP 認証に対応していません。</a> </h5> ",
+'mainPanelDirectLoginBlockLabel': "ダイレクトログイン",
+'directLinkReferenceShowButtonLabel': "表示",
+'mainPanelDirectLoginBlockDescription': "<p>ダイレクトログインを設定してユーザー名やパスワードを入力することなくログインできるようにしましょう。</p> <p>ダイレクトログインでさらにセキュリティを強化するために:</p> <ul> <li> <p>より複雑なパスワードを設定しましょう</p> </li> <li> <p>推測されやすい同じパスワードを複数のサイトで使わないようにしましょう。</p> </li> </ul> <p>ブックマークレットを使うと簡単に設定できます。</p><a href=\"http://www.clipperz.com/support/user_guide/direct_logins\" target=\"_blank\">ダイレクトログインに関する詳しい情報</a> ",
+'mainPanelRecordsBlockLabel': "カード",
+'mainPanelAddRecordButtonLabel': "新規カード追加",
+'mainPanelRemoveRecordButtonLabel': "カード削除",
+'mainPanelRecordFilterBlockAllLabel': "すべて",
+'mainPanelRecordFilterBlockTagsLabel': "タグ",
+'mainPanelRecordFilterBlockSearchLabel': "検索",
+'recordDetailNoRecordAtAllTitle': "Clipperz へようこそ",
+'recordDetailNoRecordAtAllDescription': "<h5>まず最初にカードを追加しましょう。</h5> <p>カードはパスワードやその他の重要な情報を保管するためのシンプルでフレキシブルなフォームです。</p> <p>カードにはウェブサイトのログインパスワード、自転車の鍵の番号、クレジットカードの番号など何でも記入できます。</p> <h5>ブックマークレットを活用しましょう。</h5> <p>まずは簡単にカードを追加できるブックマークレットをインストールしましょう。</p> <p>ブックマークレットのタブをクリックしてインストール方法と利用方法を確認しましょう。</p> <p> </p> <p>ブックマークレットをインストールしたら Clipperz を活用しましょう。</p> <p> </p><a href=\"http://www.clipperz.com/support/user_guide/managing_cards\" target=\"_blank\">カードに関する詳しい情報</a> ",
+'newRecordWizardTitleBox': "<h5>テンプレート選択</h5> <p>カードはシンプルでパスワードや重要な情報を何でも保存できる柔軟性があります。</p> <p>まずはテンプレートを選んでください。  カードはいつでも自由に変更できます。</p> ",
+'newRecordWizardBookmarkletConfigurationTitle': "ダイレクトログイン",
+'newRecordWizardBookmarkletConfigurationDescription': "<p>ブックマークレットが生成したコードを下に貼り付けてください。</p> <p>ダイレクトログイン情報を含む新しいカードが作成されます。</p> ",
+'newRecordWizardCreateButtonLabel': "作成",
+'newRecordWizardCancelButtonLabel': "キャンセル",
+'donateSplashPanelTitle': "Clipperz のために今すぐ寄付しよう",
+'donateSplashPanelDescription': "<p>寄付する理由:</p> <ul> <li> <p>新機能追加をサポートします</p> </li> <li> <p>Clipperz を無料に保ちます</p> </li> <li> <p>開発陣の仕事に感謝します</p> </li> </ul> <p>詳しくは寄付のページをごらんください .</p> <p><b>寄付しますか?</b> </p> ",
+'donateCloseButtonLabel': "あとでする",
+'donateDonateButtonLabel': "はい",
+'recordTemplates': {
+ 'WebAccount': {
+ 'title': "ウェブパスワード",
+ 'description': "<p>ログイン情報用のシンプルなカードです。</p> ",
+ 'fields': {
+ 'URL': "ウェブアドレス",
+ 'TXT': "ユーザー名またはメールアドレス",
+ 'PWD': "パスワード"
+ }
+ },
+ 'BankAccount': {
+ 'title': "銀行口座",
+ 'description': "<p>口座番号とオンラインバンキング情報用のカードです。</p> ",
+ 'fields': {
+ 'TXT': "銀行",
+ 'TXT': "口座番号",
+ 'URL': "銀行サイト",
+ 'TXT': "オンラインバンキング ID",
+ 'PWD': "オンラインバンキングパスワード"
+ }
+ },
+ 'CreditCard': {
+ 'title': "クレジットカード",
+ 'description': "<p>クレジットカードに関するあらゆる情報を保管できます。</p> ",
+ 'fields': {
+ 'TXT': "種類(Visa 、 AMEX など)",
+ 'TXT': "番号",
+ 'TXT': "所有者名",
+ 'TXT': "有効期限",
+ 'TXT': "CVV2 番号",
+ 'PWD': "暗証番号",
+ 'URL': "カード会社サイト",
+ 'TXT': "ユーザー名",
+ 'PWD': "パスワード"
+ }
+ },
+ 'AddressBookEntry': {
+ 'title': "アドレス帳",
+ 'description': "<p>Clipperz はプライベートなアドレス帳としても機能します。 このテンプレートを利用して簡単に新しい住所を追加できます。</p> ",
+ 'fields': {
+ 'TXT': "名前",
+ 'TXT': "メールアドレス",
+ 'TXT': "電話番号",
+ 'TXT': "携帯電話",
+ 'ADDR': "住所"
+ }
+ },
+ 'Custom': {
+ 'title': "カスタムカード",
+ 'description': "<p>カスタムカードを使えばどんな情報でも保管できます。</p> ",
+ 'fields': {
+ 'TXT': "ラベル 1",
+ 'TXT': "ラベル 2",
+ 'TXT': "ラベル 3"
+ }
+ }
+},
+'recordFieldTypologies': {
+ 'TXT': {
+ 'description': "テキスト入力欄",
+ 'shortDescription': "テキスト"
+ },
+ 'PWD': {
+ 'description': "通常は非表示になるテキスト入力欄",
+ 'shortDescription': "パスワード"
+ },
+ 'URL': {
+ 'description': "表示モードではクリックできる URL 入力欄",
+ 'shortDescription': "ウェブアドレス"
+ },
+ 'DATE': {
+ 'description': "日付入力欄",
+ 'shortDescription': "日付"
+ },
+ 'ADDR': {
+ 'description': "Google マップ用の URL に似た文字列",
+ 'shortDescription': "住所"
+ },
+ 'CHECK': {
+ 'description': "チェックボックスの詳細",
+ 'shortDescription': "チェックボックス"
+ },
+ 'RADIO': {
+ 'description': "ラジオボタンの詳細",
+ 'shortDescription': "ラジオボタン"
+ },
+ 'SELECT': {
+ 'description': "セレクトリストの詳細",
+ 'shortDescription': "セレクトリスト"
+ }
+},
+'newRecordPanelGeneralExceptionTitle': "エラー",
+'newRecordPanelGeneralExceptionMessage': "コードが不正です。 ブックマークレットを確認してもう一度やり直してください。",
+'newRecordPanelWrongBookmarkletVersionExceptionTitle': "エラー",
+'newRecordPanelWrongBookmarkletVersionExceptionMessage': "古いバージョンのブックマークレットで生成されたコードです。 ブックマークレットを更新してやり直してください。",
+'newRecordPanelExceptionPanelCloseButtonLabel': "キャンセル",
+'mainPanelDeletingRecordPanelConfirmationTitle': "カード削除中",
+'mainPanelDeleteRecordPanelConfirmationText': "本当に削除しますか?",
+'mainPanelDeleteRecordPanelConfirmButtonLabel': "はい",
+'mainPanelDeleteRecordPanelDenyButtonLabel': "いいえ",
+'mainPanelDeletingRecordPanelInitialTitle': "カード削除中",
+'mainPanelDeletingRecordPanelInitialText': "---",
+'mainPanelDeletingRecordPanelCompletedText': "完了",
+'deleteRecordPanelCollectRecordDataMessageTitle': "カード削除",
+'deleteRecordPanelCollectRecordDataMessageText': "カードリスト更新中",
+'deleteRecordPanelEncryptUserDataMessageTitle': "カード削除",
+'deleteRecordPanelEncryptUserDataMessageText': "カードヘッダ暗号化",
+'deleteRecordPanelSendingDataToTheServerMessageTitle': "カード削除",
+'deleteRecordPanelSendingDataToTheServerMessageText': "送信中",
+'deleteRecordPanelUpdatingTheInterfaceMessageTitle': "カード削除",
+'deleteRecordPanelUpdatingTheInterfaceMessageText': "更新中",
+'recordDetailNoRecordSelectedTitle': "カードが選択されていません",
+'recordDetailNoRecordSelectedDescription': "<p>左のリストからカードを選択してください。</p> ",
+'recordDetailLoadingRecordMessage': "データ受信中",
+'recordDetailDecryptingRecordMessage': "データ復元中",
+'recordDetailLoadingRecordVersionMessage': "最新情報を受信中",
+'recordDetailDecryptingRecordVersionMessage': "最新情報を復元中",
+'recordDetailLoadingErrorMessageTitle': "受信エラー",
+'recordDetailNotesLabel': "ノート",
+'recordDetailLabelFieldColumnLabel': "ラベル",
+'recordDetailDataFieldColumnLabel': "データ",
+'recordDetailTypeFieldColumnLabel': "タイプ",
+'recordDetailSavingChangesMessagePanelInitialTitle': "保存中",
+'recordDetailSavingChangesMessagePanelInitialText': "---",
+'recordDetailRemoveFieldButtonLabel': "-",
+'recordDetailAddFieldButtonLabel': "フィールド追加",
+'recordDetailPasswordFieldHelpLabel': "パスワードをコピーするには星マークをクリックして ctrl-C をタイプします",
+'recordDetailPasswordFieldScrambleLabel': "隠す",
+'recordDetailPasswordFieldUnscrambleLabel': "可視化",
+'recordDetailDirectLoginBlockTitle': "ダイレクトログイン",
+'recordDetailNewDirectLoginDescription': "<p>ダイレクトログイン設定</p> ",
+'recordDetailDirectLoginBlockNoDirectLoginConfiguredDescription': "<p>オンラインサービスのログイン情報を含んでいますか?</p> <p>ブックマークレットを使ってダイレクトログインを設定しましょう!</p> ",
+'recordDetailDeleteDirectLoginButtonLabel': "-",
+'recordDetailAddNewDirectLoginButtonLabel': "新規ダイレクトログイン追加",
+'recordDetailEditButtonLabel': "編集",
+'recordDetailSaveButtonLabel': "保存",
+'recordDetailCancelButtonLabel': "キャンセル",
+'newRecordTitleLabel': "_新規カード_",
+'newDirectLoginLabelSuffix': "",
+'recordSaveChangesPanelCollectRecordInfoMessageTitle': "カード保存",
+'recordSaveChangesPanelCollectRecordInfoMessageText': "更新中",
+'recordSaveChangesPanelEncryptUserDataMessageTitle': "カード保存",
+'recordSaveChangesPanelEncryptUserDataMessageText': "カードヘッダ暗号化",
+'recordSaveChangesPanelEncryptRecordDataMessageTitle': "カード保存",
+'recordSaveChangesPanelEncryptRecordDataMessageText': "カードデータ暗号化",
+'recordSaveChangesPanelEncryptRecordVersionDataMessageTitle': "カード保存",
+'recordSaveChangesPanelEncryptRecordVersionDataMessageText': "バージョンデータ暗号化",
+'recordSaveChangesPanelSendingDataToTheServerMessageTitle': "カード保存",
+'recordSaveChangesPanelSendingDataToTheServerMessageText': "カード送信中",
+'recordSaveChangesPanelUpdatingTheInterfaceMessageTitle': "カード保存",
+'recordSaveChangesPanelUpdatingTheInterfaceMessageText': "更新中",
+'passwordGeneratorPanelTitle': "パスワードジェネレータ",
+'passwordGeneratorPanelOkLabel': "OK",
+'passwordGeneratorPanelCancelLabel': "キャンセル",
+'passwordGeneratorLowercaseLabel': "abc",
+'passwordGeneratorUppercaseLabel': "ABC",
+'passwordGeneratorNumberLabel': "012",
+'passwordGeneratorSymbolLabel': "@#$",
+'passwordGeneratorLengthLabel': "文字数:",
+//'DWRUtilLoadingMessage': "ロード中 ...",
+'comingSoon': "近日登場 ...",
+'panelCollectingEntryopyMessageText': "整頓中",
+'directLoginConfigurationCheckBoxFieldSelectedValue': "はい",
+'directLoginConfigurationCheckBoxFieldNotSelectedValue': "いいえ",
+'importFormats': {
+ 'CSV': {
+ 'label': "CSV",
+ 'description': "<p>広く普及しているフォーマットです。 いくつかのパスワードマネージャは CSV でのエクスポートに対応しています。</p>"
+ },
+ 'Excel': {
+ 'label': "エクセル",
+ 'description': "<p>マイクロソフトの有名な表計算ソフトです。 エクセルのファイルでパスワードを保存することは広く行われていますがおすすめできません。</p>"
+ },
+ 'KeePass': {
+ 'label': "KeePass",
+ 'description': "<p>パスワードマネージャ KeePass で生成されるテキストファイルです。</p>"
+ },
+ 'PasswordPlus': {
+ 'label': "Password Plus",
+ 'description': "<p>パスワードマネージャ Password Plus で生成される CSV ファイルです。</p>"
+ },
+ 'Roboform': {
+ 'label': "RoboForm",
+ 'description': "<p>パスワードマネージャ Roboform で印刷用に表示される HTML ファイルです。</p>"
+ },
+ 'ClipperzExport': {
+ 'label': "JSON",
+ 'description': "<p>Clipperz で生成されるフォーマットです。 ダイレクトログインを含むすべての情報が含まれます。</p>"
+ }
+},
+'Clipperz_ImportWizard_Title': "JSON インポート",
+'importOptions_clipperz_description': "<p>Clipperz で生成された JSON ファイルをテキストエディタで開きます。 次に下のテキストエリアにファイルの内容をコピーします。</p> ",
+'CSV_ImportWizard_Title': "CSV インポート",
+'importOptions_csv_description_': "<p>CSV ファイルをテキストエディタで開きます。 下のテキストエリアにファイルの内容をコピーします。</p> <p>区切り記号などを選択します。</p> ",
+'Excel_ImportWizard_Title': "エクセルインポート",
+'importOptions_excel_description_': "<p>エクセルでファイルを開いてインポートしたいセルを選択します。 次に下のテキストエリアに選択したセルをコピーします。</p> ",
+'KeePass_ImportWizard_Title': "KeePass インポート",
+'importOptions_keePass_description_': "<p>KeePas で生成されたファイルをテキストエディタで開きます。 次に下のテキストエリアにファイルの内容をコピーします。</p> ",
+'PasswordPlus_ImportWizard_Title': "Password Plus インポート",
+'importOptions_passwordPlus_description': "<p>Password Plus で生成された CSV ファイルをテキストエディタで開きます。 下のテキストエリアにファイルの内容をコピーします。</p> ",
+'RoboForm_ImportWizard_Title': "RoboForm インポート",
+'importOptions_roboForm_description': "<p>RoboForm で生成された HTML ファイルをテキストエディタで開きます。 次に下のテキストエリアにファイルの内容をコピーします。</p> ",
+'importData_parsingDataTitle': "インポート",
+'importData_parsingDataText': "分析中 ...",
+'importData_previewingDataTitle': "インポート",
+'importData_previewingDataText': "変換中 ...",
+'importData_processingDataTitle': "インポート",
+'importData_processingDataText': "カード作成中 ...",
+'ImportWizard': {
+ 'EDIT': "編集",
+ 'PREVIEW': "プレビュー",
+ 'IMPORT': "インポート",
+ 'KEEPASS_SETTINGS': "設定",
+ 'CSV_EDIT': "貼り付け",
+ 'CSV_COLUMNS': "列",
+ 'CSV_HEADER': "ラベル",
+ 'CSV_TITLE': "タイトル",
+ 'CSV_NOTES': "ノート",
+ 'CSV_FIELDS': "タイプ",
+ 'EXCEL_EDIT': "編集"
+},
+'CSV_ImportWizard_Columns': "<p>インポートする列を選択してください。</p> ",
+'CSV_ImportWizard_Header': "<p>最初の行にラベルが含まれている場合、下のチェックボックスをチェックしてください。</p> ",
+'CSV_ImportWizard_Header_Settings_firstRowHeaderLabel': "先頭行をラベルとして利用する",
+'CSV_ImportWizard_Title': "<p>カードのタイトルになる列を選択してください。 (必須)</p>",
+'CSV_ImportWizard_Notes': "<p>ノートに相当する列を選択してください。 (オプション)</p> ",
+'CSV_ImportWizard_Notes_Settings_noSelectionLabel': "ノートは利用できません",
+'CSV_ImportWizard_Fields': "<p>それぞれの列のデータタイプをドロップダウンリストから選択してください。</p> ",
+'CSV_ImportWizard_Fields_MissingLabelWarning': "ラベルがありません",
+'importData_importConfirmation_title': "インポート",
+'importData_importConfirmation_text': "__numberOfRecords__ 枚のカードをインポートしますか?",
+'WELCOME_BACK': "おかえりなさい",
+'currentConnectionText': "あなたの利用 IP アドレスは __ip__, です。 country__, から __operatingSystem__ 版 __browser__ を利用しています。",
+'latestConnectionText': "前回の利用は __elapsedTimeDescription__ (__time__)、IP アドレスは __ip__, でした。 country__ から __operatingSystem__ 版 __browser__ を利用しました。",
+'fullLoginHistoryLinkLabel': "ログイン履歴を詳しく見る",
+'elapsedTimeDescriptions': {
+ 'MORE_THAN_A_MONTH_AGO': "1 か月以上前",
+ 'MORE_THAN_A_WEEK_AGO': "1 週間以上前",
+ 'MORE_THAN_*_WEEKS_AGO': "elapsed__ 週間以上前",
+ 'YESTERDAY': "昨日",
+ '*_DAYS_AGO': "__elapsed__ 日前",
+ 'ABOUT_AN_HOUR_AGO': "約 1 時間前",
+ '*_HOURS_AGO': "__elapsed__ 時間前",
+ 'JUST_A_FEW_MINUTES_AGO': "直前",
+ 'ABOUT_*_MINUTES_AGO': "約 __elapsed__ 分前"
+},
+'unknown_ip': "不明",
+'countries': {
+ '--': "不明",
+ 'AD': "アンドラ",
+ 'AE': "アラブ首長国連邦",
+ 'AF': "アフガニスタン",
+ 'AG': "アンティグアバーブーダ",
+ 'AI': "アングイラ",
+ 'AL': "アルバニア",
+ 'AM': "アルメニア",
+ 'AN': "オランダ アンティル諸島",
+ 'AO': "アンゴラ",
+ 'AP': "その他のアジアパシフィック地域",
+ 'AR': "アルゼンチン",
+ 'AS': "米国領サモア",
+ 'AT': "オーストリア",
+ 'AU': "オーストラリア",
+ 'AW': "アルーバ",
+ 'AX': "アーラント諸島",
+ 'AZ': "アゼルバイジャン",
+ 'BA': "ボスニア・ヘルツェゴビナ",
+ 'BB': "バルバドス",
+ 'BD': "バングラデシュ",
+ 'BE': "ベルギー",
+ 'BF': "ブルキナファソ",
+ 'BG': "ブルガリア",
+ 'BH': "バーレーン",
+ 'BI': "ブルンジ",
+ 'BJ': "ベナン",
+ 'BN': "ブルネイダルサラーム",
+ 'BO': "ボリビア",
+ 'BR': "ブラジル",
+ 'BS': "バハマ",
+ 'BT': "ブータン",
+ 'BW': "ボツワナ",
+ 'BY': "ベラルーシ",
+ 'BZ': "ベリーズ",
+ 'CA': "カナダ",
+ 'CD': "コンゴ民主共和国",
+ 'CF': "中央アフリカ共和国",
+ 'CH': "スイス",
+ 'CI': "コートジボワール",
+ 'CK': "クック諸島",
+ 'CL': "チリ",
+ 'CM': "カメルーン",
+ 'CN': "中国",
+ 'CO': "コロンビア",
+ 'CR': "コスタリカ",
+ 'CS': "セルビア・モンテネグロ",
+ 'CU': "キューバ",
+ 'CY': "キプロス",
+ 'CZ': "チェコ共和国",
+ 'DE': "ドイツ",
+ 'DJ': "ジブチ",
+ 'DK': "デンマーク",
+ 'DO': "ドミニカ共和国",
+ 'DZ': "アルジェリア",
+ 'EC': "エクアドル",
+ 'EE': "エストニア",
+ 'EG': "エジプト",
+ 'ER': "エリトリア",
+ 'ES': "スペイン",
+ 'ET': "エチオピア",
+ 'EU': "欧州連合",
+ 'FI': "フィンランド",
+ 'FJ': "フィジー",
+ 'FM': "ミクロネシア連邦邦国",
+ 'FR': "フランス",
+ 'GA': "ガボン",
+ 'GB': "英国",
+ 'GD': "グラナダ",
+ 'GE': "グルジア",
+ 'GF': "仏領ギアナ",
+ 'GG': "ガーンジー",
+ 'GH': "ガーナ",
+ 'GI': "ジブラルタル",
+ 'GL': "グリーンランド",
+ 'GP': "グアドロープ",
+ 'GR': "ギリシャ",
+ 'GT': "カタロニア",
+ 'GU': "グアム",
+ 'GW': "ギニアビサウ",
+ 'GY': "ガイアナ",
+ 'HK': "香港",
+ 'HN': "ホンデュラス",
+ 'HR': "クロアチア",
+ 'HT': "ハイチ",
+ 'HU': "ハンガリー",
+ 'ID': "インドネシア",
+ 'IE': "アイルランド",
+ 'IL': "イスラエル",
+ 'IM': "マン島",
+ 'IN': "インド",
+ 'IO': "英領インド洋植民地",
+ 'IQ': "イラク",
+ 'IR': "イラン・イスラム共和国",
+ 'IS': "アイスランド",
+ 'IT': "イタリア",
+ 'JE': "ジャージー",
+ 'JO': "ヨルダン",
+ 'JP': "日本",
+ 'KE': "ケニア",
+ 'KG': "キルギスタン",
+ 'KH': "カンボジア",
+ 'KI': "キリバス",
+ 'KN': "セントキッツネヴィス",
+ 'KR': "大韓民国 (韓国)",
+ 'KW': "クウェート",
+ 'KY': "カイマン諸島",
+ 'KZ': "カザフスタン",
+ 'LA': "ラオス人民民主共和国",
+ 'LB': "レバノン",
+ 'LC': "セントルシア",
+ 'LI': "リヒテンシュタイン",
+ 'LK': "スリランカ",
+ 'LR': "リベリア",
+ 'LS': "レソト",
+ 'LT': "リトアニア",
+ 'LU': "ルクセンブルグ",
+ 'LV': "ラトビア",
+ 'LY': "リビア・アラブ・Jamahiriya",
+ 'MA': "モロッコ",
+ 'MC': "モナコ",
+ 'MD': "モルドバ共和国",
+ 'MG': "マダガスカル",
+ 'MH': "マーシャル諸島",
+ 'MK': "マケドニア共和国",
+ 'ML': "マリ",
+ 'MM': "ミャンマー",
+ 'MN': "モンゴル",
+ 'MO': "マカオ",
+ 'MP': "北マリアナ諸島",
+ 'MR': "モーリタニア",
+ 'MT': "マルタ",
+ 'MU': "モーリシャス",
+ 'MV': "モルジヴ",
+ 'MW': "マラウイ",
+ 'MX': "メキシコ",
+ 'MY': "マレーシア",
+ 'MZ': "モザンビーク",
+ 'NA': "ナミビア",
+ 'NC': "ニューカレドニア",
+ 'NF': "ノーフォーク諸島",
+ 'NG': "ナイジェリア",
+ 'NI': "ニカラグア",
+ 'NL': "オランダ",
+ 'NO': "ノルウェー",
+ 'NP': "ネパール",
+ 'NR': "ナウル",
+ 'NU': "ニウエ",
+ 'NZ': "ニュージーランド",
+ 'OM': "オマーン",
+ 'PA': "パナマ",
+ 'PE': "ペルー",
+ 'PF': "仏領ポリネシア",
+ 'PG': "パプアニューギニア",
+ 'PH': "フィリピン",
+ 'PK': "パキスタン",
+ 'PL': "ポーランド",
+ 'PR': "プエルトリコ",
+ 'PS': "パレスチナ占領地区",
+ 'PT': "ポルトガル",
+ 'PW': "パラオ",
+ 'PY': "パラグアイ",
+ 'QA': "カタール",
+ 'RO': "ルーマニア",
+ 'RS': "セルビア",
+ 'RU': "ロシア連邦",
+ 'RW': "ルワンダ",
+ 'SA': "サウジアラビア",
+ 'SB': "ソロモン諸島",
+ 'SC': "セイシェル",
+ 'SD': "スーダン",
+ 'SE': "スウェーデン",
+ 'SG': "シンガポール",
+ 'SI': "スロベニア",
+ 'SK': "スロバキア",
+ 'SL': "シエラレオネ",
+ 'SM': "サンマリノ",
+ 'SN': "セネガル",
+ 'SR': "スリナム",
+ 'SV': "エルサルバドル",
+ 'SY': "シリアアラブ共和国",
+ 'SZ': "スワジランド",
+ 'TC': "タークスアンドケーコス諸島",
+ 'TG': "トーゴ",
+ 'TH': "タイ",
+ 'TJ': "タジキスタン",
+ 'TM': "トルクメニスタン",
+ 'TN': "チュニジア",
+ 'TO': "トンガ",
+ 'TR': "トルコ",
+ 'TT': "トリニダードトバコ",
+ 'TV': "ツヴァル",
+ 'TW': "中国領・台湾",
+ 'TZ': "タニザニア連合共和国",
+ 'UA': "ウクライナ",
+ 'UG': "ウガンダ",
+ 'US': "アメリカ合衆国",
+ 'UY': "ウルグアイ",
+ 'UZ': "ウズベキスタン",
+ 'VA': "聖庁 (バチカン市国)",
+ 'VE': "ベネズェラ",
+ 'VG': "英国ヴァージン諸島",
+ 'VI': "米国ヴァージン諸島",
+ 'VN': "ベトナム",
+ 'VU': "バヌアツ",
+ 'WF': "ワリーエフトゥーナ諸島",
+ 'WS': "サモア",
+ 'YE': "イエメン",
+ 'ZA': "南アフリカ",
+ 'ZM': "ザンビア",
+ 'ZW': "ジンバブエ",
+ 'ZZ': "Reserved"
+},
+'browsers': {
+ 'UNKNOWN': "不明",
+ 'MSIE': "インターネットエクスプローラー",
+ 'FIREFOX': "Firefox",
+ 'OPERA': "Opera",
+ 'SAFARI': "Safari",
+ 'OMNIWEB': "OmniWeb",
+ 'CAMINO': "Camino"
+},
+'operatingSystems': {
+ 'UNKNOWN': "不明",
+ 'WINDOWS': "ウィンドウズ",
+ 'MAC': "Mac",
+ 'LINUX': "Linux",
+ 'IPHONE': "iPhone",
+ 'MOBILE': "携帯電話",
+ 'OPENBSD': "OpenBSD",
+ 'FREEBSD': "FreeBSD",
+ 'NETBSD': "NetBSD"
+},
+'calendarStrings': {
+ 'months': {
+ '0': "1 月",
+ '1': "2 月",
+ '2': "3 月",
+ '3': "4 月",
+ '4': "5",
+ '5': "6 月",
+ '6': "7 月",
+ '7': "8 月",
+ '8': "9 月",
+ '9': "10 月",
+ '10': "11 月",
+ '11': "12 月"
+ },
+ 'shortMonths': {
+ '0': "1",
+ '1': "2",
+ '2': "3",
+ '3': "4",
+ '4': "5",
+ '5': "6",
+ '6': "7",
+ '7': "8",
+ '8': "9",
+ '9': "10",
+ '10': "11",
+ '11': "12"
+ },
+ 'days': {
+ '0': "日曜日",
+ '1': "月曜日",
+ '2': "火曜日",
+ '3': "水曜日",
+ '4': "木曜日",
+ '5': "金曜日",
+ '6': "土曜日"
+ },
+ 'shortDays': {
+ '0': "日",
+ '1': "月",
+ '2': "火",
+ '3': "水",
+ '4': "木",
+ '5': "金",
+ '6': "土"
+ },
+ 'veryShortDays': {
+ '0': "月",
+ '1': "月",
+ '2': "日",
+ '3': "金",
+ '4': "木",
+ '5': "金",
+ '6': "水"
+ },
+ 'amDesignation': "土",
+ 'pmDesignation': "午後"
+},
+'fullDate_format': "l, F d, Y H:i:s",
+
+__syntaxFix__: "syntax fix"
+});
diff --git a/frontend/beta/js/Clipperz/PM/Strings/Strings_pt-BR.js b/frontend/beta/js/Clipperz/PM/Strings/Strings_pt-BR.js
new file mode 100644
index 0000000..db6c2f6
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Strings/Strings_pt-BR.js
@@ -0,0 +1,478 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+Clipperz.PM.Strings.Languages['pt-BR'.toLowerCase()] = MochiKit.Base.merge(Clipperz.PM.Strings.Languages['en-us'], {
+'clipperzServiceDescriptionConfig': "<h2>Guarde com você!</h2> <ul> <li> <h3>Clipperz é:</h3> <ul> <li> <p>um simples e seguro gerenciador de senhas</p> </li> <li> <p>uma efetiva solução com uma única assinatura</p> </li> <li> <p>um cofre digital para suas informações confidenciais</p> </li> </ul> </li> <li> <h3>Com Clipperz você pode:</h3> <ul> <li> <p>guardar e gerenciar suas senhas e credenciais online</p> </li> <li> <p>logar em seus serviços web sem precisar entrar com nenhum nome de usuário ou senha</p> </li> <li> <p>proteger todos os seus dados sensíveis: códigos de alarme, PINs, números de cartão de crédito, &hellip;</p> </li> <li> <p>compartilhar segredos com membros da família e associados (em breve)</p> </li> </ul> </li> <li> <h3>Clipperz proporciona:</h3> <ul> <li> <p>anonimato completo e gratuito</p> </li> <li> <p>acesso a qualquer hora em qualquer computador</p> </li> <li> <p>sem software ou download e nada que instalar</p> </li> <li> <p>evite guardar seus segredos em seu PC ou papel</p> </li> </ul> </li> <li> <h3>Segurança Clipperz:</h3> <ul> <li> <p>seus segredos são codificados localmente por seu navegador antes de ser enviado para Clipperz</p> </li> <li> <p>a chave de codificação é uma senha que só você conhece</p> </li> <li> <p>Clipperz armazena apenas seus dados confidenciais codificados, nunca acessando os dados originais</p> </li> <li> <p>Clipperz é construído a partir de esquemas de codificação padrão, ou seja, nada é exclusivo ou caseiro</p> </li> <li> <p>você pode revisar o código a qualquer momento, mas você não precisa conhecer nada sobre criptograia para ser um usuário feliz!</p> </li> </ul> </li> <li> <a href=\"http://www.clipperz.com\" target=\"_blank\">Saiba mais</a> </li> </ul> ",
+'loginFormTitle': "entre sua conta Clipperz",
+'loginFormUsernameLabel': "nome do usuário",
+'loginFormPassphraseLabel': "frase chave",
+'loginFormDontHaveAnAccountLabel': "não tem uma conta?",
+'loginFormCreateOneLabel': "criar uma",
+'loginFormForgotYourCredentialsLabel': "esqueceu suas credenciais?",
+'loginFormAarghThatsBadLabel': "xiiiii! isso é não é bom!",
+'loginFormAfraidOfMaliciousScriptsLabel': "medo de scripts maliciosos?",
+'loginFormVerifyTheCodeLabel': "verifique o código",
+'loginFormButtonLabel': "Entrar",
+'loginFormOneTimePasswordCheckboxLabel': "use uma frase chave descartável",
+'loginPanelSwithLanguageDescription': "<h5>Mudar para sua linguagem preferida</h5> ",
+'browserCompatibilityDescription': "<p>Tenha uma experiência melhor e mais segura com Clipperz, utilizando o Firefox. No entanto, Clipperz funciona bem também em Opera e MS Internet Explorer!</p> ",
+'OTPloginMessagePanelInitialTitle': "Acessando usando a frase chave descartável",
+'OTPloginMessagePanelInitialText': "Enviando credenciais descartáveis ...",
+'OTPloginMessagePanelLoadingTitle': "Acessando usando a frase chave descartável",
+'OTPloginMessagePanelLoadingText': "Buscando informação de autenticação codificada no servidor ...",
+'OTPloginMessagePanelProcessingTitle': "Acessando usando a frase chave descartável",
+'OTPloginMessagePanelProcessingText': "Decodificação local da informação de autenticação ...",
+'loginMessagePanelInitialTitle': "Entrando ...",
+'loginMessagePanelInitialButtonLabel': "Cancelar",
+'loginMessagePanelConnectedTitle': "Conectado",
+'loginMessagePanelConnectedText': "Concluído",
+'loginMessagePanelFailureTitle': "Erro",
+'loginMessagePanelFailureText': "Ocorreu uma falha",
+'loginMessagePanelFailureButtonLabel': "Fechar",
+'connectionLoginSendingCredentialsMessageTitle': "Verificando credenciais",
+'connectionLoginSendingCredentialsMessageText': "Enviando credenciais",
+'connectionLoginCredentialsVerificationMessageTitle': "Verificando credenciais",
+'connectionLoginCredentialsVerificationMessageText': "Realizando autenticação SRP",
+'connectionLoginDoneMessageTitle': "Verificando credenciais",
+'connectionLoginDoneMessageText': "Conectado",
+'userLoginPanelUpgradingUserCredentialsMessageTitle': "Verificando credenciais",
+'userLoginPanelUpgradingUserCredentialsMessageText': "Upgrade de suas credenciais para um novo esquema de autenticação",
+'userLoginPanelConnectedMessageTitle': "Usuário autenticado",
+'userLoginPanelConnectedMessageText': "Logado com sucesso em",
+'userLoginPanelTryingAnOlderConnectionSchemaMessageTitle': "Verificando credenciais",
+'userLoginPanelTryingAnOlderConnectionSchemaMessageText': "Tentando esquema antigo de autenticação",
+'userLoginPanelLoadingUserDataMessageTitle': "Usuário autenticado",
+'userLoginPanelLoadingUserDataMessageText': "Baixando cabeçalhos de cartão codificados de Clipperz",
+'userLoginPanelDecryptingUserDataMessageTitle': "Usuário autenticado",
+'userLoginPanelDecryptingUserDataMessageText': "Descrição local de cabeçalhos dos cartões",
+'userLoginPanelDecryptingUserStatisticsMessageTitle': "Usuário autenticado",
+'userLoginPanelDecryptingUserStatisticsMessageText': "Descrição local de estatísticas de uso",
+'splashAlertTitle': "Bem-vindo ao Clipperz!",
+'splashAlertText': "<p>Alguns avisos de segurança</p> <ul> <li> <p>Guardar suas informações no Clipperz é tão seguro quanto a frase chave que você escolher para protege-los. Ninguém pode acessá-los sem essa frase chave.</p> </li> <li> <p>Se você vai utlizar Clipperz para armazenar suas informações confidenciais e críticas, escolha uma frase chave difícil de ser descoberta. Quanto mais longa, melhor!</p> </li> <li> <p>Clipperz não será capaz de recuperar frase chave perdidas!</p> </li> </ul> <p>Para mais informações, por favor vá até <a href=\"http://www.clipperz.com\" target=\"_blank\">Clipperz</a> website.</p> ",
+'splashAlertCloseButtonLabel': "Ok",
+'registrationFormTitle': "crie sua conta",
+'registrationFormUsernameLabel': "nome do usuário",
+'registrationFormPassphraseLabel': "frase chave",
+'registrationFormRetypePassphraseLabel': "entre novamente sua frase chave",
+'registrationFormSafetyCheckLabel': "Eu compreendo que Clipperz não será capaz de recuperar senhas perdidas.",
+'registrationFormTermsOfServiceCheckLabel': "Eu li e concordo com os <a href='http://www.clipperz.com/terms_of_service' target='_blank'>Termos do Serviço</a>.",
+'registrationFormDoYouAlreadyHaveAnAccountLabel': "você já tem uma conta?",
+'registrationFormSimplyLoginLabel': "login simples",
+'registrationFormButtonLabel': "Registrar",
+'registrationFormWarningMessageNotMatchingPassphrases': "Suas frases chaves não conferem, por favor tente novamente.",
+'registrationFormWarningMessageSafetyCheckNotSelected': "Por favor leia e confira todos os campos abaixo.",
+'registrationFormWarningMessageTermsOfServiceCheckNotSelected': "Você precisa concordar com os Termos do Serviço.",
+'registrationMessagePanelInitialTitle': "Criando conta ...",
+'registrationMessagePanelInitialText': "---",
+'registrationMessagePanelInitialButtonLabel': "Cancelar",
+'registrationMessagePanelRegistrationDoneTitle': "Registro",
+'registrationMessagePanelRegistrationDoneText': "Concluído",
+'registrationMessagePanelFailureTitle': "Registrou falhou",
+'registrationMessagePanelFailureButtonLabel': "Fechar",
+'connectionRegistrationSendingRequestMessageText': "Verificando credenciais",
+'connectionRegistrationSendingCredentialsMessageText': "Enviando credenciais",
+'registrationSplashPanelTitle': "Informe de segurança",
+'registrationSplashPanelDescription': "<p>Essas são suas credenciais Clipperz, cuide delas com cuidado. Clipperz nunca vai mostrar seu nome de usuário e frase chave uma outra vez!</p> ",
+'registrationSplashPanelUsernameLabel': "nome de usuário",
+'registrationSplashPanelPassphraseLabel': "frase chave",
+'registrationSplashPanelShowPassphraseButtonLabel': "mostrar frase chave",
+'donateHeaderLinkLabel': "doar",
+'creditsHeaderLinkLabel': "créditos",
+'feedbackHeaderLinkLabel': "feedback",
+'helpHeaderLinkLabel': "ajuda",
+'forumHeaderLinkLabel': "fórum",
+'recordMenuLabel': "cartões",
+'accountMenuLabel': "conta",
+'dataMenuLabel': "dados",
+'contactsMenuLabel': "contatos",
+'toolsMenuLabel': "ferramentas",
+'logoutMenuLabel': "sair",
+'lockMenuLabel': "bloquear",
+'lockTitle': "A conta está bloqueada",
+'lockDescription': "<p>Para desbloquear sua conta, por favor, entre com a frase chave</p> ",
+'unlockButtonLabel': "desbloquear",
+'changePasswordTabLabel': "Alterar sua frase chave",
+'changePasswordTabTitle': "Alterar sua frase chave",
+'changePasswordFormUsernameLabel': "nome de usuário",
+'changePasswordFormOldPassphraseLabel': "frase chave antiga",
+'changePasswordFormNewPassphraseLabel': "frase chave nova",
+'changePasswordFormRetypePassphraseLabel': "re-inserir frase chave nova",
+'changePasswordFormSafetyCheckboxLabel': "Eu compreendo que Clipperz não poderá recuperar a frase chave perdida.",
+'changePasswordFormSubmitLabel': "Alterar frase chave",
+'changePasswordFormWrongUsernameWarning': "Nome de usuário errado",
+'changePasswordFormWrongPassphraseWarning': "Frase chave errada",
+'changePasswordFormWrongRetypePassphraseWarning': "Suas frases chaves não conferem, por favor tente novamente.",
+'changePasswordFormSafetyCheckWarning': "Por favor leia e confira todos os campos abaixo.",
+'changePasswordFormProgressDialogTitle': "Alterando credenciais do usuário",
+'changePasswordFormProgressDialogConnectedMessageTitle': "Conectado",
+'changePasswordFormProgressDialogConnectedMessageText': "Concluído",
+'changePasswordFormProgressDialogErrorMessageTitle': "Erro",
+'changePasswordFormProgressDialogErrorMessageText': "Mudança de credenciais falhou!",
+'changeCredentialsPanelEncryptingDataMessageTitle': "Alterando sua frase chave",
+'changeCredentialsPanelEncryptingDataMessageText': "Codificação local de cabeçalho de cartões",
+'changeCredentialsPanelCreatingNewCredentialsMessageTitle': "Alterando sua frase chave",
+'changeCredentialsPanelCreatingNewCredentialsMessageText': "Atualizando suas credenciais",
+'changeCredentialsPanelSendingNewCredentialsToTheServerMessageTitle': "Alterando sua frase chave",
+'changeCredentialsPanelSendingNewCredentialsToTheServerMessageText': "Enviando suas credenciais codificadas para Clipperz",
+'changeCredentialsPanelDoneMessageTitle': "Alterando sua frase chave",
+'changeCredentialsPanelDoneMessageText': "Concluído",
+'manageOTPTabLabel': "Gerenciar suas frases chaves descartáveis",
+'manageOTPTabTitle': "Gerenciar suas frases chaves descartáveis",
+'manageOTPTabDescription': "<p>Uma frase chave descartável funciona como uma frase chave normal, mas só pode ser utilizada uma única vez.</p> <p>Se a mesma frase chave for utilizada novamente num próximo login, ela será rejeitada e o login não irá ocorrer.</p> <p>Imediatamente após um login com sucesso, sua frase chave descartável será apagada para evitar logins fraudulentos.</p> <p>Frases chaves descartáveis são uma excelente opção se você está preocupado com keyloggers ou spywares que podem estar coletando seus dados em determinadas máquinas.</p> <p> <b>É recomendável que você utilize frases chaves descartáveis sempre que utilizar terminais públicos como Internet cafés e bibliotecas.</b> </p> ",
+'oneTimePasswordReadOnlyMessage': "<h6>Desculpe!</h6> <p>Você não pode gerenciar sua frase chave descartável quando usando a versão offline do Clipperz.</p> ",
+'oneTimePasswordLoadingMessage': "<h6>Carregando informação</h6> <p>Por favor, aguarde ...</p> ",
+'oneTimePasswordNoPasswordAvailable': "<h6>Nenhuma frase chave descartável disponível</h6> <p>Clique o botão “Novo” acima para adicionar uma frase chave descartável em sua conta.</p> ",
+'createNewOTPButtonLabel': "Novo",
+'deleteOTPButtonLabel': "Apagar",
+'printOTPButtonLabel': "Imprimir",
+'disabledOneTimePassword_warning': "desativada",
+'oneTimePasswordSelectionLink_selectLabel': "Selecionar:",
+'oneTimePasswordSelectionLink_all': "tudo",
+'oneTimePasswordSelectionLink_none': "nenhum",
+'oneTimePasswordSelectionLink_used': "usado",
+'oneTimePasswordSelectionLink_unused': "não usado",
+'saveOTP_encryptUserDataTitle': "Salvando a frase chave descartável",
+'saveOTP_encryptUserDataText': "Processando novas credenciais descartáveis ...",
+'saveOTP_encryptOTPDataTitle': "Salvando a frase chave descartável",
+'saveOTP_encryptOTPDataText': "Codificação local da informação de autenticação ...",
+'saveOTP_sendingDataTitle': "Salvando a frase chave descartável",
+'saveOTP_sendingDataText': "Enviando informação de autenticação para o servidor ...",
+'saveOTP_updatingInterfaceTitle': "Salvando a frase chave descartável",
+'saveOTP_updatingInterfaceText': "Atualizando interface ...",
+'accountPreferencesLabel': "Preferências",
+'accountPreferencesTabTitle': "Preferências",
+'accountPreferencesLanguageTitle': "Seleção de idioma",
+'accountPreferencesLanguageDescription': "<p>Escolha seu idioma preferido da lista abaixo.</p> ",
+'showDonationReminderPanelTitle': "Lembretes de doação",
+'showDonationReminderPanelDescription': "<p>Mostrar lembretes de doação</p> ",
+'saveUserPreferencesFormSubmitLabel': "Salvar",
+'cancelUserPreferencesFormSubmitLabel': "Cancelar",
+'accountPreferencesSavingPanelTitle_Step1': "Salvando preferências",
+'accountPreferencesSavingPanelText_Step1': "Codificação local de suas preferências",
+'accountPreferencesSavingPanelTitle_Step2': "Salvando preferências",
+'accountPreferencesSavingPanelText_Step2': "Enviando informação codificada para o servidor",
+'accountLoginHistoryLabel': "Histórico de conexão",
+'loginHistoryTabTitle': "Histórico de conexão",
+'loginHistoryReadOnlyMessage': "<h6>Desculpe!</h6> <p>Seu histórico de conexão não está disponível quando usando uma versão offline do Clipperz.</p> ",
+'loginHistoryLoadingMessage': "<h6>Carregando informação</h6> <p>Por favor, aguarde ...</p> ",
+'loginHistoryLoadedMessageConfig': "<h6>Suas 10 últimas conexões</h6> <p> </p> ",
+'loginHistoryIPLabel': "IP",
+'loginHistoryTimeLabel': "data",
+'loginHistoryCurrentSessionText': "sessão atual",
+'loginHistoryReloadButtonLabel': "Recarregar histórico de conexão",
+'deleteAccountTabLabel': "Apagar sua conta",
+'deleteAccountTabTitle': "Apagar sua conta",
+'deleteAccountFormUsernameLabel': "nome de usuário",
+'deleteAccountFormPassphraseLabel': "frase chave",
+'deleteAccountFormSafetyCheckboxLabel': "Eu compreendo que toda minha informação será apagada e que esta ação é irreversível.",
+'deleteAccountFormSubmitLabel': "Apagar minha conta",
+'deleteAccountFormWrongUsernameWarning': "Nome de usuário errado",
+'deleteAccountFormWrongPassphraseWarning': "Frase chave errada",
+'deleteAccountFormSafetyCheckWarning': "Por favor leia e confira os campos abaixo.",
+'accountPanelDeletingAccountPanelConfirmationTitle': "ATENÇÃO",
+'accountPanelDeleteAccountPanelConfirmationText': "Você tem certeza que quer apagar esta conta?",
+'accountPanelDeleteAccountPanelConfirmButtonLabel': "Sim",
+'accountPanelDeleteAccountPanelDenyButtonLabel': "Não",
+'offlineCopyTabLabel': "Cópia offline",
+'offlineCopyTabTitle': "Cópia offline",
+'offlineCopyTabDescription': "<p>Com apenas um click você pode passar toda sua informação codificada dos servidores Clipperz para seu hard disk e criar uma versão read-only offline do Clipperz para ser utilizada quando você não estiver conectado na Internet.</p> <p>Essa versão read-only é tão segura quanto a versão online e não vai expor suas informações a riscos maiores já que ambas tem a mesma arquitetura de código e segurança.</p> <ol> <li> <p>Clique no link abaixo para iniciar o download.</p> </li> <li> <p>O navegador vai perguntar o que fazer com o arquivo “Clipperz_YYYYMMDD.html”. Grave-o em seu hard disk.</p> </li> <li> <p>Clique duas vezes no arquivo baixado para abrir a versão offline em seu navegador.</p> </li> <li> <p>Entre sua frase chave e nome de usuário como sempre faz.</p> </li> </ol> ",
+'offlineCopyDownloadLinkLabel': "Baixar",
+'offlineCopyDownloadWarningConfig': "<h4> <a href=\"#\" id=\"offlineCopyDownloadWarningLink\">Atualize sua “cópia offline”!</a> </h4> <p>Vocie recentemente criou ou modificou um ou mais cartões, seria inteligente baixar uma nova “cópia offline”.</p> ",
+'sharingTabLabel': "Compartilhar",
+'sharingTabTitle': "Compartilhar",
+'sharingTabDescriptionConfig': "<p>Frequentemente uma informação confidencial precisa ser compartilhada com uma ou mais pessoas.</p> <p>Isso pode ser tão simples quanto permitir o acesso de seus colegas ao seu voice mail quando você está fora do escritório, ou tão complicado quanto permitir que seus herdeiros acessem seu caixa num banco quando você morrer.</p> <p>Clipperz pode fazer o processo de compartilhamento simples e seguro.</p> <p> </p> <p> <b>Em breve ...</b> </p> ",
+'importTabLabel': "Importar",
+'importTabTitle': "Importar",
+'importTabDescription': "<p> <b>Em breve ...</b> <p> ",
+'printingTabLabel': "Exportar",
+'printingTabTitle': "Exportar",
+'printingTabDescription': "<p> <b>Versão para impressão</b> </p> <p>Clicando no link abaixo você abre uma nova janela contendo todos os seus cartões em formato de impressão.</p> <p>Se você vai impriir para backup, considere a opção mais segura criando uma “cópia offline”.</p> ",
+'printingLinkLabel': "Versão para impressão",
+'contactsTabLabel': "Contatos",
+'contactsTabTitle': "Contatos",
+'passwordGeneratorTabLabel': "Gerador de senhas",
+'passwordGeneratorTabTitle': "Gerador de senhas",
+'passwordGeneratorTabButtonLabel': "Gerar senha",
+'bookmarkletTabLabel': "Bookmarklet",
+'bookmarkletTabTitle': "Bookmarklet",
+'bookmarkletTabDescription': "<p>Um bookmarklet é uma ferramenta “one-click” que pode executar diversas tarefas úteis. Pode ser salva e utilizada como uma página web preferida normal.</p> <p>Os bookmarklet Clipperz vão ajudar você a a rapidamente criar novos cartões e novos logins diretos a partir dos cartões existentes.</p> <p> <b>Por favor, note que o bookmarklet não inclui nenhuma informação relacionada à sua conta (e.g. seu nome de usuário ou frase chave), o bookmarklet é um ferramenta contendo o mesmo código para todos ois usuários Clipperz.</b> </p> <h3>Como instalar o bookmarlet</h3> <h5>Firefox, Camino, Opera, Safari</h5> <ol> <li> <p>Assegure-se que a “Barra de Bookmarks” está visível, selecionando “View > Toolbars > Bookmarks”, ou menu similar no menu do navegador</p> </li> <li> <p>Arraste o link “Adicionar ao Clipperz” abaixo para a barra de bookmark.</p> </li> </ol> <h5>Internet Explorer</h5> <ol> <li> <p>Assegure-se que o barra de “Links” está visível selecionando “View > Toolbar > Links” no menu do navegador.</p> </li> <li> <p>Clique com o botão direito no link “Adicionar ao Clipperz” abaixo.</p> </li> <li> <p>Select “Selecione “Add to favorites” no menu contextual.</p> </li> <li> <p>Clique “Yes” para qualquer mensagem de segurança que surgir em pop-up.</p> </li> <li> <p>Abra o folder “Links” e clique “OK”.</p> </li> </ol> ",
+'bookmarkletTabBookmarkletTitle': "Adicionar ao Clipperz",
+'bookmarkletTabInstructions': "<h3>Como criar um novo cartão para acessar diretamente um serviço online</h3> <ol> <li> <p>Abra a página web onde o formulário de login está. (é a página onde você usualmente entra com suas credenciais)</p> </li> <li> <p>Dispare a preferência clicando nela: um pop-up vai aparecer sobre a página.</p> </li> <li> <p>Copie para o clipboard o conteúdo da área de texto do pop-up. (ctrl-C)</p> </li> <li> <p>Entre em sua conta Clipperz e clique no botão <b>Adicionar novo cartão</b>.</p> </li> <li> <p>Selecione o template de \"Login Direto\" e cole o conteúdo do clipboard para a grande área de texto do formulário. (ctrl-V)</p> </li> <li> <p>Pressione o botão <b>Criar</b>, reveja os detalhes e clique <b>Save</b>.</p> </li> </ol> <h3>Como adicionar login direto a um cartão existente</h3> <ol> <li> <p>Idem acima.</p> </li> <li> <p>Idem acima.</p> </li> <li> <p>Idem acima.</p> </li> <li> <p>Entre em sua conta Clipperz e selecione o cartão contendo as credenciais para o serviço web que você visitou e clique no botão <b>Editar</b>.</p> </li> <li> <p>Cole o conteúdo do clipboard para a grande área de texto da sessão “Logins diretos”. (ctrl-V)</p> </li> <li> <p>Pressione o botão <b>Adicionar login direto</b>, reveja os detalhes e clique <b>Salvar</b>.</p> </li> </ol> <p> </p> <p>Mais informações sobre as preferências estão <a href=\"http://www.clipperz.com/support/user_guide/bookmarklet\" target=\"_blank\">disponíveis aqui</a>.</p> ",
+'mainPanelDirectLoginBlockLabel': "Logins diretos",
+'directLinkReferenceShowButtonLabel': "mostrar",
+'mainPanelDirectLoginBlockDescription': "<p>Adicionar “logins diretos” para entrar em páginas web sem ter que digitar nome de usuário e senhas!</p> <p>“Logins diretos” ampliam a segurança de sus senha já que você pode:</p> <ul> <li> <p>utilizar senhas mais complexas;</p> </li> <li> <p>nunca re-utilizar a mesma senha fácil-de-lembrar.</p> </li> </ul> <p>Configuração simples e rápida com os <b>bookmarklet</b> Clipperz.</p> <a href=\"http://www.clipperz.com/support/user_guide/direct_logins\" target=\"_blank\">Saiba mais sobre “logins diretos”</a> ",
+'mainPanelRecordsBlockLabel': "Cartões",
+'mainPanelAddRecordButtonLabel': "Adicionar novo cartão",
+'mainPanelRemoveRecordButtonLabel': "Apagar cartão",
+'mainPanelRecordFilterBlockAllLabel': "todos",
+'mainPanelRecordFilterBlockTagsLabel': "tags",
+'mainPanelRecordFilterBlockSearchLabel': "buscar",
+'recordDetailNoRecordAtAllTitle': "Bem-vindo ao Clipperz!",
+'recordDetailNoRecordAtAllDescription': "<h5>Inicie criando cartões para sua conta.</h5> <p>Cartões são formulários simples e flexíveis onde você guarda senhas e outras informações confidenciais.</p> <p>Cartões podem conter credenciais de login a sites, a combinação do seu cadeado da bicicleta, detalhes do seu cartão de crédito, ...</p> <h5>Não esqueça o bookmarklet</h5> <p>Antes de começar, instale o bookmarklet “Adicionar ao Clipperz”: ele vai tornar o processo de criar cartões mais fácil e divertido.</p> <p> </p> <p>Depois, apenas click no botão <b>Adicionar novo cartão</b> e aproveite sua conta Clipperz.</p> <p> </p> <a href=\"http://www.clipperz.com/support/user_guide/managing_cards\" target=\"_blank\">Saiba mais sobre criar e gerenciar cartões</a> ",
+'newRecordWizardTitleBox': "<h5>Por favor selecione um template</h5> <p>Cartões são formulários simples e flexíveis onde você pode arquivar suas senhas ou outras informações confidenciais.</p> <p>Comece escolhendo um dos templates abaixo. Você poderá customizar seus cartões mais tarde, adicionando e removendo campos.</p> ",
+'newRecordWizardBookmarkletConfigurationTitle': "Login direto",
+'newRecordWizardBookmarkletConfigurationDescription': "<p>Coloque abaixo o código de configuração gerado pelo bookmarklet Clipperz.</p> <p>Um novo cartão completo com login direto para sua conta web será criado.</p> ",
+'newRecordWizardCreateButtonLabel': "Criar",
+'newRecordWizardCancelButtonLabel': "Cancelar",
+'donateSplashPanelTitle': "Apoie Clipperz, faça uma doação hoje!",
+'donateSplashPanelDescription': "<p>Algumas boas razões para doar:</p> <ul> <li> <p>apoie o desenvolvimento de novas funcionalidades</p> </li> <li> <p>mantenha Clipperz gratuito</p> </li> <li> <p>mostrar apreciação por trabalho duro</p> </li> </ul> <p>Para qualquer informação adicional, por favor visite nossa <a href=\"http://www.clipperz.com/donations\" target=\"_blank\">página de Doações</a>.</p> <p> <b>Pronto para doar?</b> </p> ",
+'donateCloseButtonLabel': "Não ainda",
+'donateDonateButtonLabel': "Sim",
+'recordTemplates': {
+ 'WebAccount': {
+ 'title': "Senha web",
+ 'description': "<p>Um cartão simples para arquivar credenciais de login para seus serviços online.</p> ",
+ 'fields': {
+ 'URL': "Endereço web",
+ 'TXT': "Nome de usuário ou email",
+ 'PWD': "Senha"
+ }
+ },
+ 'BankAccount': {
+ 'title': "Conta bancária",
+ 'description': "<p>Arquive com segurança o número de sua conta corrente e suas credenciais de online banking.</p> ",
+ 'fields': {
+ 'TXT': "Banco",
+ 'TXT': "Número da conta",
+ 'URL': "Website do banco",
+ 'TXT': "ID de online banking",
+ 'PWD': "Senha de online banking"
+ }
+ },
+ 'CreditCard': {
+ 'title': "Cartão de crédito",
+ 'description': "<p>Número do cartão, validade, CVV2 e PIN sempre disponíveis no Clipperz</p> ",
+ 'fields': {
+ 'TXT': "Tipo (Visa, AmEx, ...)",
+ 'TXT': "Número",
+ 'TXT': "Nome do proprietário",
+ 'TXT': "Prazo de validade",
+ 'TXT': "CVV2",
+ 'PWD': "PIN",
+ 'URL': "Website do cartão",
+ 'TXT': "Nome do usuário",
+ 'PWD': "Senha"
+ }
+ },
+ 'AddressBookEntry': {
+ 'title': "Agenda de endereços",
+ 'description': "<p>Clipperz pode também funcionar como sua agenda de endereços particular. Use esse template para facilmente adicionar novas entradas.</p> ",
+ 'fields': {
+ 'TXT': "Nome",
+ 'TXT': "Email",
+ 'TXT': "Fone",
+ 'TXT': "Mobile",
+ 'ADDR': "Endereço"
+ }
+ },
+ 'Custom': {
+ 'title': "Cartão customizado",
+ 'description': "<p>Não importa o tipo de informação confidencial você precisa proteger, crie um cartão customizado para sua necessidade.</p> ",
+ 'fields': {
+ 'TXT': "Label 1",
+ 'TXT': "Label 2",
+ 'TXT': "Label 3"
+ }
+ }
+},
+'recordFieldTypologies': {
+ 'TXT': {
+ 'description': "simple text field",
+ 'shortDescription': "texto"
+ },
+ 'PWD': {
+ 'description': "simple text field, with default status set to hidden",
+ 'shortDescription': "senha"
+ },
+ 'URL': {
+ 'description': "simple text field in edit mode, that became an active url in view mode",
+ 'shortDescription': "endereço web"
+ },
+ 'DATE': {
+ 'description': "a value set with a calendar helper",
+ 'shortDescription': "data"
+ },
+ 'ADDR': {
+ 'description': "just like the URL, but the active link points to Google Maps (or similar service) passing the address value as argument",
+ 'shortDescription': "endereço"
+ },
+ 'CHECK': {
+ 'description': "check description",
+ 'shortDescription': "check"
+ },
+ 'RADIO': {
+ 'description': "radio description",
+ 'shortDescription': "radio"
+ },
+ 'SELECT': {
+ 'description': "select description",
+ 'shortDescription': "select"
+ }
+},
+'newRecordPanelGeneralExceptionTitle': "Erro",
+'newRecordPanelGeneralExceptionMessage': "O texto de configuração não é válido. Certifique-se do texto no pop-up de bookmarklet e tente novamente.",
+'newRecordPanelWrongBookmarkletVersionExceptionTitle': "Erro",
+'newRecordPanelWrongBookmarkletVersionExceptionMessage': "O texto de configuração foi gerado por uma velha versão de bookmarklet. Por favor, atualize seus preferidos e tente novamente.",
+'newRecordPanelExceptionPanelCloseButtonLabel': "Cancelar",
+'mainPanelDeletingRecordPanelConfirmationTitle': "Apagando o cartão selecionado",
+'mainPanelDeleteRecordPanelConfirmationText': "Você quer mesmo apagar o cartão selecionado?",
+'mainPanelDeleteRecordPanelConfirmButtonLabel': "Sim",
+'mainPanelDeleteRecordPanelDenyButtonLabel': "Não",
+'mainPanelDeletingRecordPanelInitialTitle': "Apagando o cartão selecionado",
+'mainPanelDeletingRecordPanelCompletedText': "Concluído",
+'deleteRecordPanelCollectRecordDataMessageTitle': "Apagar cartão",
+'deleteRecordPanelCollectRecordDataMessageText': "Atualizando lista de cartões",
+'deleteRecordPanelEncryptUserDataMessageTitle': "Apagar cartão",
+'deleteRecordPanelEncryptUserDataMessageText': "Codificação local de cabeçalhos de cartão",
+'deleteRecordPanelSendingDataToTheServerMessageTitle': "Apagar cartão",
+'deleteRecordPanelSendingDataToTheServerMessageText': "Enviando os cabeçalhos de cartão codificados para Clipperz",
+'deleteRecordPanelUpdatingTheInterfaceMessageTitle': "Apagar cartão",
+'deleteRecordPanelUpdatingTheInterfaceMessageText': "Atualizando a interface",
+'recordDetailNoRecordSelectedTitle': "Nenhum cartão selecionado",
+'recordDetailNoRecordSelectedDescription': "<p>Por favor selecione um cartão da lista na esquerda.</p> ",
+'recordDetailLoadingRecordMessage': "Baixando cartão codificados do Clipperz",
+'recordDetailDecryptingRecordMessage': "Descrição local dos dados do cartão",
+'recordDetailLoadingRecordVersionMessage': "Baixando a versão mais recente do cartão",
+'recordDetailDecryptingRecordVersionMessage': "Descrição local da versão mais recente",
+'recordDetailLoadingErrorMessageTitle': "Erro enquanto baixando o cartão",
+'recordDetailNotesLabel': "Notas",
+'recordDetailLabelFieldColumnLabel': "Legenda do campo",
+'recordDetailDataFieldColumnLabel': "Dados do campo",
+'recordDetailTypeFieldColumnLabel': "Tipo",
+'recordDetailSavingChangesMessagePanelInitialTitle': "Salvando cartão",
+'recordDetailAddFieldButtonLabel': "Adicionar novo campo",
+'recordDetailPasswordFieldHelpLabel': "para copiar a senha para o clipboard clique nas estrelas e em seguida Ctrl-C",
+'recordDetailPasswordFieldScrambleLabel': "misturar",
+'recordDetailPasswordFieldUnscrambleLabel': "mostrar",
+'recordDetailDirectLoginBlockTitle': "Logins diretos",
+'recordDetailNewDirectLoginDescription': "<p>Configuração de login direto</p> ",
+'recordDetailDirectLoginBlockNoDirectLoginConfiguredDescriptionConfig': "<p>Este cartão contém credenciais para acessar um serviço online?</p> <p>Use o bookmarklet para configurar um “login direto” desde o Clipperz com apenas um click!</p> ",
+'recordDetailAddNewDirectLoginButtonLabel': "Adicionar novo login direto",
+'recordDetailEditButtonLabel': "Editar",
+'recordDetailSaveButtonLabel': "Salvar",
+'recordDetailCancelButtonLabel': "Cancelar",
+'newRecordTitleLabel': "_novo cartão_",
+'recordSaveChangesPanelCollectRecordInfoMessageTitle': "Salvar cartão",
+'recordSaveChangesPanelCollectRecordInfoMessageText': "Subindo cabeçalhos de cartão",
+'recordSaveChangesPanelEncryptUserDataMessageTitle': "Salvar cartão",
+'recordSaveChangesPanelEncryptUserDataMessageText': "Codificação local do cabeçalho do cartão",
+'recordSaveChangesPanelEncryptRecordDataMessageTitle': "Salvar cartão",
+'recordSaveChangesPanelEncryptRecordDataMessageText': "Codificação local da informação do cartão",
+'recordSaveChangesPanelEncryptRecordVersionDataMessageTitle': "Salvar cartão",
+'recordSaveChangesPanelEncryptRecordVersionDataMessageText': "Codificação local da informação de versão do cartão",
+'recordSaveChangesPanelSendingDataToTheServerMessageTitle': "Salvar cartão",
+'recordSaveChangesPanelSendingDataToTheServerMessageText': "Subindo o cabeçalho do cartão codificado para Clipperz",
+'recordSaveChangesPanelUpdatingTheInterfaceMessageTitle': "Salvar cartão",
+'recordSaveChangesPanelUpdatingTheInterfaceMessageText': "Atualizando a interface",
+'passwordGeneratorPanelTitle': "Gerador de senhas",
+'passwordGeneratorPanelOkLabel': "Ok",
+'passwordGeneratorPanelCancelLabel': "Cancelar",
+'passwordGeneratorLengthLabel': "compr.:",
+//'DWRUtilLoadingMessage': "Carregando ...",
+'comingSoon': "em breve ...",
+'panelCollectingEntryopyMessageText': "Coletando entropia",
+'directLoginConfigurationCheckBoxFieldSelectedValue': "Sim",
+'directLoginConfigurationCheckBoxFieldNotSelectedValue': "Não",
+'WELCOME_BACK': "Welcome back!",
+'currentConnectionText': "Você está conectado do ip&nbsp;__ip__, aparentemente desde __country__, usando __browser__ num __operatingSystem__.",
+'latestConnectionText': "Sua úlitima conexão foi __elapsedTimeDescription__ (__time__) do ip&nbsp;__ip__, aparentemente desde __country__, usando __browser__ num __operatingSystem__.",
+'fullLoginHistoryLinkLabel': "mostrar o histórico de logins completos",
+'elapsedTimeDescriptions': {
+ 'MORE_THAN_A_MONTH_AGO': "mais de um mês atrás",
+ 'MORE_THAN_A_WEEK_AGO': "mais de uma semana atrás",
+ 'MORE_THAN_*_WEEKS_AGO': "mais de __elapsed__ semanas atrás",
+ 'YESTERDAY': "ontem",
+ '*_DAYS_AGO': "__elapsed__ dias atrás",
+ 'ABOUT_AN_HOUR_AGO': "cerca de uma hora atrás",
+ '*_HOURS_AGO': "__elapsed__ horas atrás",
+ 'JUST_A_FEW_MINUTES_AGO': "apenas alguns minutos atrás",
+ 'ABOUT_*_MINUTES_AGO': "cerca de __elapsed__ minutos atrás"
+},
+'unknown_ip': "desconhecido",
+'calendarStrings': {
+ 'months': {
+ '0': "Janeiro",
+ '1': "Fevereiro",
+ '2': "Março",
+ '3': "Abril",
+ '4': "Maio",
+ '5': "Junho",
+ '6': "Julho",
+ '7': "Agosto",
+ '8': "Setembro",
+ '9': "Outubro",
+ '10': "Novembro",
+ '11': "Dezembro"
+ },
+ 'shortMonths': {
+ '0': "Jan",
+ '1': "Fev",
+ '2': "Mar",
+ '3': "Abr",
+ '4': "Mai",
+ '5': "Jun",
+ '6': "Jul",
+ '7': "Ago",
+ '8': "Set",
+ '9': "Out",
+ '10': "Nov",
+ '11': "Dez"
+ },
+ 'days': {
+ '0': "Domingo",
+ '1': "Segunda-feira",
+ '2': "Terça-feira",
+ '3': "Quarta-feira",
+ '4': "Quinta-feira",
+ '5': "Sexta-feira",
+ '6': "Sábado"
+ },
+ 'shortDays': {
+ '0': "Dom",
+ '1': "Seg",
+ '2': "Ter",
+ '3': "Qua",
+ '4': "Quin",
+ '5': "Sex",
+ '6': "Sab"
+ },
+ 'veryShortDays': {
+ '0': "Do",
+ '1': "Se",
+ '2': "Te",
+ '3': "Qa",
+ '4': "Qi",
+ '5': "Se",
+ '6': "Sa"
+ },
+ 'amDesignation': "am",
+ 'pmDesignation': "pm"
+},
+
+__syntaxFix__: "syntax fix"
+});
diff --git a/frontend/beta/js/Clipperz/PM/Strings/Strings_pt-PT.js b/frontend/beta/js/Clipperz/PM/Strings/Strings_pt-PT.js
new file mode 100644
index 0000000..5284683
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Strings/Strings_pt-PT.js
@@ -0,0 +1,42 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+//=============================================================================
+//
+// P O R T U G U Ê S ( pt_PT )
+//
+//=============================================================================
+
+Clipperz.PM.Strings.Languages['pt-pt'] = MochiKit.Base.merge(Clipperz.PM.Strings.Languages['pt-br'], {
+
+
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+});
+
diff --git a/frontend/beta/js/Clipperz/PM/Strings/Strings_ru-RU.js b/frontend/beta/js/Clipperz/PM/Strings/Strings_ru-RU.js
new file mode 100644
index 0000000..41c904f
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Strings/Strings_ru-RU.js
@@ -0,0 +1,440 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+Clipperz.PM.Strings.Languages['ru-RU'.toLowerCase()] = MochiKit.Base.merge(Clipperz.PM.Strings.Languages['en-us'], {
+'clipperzServiceDescription': "<h2>Держи при себе!</h2> <ul> <li> <h3>Clipperz - это:</h3> <ul> <li> <p>безопасный и простой менеджер паролей</p> </li> <li> <p>эффективное решение для единой регистрации</p> </li> <li> <p>цифровое хранилище Ваших конфидециальных данных</p> </li> </ul> </li> <li>
+ <h3>C помошью Clipperz Вы можете:</h3> <ul>
+ <li> <p>хранить и управлять Вашими паролями</p> </li> <li> <p>входить в любые веб-сервисы без ввода логина и пароля</p> </li> <li> <p>защитить все важные данные: коды охранной сигнализации, ПИНы, номера кредитных кард, ...</p> </li> <li> <p>открыть доступ Вашим членам семьи, друзьям, коллегам</p> </li> </ul> </li> <li>
+ <h3>Преимущества Clipperz:</h3> <ul>
+ <li> <p>бесплатный и абсолютно анонимный</p> </li> <li> <p>доступен в любое время и с любого компьютера</p> </li> <li> <p>не нужно ничего устанавливать</p> </li> <li> <p>не надо хранить секреты на компьютере или бумаге</p> </li> </ul> </li> <li>
+ <h3>Безопасность Clipperz:</h3> <ul>
+ <li> <p>все данные перед отправкой в Clipperz шифруются в браузере</p> </li> <li> <p>секретный ключ - это фраза, которую знаете только Вы</p> </li> <li> <p>Clipperz управляет важными данными в зашифрованном виде и никогда не получит доступ к ним в открытом виде</p> </li> <li> <p>Clipperz основан на стандартных криптографических протоколах: без каких-либо самоделок</p> </li> <li> <p>Вы можете просмотреть исходный код, но Вам ничего не надо знать о криптографии, чтобы быть просто пользоваться</p> </li> </ul> </li> <li>
+ <a href=\"http://www.clipperz.com\" target=\"_blank\">Подробнее</a> </li> </ul> ",
+'loginFormTitle': "войти под Вашим аккаунтом Clipperz",
+'loginFormUsernameLabel': "имя пользователя",
+'loginFormPassphraseLabel': "ключевая фраза",
+'loginFormDontHaveAnAccountLabel': "у вас еще нет аккаунта?",
+'loginFormCreateOneLabel': "создать",
+'loginFormForgotYourCredentialsLabel': "забыли пароль?",
+'loginFormAarghThatsBadLabel': "о! это плохо!",
+'loginFormAfraidOfMaliciousScriptsLabel': "опасаетесь вредоносных скриптов?",
+'loginFormVerifyTheCodeLabel': "проверить код",
+'loginFormButtonLabel': "Войти",
+'loginFormOneTimePasswordCheckboxLabel': "использовать одноразовую ключевую фразу",
+'loginPanelSwithLanguageDescription': "<h5>Переключиться на Ваш язык</h5> ",
+'browserCompatibilityDescription': "<p>Лучше работать с Clipperz в Firefox. Однако Clipperz хорошо совместим с Opera и MS Internet Explorer!</p> ",
+'OTPloginMessagePanelInitialTitle': "Вход",
+'OTPloginMessagePanelInitialText': "Передача данных учетной записи ...",
+'OTPloginMessagePanelLoadingTitle': "Вход",
+'OTPloginMessagePanelLoadingText': "Запрос аутентификационных данных с сервера ...",
+'OTPloginMessagePanelProcessingTitle': "Вход",
+'OTPloginMessagePanelProcessingText': "Расшифровка аутентификационных данных",
+'loginMessagePanelInitialTitle': "Вход ...",
+'loginMessagePanelInitialButtonLabel': "Отмена",
+'loginMessagePanelConnectedTitle': "Соединен",
+'loginMessagePanelConnectedText': "Выполнен",
+'loginMessagePanelFailureTitle': "Ошибка",
+'loginMessagePanelFailureText': "Ошибка при попытке входа",
+'loginMessagePanelFailureButtonLabel': "Закрыть",
+'connectionLoginSendingCredentialsMessageTitle': "Проверка учетной записи",
+'connectionLoginSendingCredentialsMessageText': "Передача данных ...",
+'connectionLoginCredentialsVerificationMessageTitle': "Проверка учетной записи",
+'connectionLoginCredentialsVerificationMessageText': "Выполняем SRP-аутентификацию ...",
+'connectionLoginDoneMessageTitle': "Проверка учетной записи",
+'connectionLoginDoneMessageText': "Соединено",
+'userLoginPanelUpgradingUserCredentialsMessageTitle': "Проверка учетной записи",
+'userLoginPanelUpgradingUserCredentialsMessageText': "Обновляем полномочия к новой схеме аутентификации",
+'userLoginPanelConnectedMessageTitle': "Пользователь аутентифицирован",
+'userLoginPanelConnectedMessageText': "Успешный вход",
+'userLoginPanelTryingAnOlderConnectionSchemaMessageTitle': "Проверка учетной записи",
+'userLoginPanelTryingAnOlderConnectionSchemaMessageText': "Пробуем войти по старой схеме",
+'userLoginPanelLoadingUserDataMessageTitle': "Пользователь аутентифицирован",
+'userLoginPanelLoadingUserDataMessageText': "Загрузка зашифрованных заголовков карточек",
+'userLoginPanelDecryptingUserDataMessageTitle': "Пользователь аутентифицирован",
+'userLoginPanelDecryptingUserDataMessageText': "Расшифровка заголовков карточек",
+'userLoginPanelDecryptingUserStatisticsMessageTitle': "Пользователь аутентифицирован",
+'userLoginPanelDecryptingUserStatisticsMessageText': "Расшифровка статистики",
+'splashAlertTitle': "Добро пожаловать в Clipperz!",
+'splashAlertText': "<p>Несколько советов по безопасности:</p> <ul> <li> <p>Хранение данных в Clipperz зависит от того, насколько безопасна выбранная Вами ключевая фраза</p> </li> <li> <p>Если собираетесь использовать Clipperz для защиты важных или критических данных, то убедитесь, что выбрали сложный пароль</p> </li> <li> <p>Clipperz не может восстановить забытую ключевую фразу</p> </li> </ul> <p>За дополнительной информацией обратитесь на <a href=\"http://www.clipperz.com\" target=\"_blank\">сайт</a> Clipperz.</p> ",
+'splashAlertCloseButtonLabel': "OK",
+'registrationFormTitle': "создать аккаунт",
+'registrationFormUsernameLabel': "имя пользователя",
+'registrationFormPassphraseLabel': "ключевая фраза",
+'registrationFormRetypePassphraseLabel': "повторите ключевую фразу",
+'registrationFormSafetyCheckLabel': "Я понимаю, что Clipperz не может восстановить забытую ключевую фразу",
+'registrationFormTermsOfServiceCheckLabel': "Я прочитал и согласен с <a href='http://www.clipperz.com/terms_of_service' target='_blank'>Условиями предоставления услуг</a>.",
+'registrationFormDoYouAlreadyHaveAnAccountLabel': "у вас уже есть аккаунт?",
+'registrationFormSimplyLoginLabel': "просто ввойдите",
+'registrationFormButtonLabel': "Зарегистрировать",
+'registrationFormWarningMessageNotMatchingPassphrases': "Ключевые фразы не совпадают, пожайлуста, повторите ввод",
+'registrationFormWarningMessageSafetyCheckNotSelected': "Прочитайте и проверьте все поля ниже",
+'registrationFormWarningMessageTermsOfServiceCheckNotSelected': "Вы должны принять Условия предоставления услуг",
+'registrationMessagePanelInitialTitle': "Создание аккаунта",
+'registrationMessagePanelInitialButtonLabel': "Отмена",
+'registrationMessagePanelRegistrationDoneTitle': "Регистрация",
+'registrationMessagePanelRegistrationDoneText': "Выполнено",
+'registrationMessagePanelFailureTitle': "Ошибка регистрации",
+'registrationMessagePanelFailureButtonLabel': "Закрыть",
+'connectionRegistrationSendingRequestMessageText': "Проверка учетной записи",
+'connectionRegistrationSendingCredentialsMessageText': "Передача данных",
+'registrationSplashPanelTitle': "Совет",
+'registrationSplashPanelDescription': "<p>Это Ваши данные учетной записи, позаботесь об их безопасности. Clipperz никогда больше не покажет Ваше имя пользователя и ключевую фразу!</p> ",
+'registrationSplashPanelUsernameLabel': "имя пользователя",
+'registrationSplashPanelPassphraseLabel': "ключевая фраза",
+'registrationSplashPanelShowPassphraseButtonLabel': "показать ключевую фразу",
+'donateHeaderLinkLabel': "пожертвования",
+'creditsHeaderLinkLabel': "список разработчиков",
+'feedbackHeaderLinkLabel': "обратная связь",
+'helpHeaderLinkLabel': "помощь",
+'forumHeaderLinkLabel': "форум",
+'recordMenuLabel': "карточки",
+'accountMenuLabel': "аккаунт",
+'dataMenuLabel': "данные",
+'contactsMenuLabel': "контакты",
+'toolsMenuLabel': "инструменты",
+'logoutMenuLabel': "выйти",
+'lockMenuLabel': "заблокировать",
+'lockTitle': "Аккаунт заблокирован",
+'lockDescription': "<p>Введите ключевую фразу для разблокировки</p> ",
+'unlockButtonLabel': "разблокировать",
+'changePasswordTabLabel': "Изменить ключевую фразу",
+'changePasswordTabTitle': "Изменить ключевую фразу",
+'changePasswordFormUsernameLabel': "имя пользователя",
+'changePasswordFormOldPassphraseLabel': "старая ключевая фраза",
+'changePasswordFormNewPassphraseLabel': "новая ключевая фраза",
+'changePasswordFormRetypePassphraseLabel': "повторить ключевую фразу",
+'changePasswordFormSafetyCheckboxLabel': "Я понимаю, что Clipperz не может восстановить забытую ключевую фразу.",
+'changePasswordFormSubmitLabel': "Изменить",
+'changePasswordFormWrongUsernameWarning': "Неправильное имя пользователя",
+'changePasswordFormWrongPassphraseWarning': "Неверная ключевая фраза",
+'changePasswordFormWrongRetypePassphraseWarning': "Ключевые фразы не совпадают, пожайлуста, повторите ввод.",
+'changePasswordFormSafetyCheckWarning': "Прочитайте и проверьте все поля ниже.",
+'changePasswordFormProgressDialogTitle': "Изменение учетной записи",
+'changePasswordFormProgressDialogConnectedMessageTitle': "Соединено",
+'changePasswordFormProgressDialogConnectedMessageText': "Выполнено",
+'changePasswordFormProgressDialogErrorMessageTitle': "Ошибка",
+'changePasswordFormProgressDialogErrorMessageText': "Ошибка изменения учетной записи!",
+'changeCredentialsPanelEncryptingDataMessageTitle': "Изменение ключевой фразы",
+'changeCredentialsPanelEncryptingDataMessageText': "Шифрование заголовков карточек",
+'changeCredentialsPanelCreatingNewCredentialsMessageTitle': "Изменение ключевой фразы",
+'changeCredentialsPanelCreatingNewCredentialsMessageText': "Обновление учетной записи",
+'changeCredentialsPanelSendingNewCredentialsToTheServerMessageTitle': "Изменение ключевой фразы",
+'changeCredentialsPanelSendingNewCredentialsToTheServerMessageText': "Загрузка данных учетной записи в Clipperz",
+'changeCredentialsPanelDoneMessageTitle': "Изменение ключевой фразы",
+'changeCredentialsPanelDoneMessageText': "Выполнено",
+'manageOTPTabLabel': "Управление одноразовыми ключевыми фразами",
+'manageOTPTabTitle': "Управление одноразовыми ключевыми фразами",
+'manageOTPTabDescription': "<p>Одноразовый пароль работает, как Ваша обычная ключевая фраза, но может быть использована только один раз.</p> <p>Если один и тот же пароль будет использоваться снова на следующих этапах, она будет отклонен и процедура входа завершится неудачно.</p> <p>Сразу после входа одноразовый пароль будет удален, чтобы предовратить любую несанкционированную попытку доступа.</p> <p>Одноразовые пароли - удачный выбор для тех, кто обеспокоен кейлоггерами или spyware, которые могут собирать информ.</p> <p> <b>Строго рекомендуется использовать одноразовые пароли для доступа к Clipperz с чужих компьютеров, из интернет-кафе и библиотек.</b> </p> ",
+'oneTimePasswordReadOnlyMessage': "<h6>Извините!</h6> <p>Вы не можете управлять одноразовыми ключевыми фразами в оффлайновой версии Clipperz.</p> ",
+'oneTimePasswordLoadingMessage': "<h6>Загрузка данных</h6> <p>Подождите, пожайлуста ...</p> ",
+'oneTimePasswordNoPasswordAvailable': "<h6>Нет свободных для использования одноразовых ключевых фраз.</h6> <p>Нажмите кнопку “Новая”, чтобы добавить еще одноразовые ключевые фразы в аккаунт.</p> ",
+'createNewOTPButtonLabel': "новая",
+'deleteOTPButtonLabel': "удалить",
+'printOTPButtonLabel': "печать",
+'disabledOneTimePassword_warning': "запрещено",
+'oneTimePasswordSelectionLink_selectLabel': "Выбрать:",
+'oneTimePasswordSelectionLink_all': "все",
+'oneTimePasswordSelectionLink_none': "ни одного",
+'oneTimePasswordSelectionLink_used': "использованные",
+'oneTimePasswordSelectionLink_unused': "неиспользованные",
+'saveOTP_encryptUserDataTitle': "Сохранение одноразовых ключевых фраз",
+'saveOTP_encryptUserDataText': "Обработка новых данных учетной записи ...",
+'saveOTP_encryptOTPDataTitle': "одноразовыми ключевыми фразами",
+'saveOTP_encryptOTPDataText': "Шифрование аутентификационных данных ...",
+'saveOTP_sendingDataTitle': "одноразовыми ключевыми фразами",
+'saveOTP_sendingDataText': "Передача аутентификационных данных на сервер ...",
+'saveOTP_updatingInterfaceTitle': "одноразовыми ключевыми фразами",
+'saveOTP_updatingInterfaceText': "Обновление интерфейса ...",
+'accountPreferencesLabel': "Настройки",
+'accountPreferencesTabTitle': "Настройки",
+'accountPreferencesLanguageTitle': "Выбор языка",
+'accountPreferencesLanguageDescription': "<p>Выберите Ваш язык из списка.</p> ",
+'showDonationReminderPanelTitle': "Напоминания о пожертвованиях",
+'showDonationReminderPanelDescription': "<p>Показать напоминания о пожертвованиях</p> ",
+'saveUserPreferencesFormSubmitLabel': "Сохранить",
+'cancelUserPreferencesFormSubmitLabel': "Отмена",
+'accountPreferencesSavingPanelTitle_Step1': "Сохранение настроек",
+'accountPreferencesSavingPanelText_Step1': "Шифрование настроек",
+'accountPreferencesSavingPanelTitle_Step2': "Сохранение настроек",
+'accountPreferencesSavingPanelText_Step2': "Передача зашифрованных настроек в Clipperz",
+'accountLoginHistoryLabel': "История входов",
+'loginHistoryTabTitle': "История входов",
+'loginHistoryReadOnlyMessage': "<h6>Извините!</h6> <p>История входов не доступна в оффлайновой версии Clipperz.</p> ",
+'loginHistoryLoadingMessage': "<h6>Загрузка данных</h6> <p>Подождите, пожайлуста ...</p> ",
+'loginHistoryLoadedMessage': "<h6>Десять Ваших последних входов</h6> <p> </p> ",
+'loginHistoryIPLabel': "IP",
+'loginHistoryTimeLabel': "дата",
+'loginHistoryCurrentSessionText': "текущая сессия",
+'loginHistoryReloadButtonLabel': "Обновить историю",
+'deleteAccountTabLabel': "Удалить аккаунт",
+'deleteAccountTabTitle': "Удалить аккаунт",
+'deleteAccountFormUsernameLabel': "имя пользователя",
+'deleteAccountFormPassphraseLabel': "ключевая фраза",
+'deleteAccountFormSafetyCheckboxLabel': "Я понимаю, что все мои данные будут удалены и это действие необратимо.",
+'deleteAccountFormSubmitLabel': "Удалить мой аккаунт",
+'deleteAccountFormWrongUsernameWarning': "Неверное имя пользователя",
+'deleteAccountFormWrongPassphraseWarning': "Неверная ключевая фраза",
+'deleteAccountFormSafetyCheckWarning': "Прочтите и отметьте все поля ниже.",
+'accountPanelDeletingAccountPanelConfirmationTitle': "ВНИМАНИЕ",
+'accountPanelDeleteAccountPanelConfirmationText': "Вы уверены, что хотите удалить аккаунт?",
+'accountPanelDeleteAccountPanelConfirmButtonLabel': "Да",
+'accountPanelDeleteAccountPanelDenyButtonLabel': "Нет",
+'offlineCopyTabLabel': "Оффлайновая копия",
+'offlineCopyTabTitle': "Оффлайновая копия",
+'offlineCopyTabDescription': "<p>Одним кликом Вы можете сохранить все зашифрованные данные с серверов Clipperz на жесткий диск и создать оффлайновую версию, которую будете использовать при отсутствии подключения к Интернету.</p> <p>Версия только для чтения безопасна также, как и полная, и не подвергает Ваши данные большим рискам, так как использует тот же код и архитектуру.</p> <ol> <li> <p>Нажмите на ссылку, чтобы начать скачивание.</p> </li> <li> <p>Браузер спросит, что сделать с файлом “Clipperz_YYYYMMDD.html”. Сохраните его на Ваш жесткий диск.</p> </li> <li> <p>Double click on the downloaded file to launch the offline version in your browser.</p> </li> <li> <p>Как обычно, введите имя пользователя и ключевую фразу.</p> </li> </ol> ",
+'offlineCopyDownloadLinkLabel': "Скачать",
+'offlineCopyDownloadWarning': "<h4> <a href=\"#\" id=\"offlineCopyDownloadWarningLink\">Обновите Вашу “оффлайновую копию”!</a> </h4> <p>Вы недавно создали или изменили одну или более карточек: было бы разумным скачать новую оффлайновую копию.</p> ",
+'sharingTabLabel': "Совместное использование",
+'sharingTabTitle': "Совместное использование",
+'sharingTabDescription': "<p>Достаточно часто конфидециальную информацию нужно открыть одному или нескольким людям.</p> <p>Это может быть просто, как дать коллеге ключ доступа к Вашей голосовой почте, когда Вас нет в офисе, или сложно, как открыть доступ наследникам к Вашему счету в местном банке, когда Вы скончаетесь.</p> <p>Clipperz поможет сделать совместное использование Ваших секретов безопасным и простым процессом.</p> <p> </p> <p> <b>Скоро ...</b> </p> ",
+'importTabLabel': "Импорт",
+'importTabTitle': "Импорт",
+'importTabDescription': "<p> <b>Скоро ...</b> </p> ",
+'printingTabLabel': "Экспорт",
+'printingTabTitle': "Экспорт",
+'printingTabDescription': "<p> <b>Печать Ваших данных</b> </p> <p>Нажмите по ссылке, чтобы открыть новое окно со всеми Вашими карточками для печати.</p> <p>Если вы собираетесь распечатать в резервных целях, пожайлуста, рассмотрите более безопасный вариант, как создание “оффлайновой копии”.</p> ",
+'printingLinkLabel': "Версия для печати",
+'contactsTabLabel': "Контакты",
+'contactsTabTitle': "Контакты",
+'passwordGeneratorTabLabel': "Генератор паролей",
+'passwordGeneratorTabTitle': "Генератор паролей",
+'passwordGeneratorTabButtonLabel': "Генератор паролей",
+'bookmarkletTabLabel': "Закладка",
+'bookmarkletTabTitle': "Закладка",
+'bookmarkletTabDescription': "<p>Закладка - это простой инструмент, который может решать очень полезные задачи. Ее можно сохранить и использовать как обычную веб-страницу.</p> <p>Закладки помогут Вам быстро создать новые карточки и новые логины внутри существующих карточек.</p> <p> <b>Пожайлуста, учтите, что закладки действительно не включают какой-либо информации, связанной с аккаунтом (например, имя или ключевая фраза), закладки содержат один и тот же код для каждого пользователя.</b> </p> <h3>Как установить закладку</h3> <h5>Firefox, Camino, Opera, Safari</h5> <ol> <li> <p>Убедитесь, что панель закладок отображается выбором “View > Toolbars > Bookmarks” или похожими пунктами из меню браузера.</p> </li> <li> <p>Нажмите и перетащите ссылку “Добавить в Clipperz” на панель закладок.</p> </li> </ol> <h5>Internet Explorer</h5> <ol> <li> <p>Убедитесь, что отображается панель “Ссылки” выбором “View > Toolbars > Links” из меню браузера.</p> </li> <li> <p>Нажмите правой кнопкой на ссылку “Добавить в Clipperz”.</p> </li> <li> <p>Выберите “Add to favorites” из контекстного меню.</p> </li> <li> <p>Нажмите “Yes” для любых сообщений, которые появятся.</p> </li> <li> <p>Откройте папку “Links” и нажмите “OK”.</p> </li> </ol> ",
+'bookmarkletTabBookmarkletTitle': "Добавить в Clipperz",
+'bookmarkletTabInstructions': "<h3>Как создать новую карточку с ссылками “прямого подключения” в онлайновый сервис</h3> <ol> <li> <p>Откройте веб-страницу с формой входа. (обычно на этой страницы Вы вводите данные вашей учетной записи)</p> </li> <li> <p>Запустите закладку, нажав на нее: появится всплывающее окно.</p> </li> <li> <p>Скопируйте в буфер обмена содержимое текстового поля из всплывающего окна. (ctrl-C)</p> </li> <li> <p>Ввойдите в Ваш аккаунт и нажмите “Добавить новую карточку”.</p> </li> <li> <p>Выберите шаблон “Прямого подключения” и вставьте в текстовое поле содержимое буфера обмена. (ctrl-V)</p> </li> <li> <p>Нажмите кнопку “Создать”, проверьте правильность и нажмите “Сохранить”.</p> </li> </ol> <h3>Как создать ссылку “Прямого подключения” в существующей карточке</h3> <ol> <li> <p>Тоже самое, как и выше.</p> </li> <li> <p>Тоже самое, как и выше.</p> </li> <li> <p>Тоже самое, как и выше.</p> </li> <li> <p>Ввойдите в Ваш аккаунт и выберите карточку с данными учетной записи для только что посещенного веб-сервиса и нажмите “Редактировать”.</p> </li> <li> <p>Вставьте содержимое буфера обмена в текстовое поле в разделе “Прямого подключения”. (ctrl-V)</p> </li> <li> <p>Нажмите “Добавить новое прямое подключение”, проверьте правильность и нажмите “Сохранить”.</p> </li> </ol> <p> </p> <p>Подробнее о закладках <a href=\"http://www.clipperz.com/support/user_guide/bookmarklet\" target=\"_blank\">здесь</a>.</p> ",
+'mainPanelDirectLoginBlockLabel': "Прямые подключения",
+'directLinkReferenceShowButtonLabel': "показать",
+'mainPanelDirectLoginBlockDescription': "<p>Добавьте “Прямые подключения”, чтобы срау входить в веб-сервисы без ввода имени и пароля!</p> <p>“Прямые подключения” значительно усиливают безопасность, так как:</p> <ul> <li> <p>удобно принимать и вводить сложные пароли;</p> </li> <li> <p>никогда не надо использовать простой и один и тот же пароль.</p> </li> </ul> <p>Простая и быстрая конфигурация с помощью закладок.</p> <a href=\"http://www.clipperz.com/support/user_guide/direct_logins\" target=\"_blank\">Подробнее о прямых подключениях</a> ",
+'mainPanelRecordsBlockLabel': "Карточки",
+'mainPanelAddRecordButtonLabel': "Добавить новую карточку",
+'mainPanelRemoveRecordButtonLabel': "Удалить карточку",
+'mainPanelRecordFilterBlockAllLabel': "все",
+'mainPanelRecordFilterBlockTagsLabel': "теги",
+'mainPanelRecordFilterBlockSearchLabel': "поиск",
+'recordDetailNoRecordAtAllTitle': "Добро пожаловать в Clipperz!",
+'recordDetailNoRecordAtAllDescription': "<h5>Начните, добавив карточку.</h5> <p>Карточки - это простой и гибкий инструмент, с помощью которого Вы можете хранить пароли и любую другую информацию.</p> <p>Карточки могут содержать учетные записи для доступа к веб-сайтам, код для замка от велосипеда, данные кредитной карточки, ...</p> <h5>Не забывай о закладках!</h5> <p>Перед началом работы установите закладку “Добавить в Clipperz”: создание карточек будет простым и забавным.</p> <p>Перейдите на панель закладок, чтобы изучить, как установить и использовать их.</p> <p> </p> <a href=\"http://www.clipperz.com/support/user_guide/managing_cards\" target=\"_blank\">Подробнее об создании и управлениями закладками</a> ",
+'newRecordWizardTitleBox': "<h5>Пожайлуста, выберите шаблон</h5> <p>Карточки - это простой и гибкий инструмент, с помощью которого Вы можете хранить пароли и любую другую информацию.</p> <p>Выберите один из шаблонов. Вы всегда сможете настроить ваши карточки, добавляя или удаляя поля.</p> ",
+'newRecordWizardBookmarkletConfigurationTitle': "Прямое подключение",
+'newRecordWizardBookmarkletConfigurationDescription': "<p>Вставьте конфигурационный код, сгенерированный с помощью закладки</p> <p>Будет создана новая карточка с поддержкой прямого подключения.</p> ",
+'newRecordWizardCreateButtonLabel': "Создать",
+'newRecordWizardCancelButtonLabel': "Отмена",
+'donateSplashPanelTitle': "Поддержите Clipperz, сделайте пожертвование сегодня!",
+'donateSplashPanelDescription': "<p>Несколько причин сделать пожертвование:</p> <ul> <li> <p>поддержка развития новых функций</p> </li> <li> <p>оставить Clipperz бесплатным</p> </li> <li> <p>показать признательность нашей упорной работе</p> </li> </ul> <p>Для дополнительной информации посетите нашу <a href=\"http://www.clipperz.com/donations\" target=\"_blank\">страницу пожертвований</a>.</p> <p> <b>Готовы пожертвовать?</b> </p> ",
+'donateCloseButtonLabel': "Еще нет",
+'donateDonateButtonLabel': "Да",
+ 'recordTemplates': {
+ 'WebAccount': {
+ 'title': "Интернет Пароль",
+ 'description': "Простая форма для хранения учетной записи в онлайновый сервис."
+ },
+ 'BankAccount': {
+ 'title': "Банковский аккаунт",
+ 'description': "Безопасное хранение номера Вашей банковской карты и учетной записи для онлайнового банкинга."
+ },
+ 'CreditCard': {
+ 'title': "Кредитная карта",
+ 'description': "Номер карты, срок действия, CCV2 и ПИН всегда в Ваших руках."
+ },
+ 'AddressBookEntry': {
+ 'title': "Запись адресной книги",
+ 'description': "Clipperz может также работать, как новая частная адресная книга. Используйте этот шаблон, чтобы легко добавить новую запись."
+ },
+ 'Custom': {
+ 'title': "Пользовательская карточка",
+ 'description': "Не важно, какие данные нужно защитить, просто создайте карточку."
+ }
+ },
+ 'recordFieldTypologies': {
+ 'TXT': {
+ 'description': "simple text field",
+ 'shortDescription': "текст"
+ },
+ 'PWD': {
+ 'description': "simple text field, with default status set to hidden",
+ 'shortDescription': "пароль"
+ },
+ 'URL': {
+ 'description': "simple text field in edit mode, that became an active url in view mode",
+ 'shortDescription': "веб-адрес"
+ },
+ 'DATE': {
+ 'description': "a value set with a calendar helper",
+ 'shortDescription': "дата"
+ },
+ 'ADDR': {
+ 'description': "just like the URL, but the active link points to Google Maps (or similar service) passing the address value as argument",
+ 'shortDescription': "почтовый адрес"
+ },
+ 'CHECK': {
+ 'description': "check description",
+ 'shortDescription': "check"
+ },
+ 'RADIO': {
+ 'description': "radio description",
+ 'shortDescription': "radio"
+ },
+ 'SELECT': {
+ 'description': "select description",
+ 'shortDescription': "select"
+ }
+ },
+'newRecordPanelGeneralExceptionTitle': "Ошибка",
+'newRecordPanelGeneralExceptionMessage': "Конфигурационный текст неверен. Убедитесь, что Вы взяли его из окна закладки и попробуйте снова.",
+'newRecordPanelWrongBookmarkletVersionExceptionTitle': "Ошибка",
+'newRecordPanelWrongBookmarkletVersionExceptionMessage': "Конфигурационный текст был сгенерирован с помощью старой весии закладок. Пожайлуста, обновите Вашу закладку и попробуйте снова.",
+'newRecordPanelExceptionPanelCloseButtonLabel': "Отмена",
+'mainPanelDeletingRecordPanelConfirmationTitle': "Удаление выбранной карточки",
+'mainPanelDeleteRecordPanelConfirmationText': "Вы действительно хотите удалить эту карточку?",
+'mainPanelDeleteRecordPanelConfirmButtonLabel': "Ага",
+'mainPanelDeleteRecordPanelDenyButtonLabel': "Не-а",
+'mainPanelDeletingRecordPanelInitialTitle': "Удаление выбранной карточки",
+'mainPanelDeletingRecordPanelCompletedText': "Выполнено",
+'deleteRecordPanelCollectRecordDataMessageTitle': "Удаление карточки",
+'deleteRecordPanelCollectRecordDataMessageText': "Обновление списка карточек",
+'deleteRecordPanelEncryptUserDataMessageTitle': "Удаление карточки",
+'deleteRecordPanelEncryptUserDataMessageText': "Шифрование заголовков карточек",
+'deleteRecordPanelSendingDataToTheServerMessageTitle': "Удаление карточки",
+'deleteRecordPanelSendingDataToTheServerMessageText': "Передача зашифрованных заголовков карчточек в Clipperz",
+'deleteRecordPanelUpdatingTheInterfaceMessageTitle': "Удаление карточки",
+'deleteRecordPanelUpdatingTheInterfaceMessageText': "Обновление интерфейса",
+'recordDetailNoRecordSelectedTitle': "Не выбрана карточка",
+'recordDetailNoRecordSelectedDescription': "<p>Пожайлуста, выберите карточку из списка слева.</p> ",
+'recordDetailLoadingRecordMessage': "Загрузка зашифрованных карточек из Clipperz",
+'recordDetailDecryptingRecordMessage': "Расшифровка данных карточек",
+'recordDetailLoadingRecordVersionMessage': "Загрузка последней версии карточкиn",
+'recordDetailDecryptingRecordVersionMessage': "Расшифровка",
+'recordDetailLoadingErrorMessageTitle': "Ошибка при загрузку",
+'recordDetailNotesLabel': "Примечания",
+'recordDetailLabelFieldColumnLabel': "Метка поля",
+'recordDetailDataFieldColumnLabel': "Данные поля",
+'recordDetailTypeFieldColumnLabel': "Тип",
+'recordDetailSavingChangesMessagePanelInitialTitle': "Сохранение карточки",
+'recordDetailAddFieldButtonLabel': "Добавить новое поле",
+'recordDetailPasswordFieldHelpLabel': "чтобы скопировать пароль в буфер обмена, нажмите на звездочку, затем Ctrl-C",
+'recordDetailPasswordFieldScrambleLabel': "спрятать",
+'recordDetailPasswordFieldUnscrambleLabel': "показать",
+'recordDetailDirectLoginBlockTitle': "Прямые подключения",
+'recordDetailNewDirectLoginDescription': "<p>Настройка прямых подключений</p> ",
+'recordDetailDirectLoginBlockNoDirectLoginConfiguredDescription': "<p>В этой карточке есть данные для доступа в онлайновый сервис?</p> <p>Используйте закладки, чтобы настроить “прямые подключения”!</p> ",
+'recordDetailAddNewDirectLoginButtonLabel': "Добавить новое прямое подключение",
+'recordDetailEditButtonLabel': "Редактировать",
+'recordDetailSaveButtonLabel': "Сохранить",
+'recordDetailCancelButtonLabel': "Отмена",
+'newRecordTitleLabel': "_новую карточку_",
+'recordSaveChangesPanelCollectRecordInfoMessageTitle': "Сохранение карточки",
+'recordSaveChangesPanelCollectRecordInfoMessageText': "Обновление заголовков карточек",
+'recordSaveChangesPanelEncryptUserDataMessageTitle': "Сохранение карточки",
+'recordSaveChangesPanelEncryptUserDataMessageText': "Шифрование заголовков карточки",
+'recordSaveChangesPanelEncryptRecordDataMessageTitle': "Сохранение карточки",
+'recordSaveChangesPanelEncryptRecordDataMessageText': "Шифровани данных карточки",
+'recordSaveChangesPanelEncryptRecordVersionDataMessageTitle': "Сохранение карточки",
+'recordSaveChangesPanelEncryptRecordVersionDataMessageText': "Шифрование данных версии карточки",
+'recordSaveChangesPanelSendingDataToTheServerMessageTitle': "Сохранение карточки",
+'recordSaveChangesPanelSendingDataToTheServerMessageText': "Передача зашифрованного заголовка карточки в Clipperz",
+'recordSaveChangesPanelUpdatingTheInterfaceMessageTitle': "Сохранение карточки",
+'recordSaveChangesPanelUpdatingTheInterfaceMessageText': "Обновление интерфейса",
+'passwordGeneratorPanelTitle': "Генератор паролей",
+'passwordGeneratorPanelOkLabel': "OK",
+'passwordGeneratorPanelCancelLabel': "Отмена",
+'passwordGeneratorLengthLabel': "длина:",
+//'DWRUtilLoadingMessage': "Загрузка данных ...",
+'comingSoon': "вскоре ...",
+'panelCollectingEntryopyMessageText': "Определение энтропии",
+'directLoginConfigurationCheckBoxFieldSelectedValue': "Да",
+'directLoginConfigurationCheckBoxFieldNotSelectedValue': "Нет",
+'WELCOME_BACK': "Добро пожаловать снова!",
+'currentConnectionText': "Сейчас вы подключились с ip&nbsp;__ip__, очевидно __country__, используя __browser__ на __operatingSystem__.",
+'latestConnectionText': "Последнее соединение было __elapsedTimeDescription__ (__time__) с ip&nbsp;__ip__, очевидно __country__, используя __browser__ на __operatingSystem__.",
+'fullLoginHistoryLinkLabel': "показать полную историю входов",
+'elapsedTimeDescriptions': {
+ 'MORE_THAN_A_MONTH_AGO': "за месяц",
+ 'MORE_THAN_A_WEEK_AGO': "за неделю",
+ 'MORE_THAN_*_WEEKS_AGO': "за несколько __elapsed__ недель",
+ 'YESTERDAY': "вчера",
+ '*_DAYS_AGO': "__elapsed__ дней(-я)",
+ 'ABOUT_AN_HOUR_AGO': "за час",
+ '*_HOURS_AGO': "__elapsed__ часов(-а)",
+ 'JUST_A_FEW_MINUTES_AGO': "несколько минут",
+ 'ABOUT_*_MINUTES_AGO': "около __elapsed__ минут"
+},
+'unknown_ip': "неизвестный",
+'calendarStrings': {
+ 'months': {
+ '0': "Январь",
+ '1': "Февраль",
+ '2': "Март",
+ '3': "Апрель",
+ '4': "Май",
+ '5': "Июнь",
+ '6': "Июль",
+ '7': "Август",
+ '8': "Сентябрь",
+ '9': "Октябрь",
+ '10': "Ноябрь",
+ '11': "Декабрь"
+ },
+ 'shortMonths': {
+ '0': "Янв",
+ '1': "Фев",
+ '2': "Мар",
+ '3': "Апр",
+ '4': "Май",
+ '5': "Июн",
+ '6': "Июл",
+ '7': "Авг",
+ '8': "Сен",
+ '9': "Окт",
+ '10': "Ноя",
+ '11': "Дек"
+ },
+ 'days': {
+ '0': "Воскресенье",
+ '1': "Понедельник",
+ '2': "Вторник",
+ '3': "Среда",
+ '4': "Четверг",
+ '5': "Пятница",
+ '6': "Суббота"
+ },
+ 'shortDays': {
+ '0': "Вск",
+ '1': "Пон",
+ '2': "Втр",
+ '3': "Сре",
+ '4': "Чет",
+ '5': "Пят",
+ '6': "Суб"
+ },
+ 'amDesignation': "am",
+ 'pmDesignation': "pm"
+},
+
+__syntaxFix__: "syntax fix"
+});
diff --git a/frontend/beta/js/Clipperz/PM/Strings/Strings_zh-CN.js b/frontend/beta/js/Clipperz/PM/Strings/Strings_zh-CN.js
new file mode 100644
index 0000000..a1d09f1
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Strings/Strings_zh-CN.js
@@ -0,0 +1,477 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+Clipperz.PM.Strings.Languages['zh-CN'.toLowerCase()] = MochiKit.Base.merge(Clipperz.PM.Strings.Languages['en-us'], {
+'clipperzServiceDescription': "<h2>只有你知道</h2> <ul> <li> <h3>Clipperz 是:</h3> <ul> <li> <p>一个简单而又安全的密码管理员</p> </li> <li> <p>一个有效的单一登录解决方案</p> </li> <li> <p>一个您保密的资料数据库</p> </li> </ul> </li> <li> <h3> 使用 Clipperz 你能:</h3> <ul> <li> <p>储存和管理你的密码和网上证书</p> </li> <li> <p>无需输入密码自动帮助你登录网站服务</p> </li> <li> <p>保护你的敏感数据:通讯录,口令,信用卡号码, ...</p> </li> <li> <p>与家人和伙伴分享秘密(将要上线)</p> </li> </ul> </li> <li> <h3>Clipperz 的特点:</h3> <ul> <li> <p>免费,彻底匿名</p> </li> <li> <p>在任何时间 任何电脑都可以轻松获取你的密码</p> </li> <li> <p>无需下载和安装任何软件</p> </li> <li> <p>再也无需在电脑或者纸上记录密码了</p> </li> </ul> </li> <li> <h3>Clipperz 的安全性:</h3> <ul> <li> <p>密码将在本地浏览器加密,然后上传至 Clipperz</p> </li> <li> <p>加密密钥是一个只有你知道的密码短语</p> </li> <li> <p>Clipperz 服务会加密你的敏感数据,并不会出现数据的原始形式</p> </li> <li> <p>Clipperz 基于加密标准,没有任何的花哨</p> </li> <li> <p>只要你愿意,你随时都可以查看源代码,但是做为一个使用者来说完全没有去必要去了解那些繁琐的加密原理</p> </li> </ul> </li> <li> <a href=\"http://www.clipperz.com\" target=\"_blank\">更多</a> </li> </ul> ",
+'loginFormTitle': "用你的 Clipperz 帐户登录",
+'loginFormUsernameLabel': "用户名",
+'loginFormPassphraseLabel': "密码短语",
+'loginFormDontHaveAnAccountLabel': "还未建立帐户?",
+'loginFormCreateOneLabel': "创建一个新帐户",
+'loginFormForgotYourCredentialsLabel': "忘记你的证书?",
+'loginFormAarghThatsBadLabel': "呃?这下糟糕了",
+'loginFormAfraidOfMaliciousScriptsLabel': "害怕有恶意脚本?",
+'loginFormVerifyTheCodeLabel': "验证代码",
+'loginFormButtonLabel': "登录",
+'loginFormOneTimePasswordCheckboxLabel': "使用一次性密码短语",
+'loginPanelSwithLanguageDescription': "<h5>选择你的第一语言</h5> ",
+'browserCompatibilityDescription': "<p>使用 Firefox 将得到更快更安全的 Clipperz 服务。不过 Clipperz 同样可以很好的工作在 Opera 和 微软的 IE 中。</p> ",
+'OTPloginMessagePanelInitialTitle': "用一次性密码短语登录",
+'OTPloginMessagePanelInitialText': "发送 OTP 证书 ...",
+'OTPloginMessagePanelLoadingTitle': "用一次性密码短语登录",
+'OTPloginMessagePanelLoadingText': "从服务器读取加密认证数据 ...",
+'OTPloginMessagePanelProcessingTitle': "用一次性密码短语登录",
+'OTPloginMessagePanelProcessingText': "本地解密认证数据",
+'loginMessagePanelInitialTitle': "登录中...",
+'loginMessagePanelInitialButtonLabel': "取消",
+'loginMessagePanelConnectedTitle': "连接成功",
+'loginMessagePanelConnectedText': "完成",
+'loginMessagePanelFailureTitle': "错误",
+'loginMessagePanelFailureText': "登录失败",
+'loginMessagePanelFailureButtonLabel': "取消",
+'connectionLoginSendingCredentialsMessageTitle': "验证证书",
+'connectionLoginSendingCredentialsMessageText': "传送证书",
+'connectionLoginCredentialsVerificationMessageTitle': "验证证书",
+'connectionLoginCredentialsVerificationMessageText': "进行 SRP 认证",
+'connectionLoginDoneMessageTitle': "验证证书",
+'connectionLoginDoneMessageText': "已连接",
+'userLoginPanelUpgradingUserCredentialsMessageTitle': "验证证书",
+'userLoginPanelUpgradingUserCredentialsMessageText': "升级证书到新的认证模式",
+'userLoginPanelConnectedMessageTitle': "用户识别",
+'userLoginPanelConnectedMessageText': "成功登录",
+'userLoginPanelTryingAnOlderConnectionSchemaMessageTitle': "验证证书",
+'userLoginPanelTryingAnOlderConnectionSchemaMessageText': "旧认证模式失效",
+'userLoginPanelLoadingUserDataMessageTitle': "用户识别",
+'userLoginPanelLoadingUserDataMessageText': "正在从 Clipperz 下载加密卡报头",
+'userLoginPanelDecryptingUserDataMessageTitle': "用户识别",
+'userLoginPanelDecryptingUserDataMessageText': "加密卡报头本地解密",
+'userLoginPanelDecryptingUserStatisticsMessageTitle': "用户识别",
+'userLoginPanelDecryptingUserStatisticsMessageText': "本地解密使用统计",
+'splashAlertTitle': "Clipperz 欢迎您",
+'splashAlertText': "<p>安全忠告</p> <ul> <li> <p>在 Clipperz ,用你选择的密码短语保存数据是安全的。没有人能够得到这些数据,除非他们有你的密码。</p> </li> <li> <p> 如果你决定使用 Clipperz 保护敏感数据和关键资料,请务必选用一个复杂的密码短语。越长越好</p> </li> <li> <p>注意:Clipperz将无法找回忘记的密码码短语!</p> </li> </ul> <p>获得更多的说明,请前往 <a href=\"http://www.clipperz.com\" target=\"_blank\">Clipperz</a> 网站.</p> ",
+'splashAlertCloseButtonLabel': "确定",
+'registrationFormTitle': "创建你的帐户",
+'registrationFormUsernameLabel': "用户名",
+'registrationFormPassphraseLabel': "密码短语",
+'registrationFormRetypePassphraseLabel': "确认密码短语",
+'registrationFormSafetyCheckLabel': "我明白 Clipperz 无法找回忘记的密码短语.",
+'registrationFormTermsOfServiceCheckLabel': "我同意接受 <a href='http://www.clipperz.com/terms_of_service' target='_blank'>服务条款</a> 款.",
+'registrationFormDoYouAlreadyHaveAnAccountLabel': "如果已有一个 Clipperz 帐户",
+'registrationFormSimplyLoginLabel': "在此登录",
+'registrationFormButtonLabel': "注册",
+'registrationFormWarningMessageNotMatchingPassphrases': "两次密码短语不同,请重新输入",
+'registrationFormWarningMessageSafetyCheckNotSelected': "请阅读并检查下面的选项框",
+'registrationFormWarningMessageTermsOfServiceCheckNotSelected': "您需要同意服务条款",
+'registrationMessagePanelInitialTitle': "创建账户...",
+'registrationMessagePanelInitialButtonLabel': "取消",
+'registrationMessagePanelRegistrationDoneTitle': "注册",
+'registrationMessagePanelRegistrationDoneText': "完成",
+'registrationMessagePanelFailureTitle': "注册失败",
+'registrationMessagePanelFailureButtonLabel': "关闭",
+'connectionRegistrationSendingRequestMessageText': "验证证书",
+'connectionRegistrationSendingCredentialsMessageText': "传送证书",
+'registrationSplashPanelTitle': "安全忠告",
+'registrationSplashPanelDescription': "<p>这是你的 Clipperz 证书,请保存好。Clipperz 永远不会第二次显示你的用户名和密码短语</p> ",
+'registrationSplashPanelUsernameLabel': "用户名",
+'registrationSplashPanelPassphraseLabel': "密码短语",
+'registrationSplashPanelShowPassphraseButtonLabel': "显示密码短语",
+'donateHeaderLinkLabel': "捐赠",
+'creditsHeaderLinkLabel': "致谢",
+'feedbackHeaderLinkLabel': "反馈",
+'helpHeaderLinkLabel': "帮助",
+'forumHeaderLinkLabel': "论坛",
+'recordMenuLabel': "密码卡片",
+'accountMenuLabel': "账户",
+'dataMenuLabel': "资料",
+'contactsMenuLabel': "联系",
+'toolsMenuLabel': "工具",
+'logoutMenuLabel': "暂时离开",
+'lockMenuLabel': "安全锁",
+'lockTitle': "账户被锁定",
+'lockDescription': "<p>请输入你的密码短语解开账户</p> ",
+'unlockButtonLabel': "解锁",
+'changePasswordTabLabel': "修改密码短语",
+'changePasswordTabTitle': "修改密码短语",
+'changePasswordFormUsernameLabel': "用户名",
+'changePasswordFormOldPassphraseLabel': "旧密码短语",
+'changePasswordFormNewPassphraseLabel': "新密码短语",
+'changePasswordFormRetypePassphraseLabel': "确认密码短语",
+'changePasswordFormSafetyCheckboxLabel': "我知道 Clipperz 不能找回丢失的密码短语",
+'changePasswordFormSubmitLabel': "修改密码短语",
+'changePasswordFormWrongUsernameWarning': "用户名错误",
+'changePasswordFormWrongPassphraseWarning': "旧密码短语错误",
+'changePasswordFormWrongRetypePassphraseWarning': "两次密码短语不同,请重新输入",
+'changePasswordFormSafetyCheckWarning': "请阅读并检查下面的选项框",
+'changePasswordFormProgressDialogTitle': "正在修改密码短语",
+'changePasswordFormProgressDialogConnectedMessageTitle': "连接",
+'changePasswordFormProgressDialogConnectedMessageText': "完成",
+'changePasswordFormProgressDialogErrorMessageTitle': "错误",
+'changePasswordFormProgressDialogErrorMessageText': "证书修改失败",
+'changeCredentialsPanelEncryptingDataMessageTitle': "正在修改你的密码短语",
+'changeCredentialsPanelEncryptingDataMessageText': "加密卡报头本地解密",
+'changeCredentialsPanelCreatingNewCredentialsMessageTitle': "正在修改你的密码短语",
+'changeCredentialsPanelCreatingNewCredentialsMessageText': "更新你的证书",
+'changeCredentialsPanelSendingNewCredentialsToTheServerMessageTitle': "正在修改你的密码短语",
+'changeCredentialsPanelSendingNewCredentialsToTheServerMessageText': "正在上传本地证书到 Clipperz",
+'changeCredentialsPanelDoneMessageTitle': "正在修改你的密码短语",
+'changeCredentialsPanelDoneMessageText': "完成",
+'manageOTPTabLabel': "管理你的一次性密码短语",
+'manageOTPTabTitle': "管理你的一次性密码短语",
+'manageOTPTabDescription': "<p>一次性密码短语工作起来和一般的密码短语一样,但是只可以使用一次</p> <p>如果同样的密码短语在一段时间以内再次登录,会被拒绝。登录进程将会失败。</p> <p>为了防止任何欺诈登录,在成功登陆之后,你的一次性密码将会立即被删除,</p> <p>如果一次性密码被键盘记录程序或者间谍软件得到,可能会从被感染的机器上收集数据,这样的话,一次性密码绝对是个很好的选择。</p> <p> <b>强烈建议在公共场合登录 Clipperz 时,使用一次性密码。比如公关计算机,网吧,图书馆等</b> </p> ",
+'oneTimePasswordReadOnlyMessage': "<h6>对不起!</h6> <p>你不能从离线版本管理你的一次性密码短语</p> ",
+'oneTimePasswordLoadingMessage': "<h6>加载数据</h6> <p>请等待 ...</p> ",
+'oneTimePasswordNoPasswordAvailable': "<h6>一次性密码短语没有激活</h6> <p>点击“新建”按钮添加一次性密码短语到你的帐户</p> ",
+'createNewOTPButtonLabel': "新建",
+'deleteOTPButtonLabel': "删除",
+'printOTPButtonLabel': "打印",
+'disabledOneTimePassword_warning': "禁用",
+'oneTimePasswordSelectionLink_selectLabel': "选择:",
+'oneTimePasswordSelectionLink_all': "所有",
+'oneTimePasswordSelectionLink_none': "没有",
+'oneTimePasswordSelectionLink_used': "被使用",
+'oneTimePasswordSelectionLink_unused': "未使用",
+'saveOTP_encryptUserDataTitle': "保存一次性密码短语",
+'saveOTP_encryptUserDataText': "处理新的 OTP 证书 ...",
+'saveOTP_encryptOTPDataTitle': "保存一次性密码短语",
+'saveOTP_encryptOTPDataText': "本地解密认证数据 ...",
+'saveOTP_sendingDataTitle': "保存一次性密码短语",
+'saveOTP_sendingDataText': "发送信任数据到服务器 ...",
+'saveOTP_updatingInterfaceTitle': "保存一次性密码短语",
+'saveOTP_updatingInterfaceText': "更新界面...",
+'accountPreferencesLabel': "使用偏好",
+'accountPreferencesTabTitle': "使用偏好",
+'accountPreferencesLanguageTitle': "界面语言选择",
+'accountPreferencesLanguageDescription': "<p>在下拉菜单中选择你的首选语言</p> ",
+'showDonationReminderPanelTitle': "捐赠提示",
+'showDonationReminderPanelDescription': "<p>显示捐赠提示</p> ",
+'saveUserPreferencesFormSubmitLabel': "保存",
+'cancelUserPreferencesFormSubmitLabel': "取消",
+'accountPreferencesSavingPanelTitle_Step1': "保存使用偏好",
+'accountPreferencesSavingPanelText_Step1': "本地加密你的使用偏好",
+'accountPreferencesSavingPanelTitle_Step2': "保存使用偏好",
+'accountPreferencesSavingPanelText_Step2': "正在向 Clipperz 传送加密后的使用偏好",
+'accountLoginHistoryLabel': "登录历史",
+'loginHistoryTabTitle': "登录历史",
+'loginHistoryReadOnlyMessage': "<h6>对不起!</h6> <p>当你使用离线版本时登录历史是无法显示的</p> ",
+'loginHistoryLoadingMessage': "<h6>加载数据</h6> <p>请等待 ...</p> ",
+'loginHistoryLoadedMessage': "<h6>您的最近 10 次登陆</h6> <p> </p> ",
+'loginHistoryIPLabel': "IP",
+'loginHistoryTimeLabel': "时间",
+'loginHistoryCurrentSessionText': "当前登录信息",
+'loginHistoryReloadButtonLabel': "刷新登录历史",
+'deleteAccountTabLabel': "删除你的账户",
+'deleteAccountTabTitle': "删除你的账户",
+'deleteAccountFormUsernameLabel': "用户名",
+'deleteAccountFormPassphraseLabel': "密码短语",
+'deleteAccountFormSafetyCheckboxLabel': "我知道我的所有数据将被删除,并且是不可回复的.",
+'deleteAccountFormSubmitLabel': "删除我的账户",
+'deleteAccountFormWrongUsernameWarning': "用户名错误",
+'deleteAccountFormWrongPassphraseWarning': "密码短语错误",
+'deleteAccountFormSafetyCheckWarning': "请阅读并检查下面的选项框",
+'accountPanelDeletingAccountPanelConfirmationTitle': "注意",
+'accountPanelDeleteAccountPanelConfirmationText': "你确认要删除你的帐户",
+'accountPanelDeleteAccountPanelConfirmButtonLabel': "是",
+'accountPanelDeleteAccountPanelDenyButtonLabel': "否",
+'offlineCopyTabLabel': "离线拷贝",
+'offlineCopyTabTitle': "离线拷贝",
+'offlineCopyTabDescription': "<p>只需点击一次就可以从 Clipperz 服务器下载所有加密数据到你的硬盘,让你在不能连接互联网的时候使用离线只读版本的 Clipperz。</p> <p>你下载的离线数据和登陆我们网站在线使用是一样安全的,它们使用了同样的密码和安全体系,都不会有暴露数据的风险。</p> <ol> <li> <p>点击链接后开始下载。</p> </li> <li> <p>浏览器会问你如何处理 “Clipperz_YYYYMMDD.html” 文件。保存这个文件到你的硬盘。</p> </li> <li> <p>双击下载的文件在浏览器运行离线版本。</p> </li> <li> <p>输入你的用户名和密码短语。</p> </li> </ol> ",
+'offlineCopyDownloadLinkLabel': "下载",
+'offlineCopyDownloadWarning': "<h4> <a href=\"#\" id=\"offlineCopyDownloadWarningLink\">更新你的“离线版本”!</a> </h4> <p>你最近创建或修改了卡片,需要下载新的“离线版本”</p> ",
+'sharingTabLabel': "共享",
+'sharingTabTitle': "共享",
+'sharingTabDescription': "<p>往往一个机密的资料需要另外一个人或者多人共同使用</p> <p>你可以在这里设置一个简单的授权码,以便在离开办公室的时候你的同事可以访问你的邮箱,或者设置一个复杂的,当你去世后子孙可以在这里找到取得银行保险箱的方法。</p> <p>Clipperz 可以安全并且简单的分享你的密码</p> <p> </p> <p> <b>即将发布...</b> </p> ",
+'importTabLabel': "导入",
+'importTabTitle': "导入",
+'importTabDescription': "<p> <b>即将发布 ...</b> </p> ",
+'printingTabLabel': "导出",
+'printingTabTitle': "导出",
+'printingTabDescription': "<p> <b>打印你的数据</b> </p> <p>点击下面的链接,将会打开一个新窗口,以打印格式显示你的密码卡片</p> <p>如果你打印下来是为了备份,请考虑使用我们提供的\"离线版本\",这比打印更安全。</p> ",
+'printingLinkLabel': "打印版本",
+'contactsTabLabel': "联系",
+'contactsTabTitle': "联系",
+'passwordGeneratorTabLabel': "随机密码生成器",
+'passwordGeneratorTabTitle': "随机密码生成器",
+'passwordGeneratorTabButtonLabel': "生成随机密码",
+'bookmarkletTabLabel': "书签按钮",
+'bookmarkletTabTitle': "书签按钮",
+'bookmarkletTabDescription': "<p>这个书签按钮是一个简单的非常有用的“一键”工具,它能像一般网站一样储存并且使用</p> <p>Clipperz 按钮书签可以帮助你快速建立密码卡片并且用存在的密码卡片直接登录</p> <p> <b>请注意,这个书签按钮不包含你账户中的任何信息(例如你的用户名和密码),对所有的 Clipperz 使用者,这个书签按钮是大家的工具,代码都是相同的。</b> </p> <h3>怎样安装书签按钮</h3> <h5>Firefox, Camino, Opera, Safari</h5> <ol> <li> <p>选择 “查看 > 工具栏 > 书签工具栏” 确认 “书签工具栏” 显示在浏览器菜单上。</p> </li> <li> <p>拖动 “添加到 Clipperz” 链接到书签工具栏。</p> </li> </ol> <h5>Internet Explorer</h5> <ol> <li> <p>选择 “查看 > 工具栏 > 链接” 确认 “链接” 显示在浏览器菜单上。</p> </li> <li> <p>右键 “添加到 Clipperz”</p> </li> <li> <p>选择 “添加到收藏夹”</p> </li> <li> <p>如果弹出安全提示选择 “是”</p> </li> <li> <p>打开 “链接” 文件夹后单击 “添加”</p> </li> </ol> ",
+'bookmarkletTabBookmarkletTitle': "添加到 Clipperz",
+'bookmarkletTabInstructions': "<h3>如何在一个在线服务中创建可以直接登录的新的密码卡片</h3> <ol> <li> <p>打开你要登录的页面(这个页面通常就是你输入登录信息的页面)</p> </li> <li> <p>点击书签按钮,会出现一个新的弹出窗口</p> </li> <li> <p>复制弹出窗口中的所有文本到剪贴板(ctrl+c)</p> </li> <li> <p>登录你的 Clipperz 账户,然后点击 <b>新建密码卡片</b> 按钮</p> </li> <li> <p>选择“直接登录”模板,之后粘贴剪贴板中的内容到大文本框(ctrl+v)</p> </li> <li> <p>按下 <b>创建</b> 按钮,检查细节并且点击 <b>保存</b>.</p> </li> </ol> <h3>对于已经存在的密码卡片如何添加直接登陆</h3> <ol> <li> <p>与上面的步骤相同</p> </li> <li> <p>与上面的步骤相同</p> </li> <li> <p>与上面的步骤相同</p> </li> <li> <p>输入你的 Clipperz 帐号,选择你刚刚访问的网络服务的密码卡片然后点击 <b>编辑</b> 按钮.</p> </li> <li> <p>将剪贴板中的内容粘贴到“直接登录”区域的大文本框中 (ctrl-V)</p> </li> <li> <p>点击添加 <b>自动登录</b> 按钮,检查细节并且点击k <b>保存</b>.</p> </li> </ol> <p> </p> <p>如果需要关于书签按钮的进一步资料可以在 <a href=\"http://www.clipperz.com/support/user_guide/bookmarklet\" target=\"_blank\">这里获得</a>.</p> ",
+'mainPanelDirectLoginBlockLabel': "直接登录",
+'directLinkReferenceShowButtonLabel': "显示",
+'mainPanelDirectLoginBlockDescription': "<p>添加 “直接登录” 可以让你不用输入用户名和密码即可登录网络账户</p> <p>“直接登录” 可以大大提高你的密码安全性,因为你可以:</p> <ul> <li> <p>方便选择和输入复杂的密码</p> </li> <li> <p>永远不再使用相同的,容易猜测的密码</p> </li> </ul> <p>用 Clipperz 书签按钮简单快速的配置</p> <a href=\"http://www.clipperz.com/support/user_guide/direct_logins\" target=\"_blank\">关于 “直接登录” 的更多信息</a> ",
+'mainPanelRecordsBlockLabel': "密码卡片",
+'mainPanelAddRecordButtonLabel': "添加新密码卡片",
+'mainPanelRemoveRecordButtonLabel': "删除密码卡片",
+'mainPanelRecordFilterBlockAllLabel': "所有",
+'mainPanelRecordFilterBlockTagsLabel': "标签",
+'mainPanelRecordFilterBlockSearchLabel': "搜索",
+'recordDetailNoRecordAtAllTitle': "欢迎来到 Clipperz!",
+'recordDetailNoRecordAtAllDescription': "<h5>从你的账户添加密码卡片开始</h5> <p>密码卡片是简单灵活的方式,在这里你可以保存你的密码和其他机密资料.</p> <p>密码卡片含有一个全权访问网站的证书,你的通讯录,你的信用卡信息,……</p> <h5>不要忘记书签按钮</h5> <p>在你开始前,安装 “添加到 Clipperz” 书签按钮:它将使创建密码卡片变得简单并且有趣</p> <p>去书签按钮标签了解如何安装并使用它</p> <p> </p> <p>然后只需单击 “添加密码卡片” 按钮,即可尽情享受 Clipperz 帐户.</p> <p> <a href=\"http://www.clipperz.com/support/user_guide/managing_cards\" target=\"_blank\">关于创建和管理密码卡片的更多信息</a> </p> ",
+'newRecordWizardTitleBox': "<h5>请选择一个模板</h5> <p>密码卡片是简单灵活的方式,在这里你可以保存你的密码和其他机密资料.</p> <p>首先选择下面的一个模板。在添加或者删除以后,可以随时定制你的密码卡片.</p> ",
+'newRecordWizardBookmarkletConfigurationTitle': "直接登陆",
+'newRecordWizardBookmarkletConfigurationDescription': "<p>将从 Clipperz 书签按钮得到的代码粘贴到下面的文本框中</p> <p>一个直接登陆你的网络账户的新密码卡片将要被创建完成</p> ",
+'newRecordWizardCreateButtonLabel': "创建",
+'newRecordWizardCancelButtonLabel': "取消",
+'donateSplashPanelTitle': "今天就捐赠支持 Clipperz!",
+'donateSplashPanelDescription': "<p>捐赠我们的原因:</p> <ul> <li> <p>支持新特性的开发</p> </li> <li> <p>保持 Clipperz 的免费</p> </li> <li> <p>对我们的辛勤工作表示感谢</p> </li> </ul> <p> <a href=\"http://www.clipperz.com/donations\" target=\"_blank\">进一步资料,请浏览我们的捐款页</a>.</p> <p> <b>愿意捐款?</b> </p> ",
+'donateCloseButtonLabel': "不必了",
+'donateDonateButtonLabel': "是",
+'recordTemplates': {
+ 'WebAccount': {
+ 'title': "网站密码",
+ 'description': "<p>为您的网上服务提供简单的密码储存,自动登录服务.</p> ",
+ 'fields': {
+ 'URL': "网址",
+ 'TXT': "用户名或者电子邮件地址",
+ 'PWD': "密码"
+ }
+ },
+ 'BankAccount': {
+ 'title': "银行帐户",
+ 'description': "<p>安全储存你的银行账号和网上银行证书.</p> ",
+ 'fields': {
+ 'TXT': "银行",
+ 'TXT': "帐号",
+ 'URL': "银行网站",
+ 'TXT': "在线银行 ID",
+ 'PWD': "在线银行密码"
+ }
+ },
+ 'CreditCard': {
+ 'title': "信用卡",
+ 'description': "<p>信用卡号码,有效日期,CVV2和PIN 都由 Clipperz 管理</p> ",
+ 'fields': {
+ 'TXT': "类型(VISA, AmEx, ...)",
+ 'TXT': "号码",
+ 'TXT': "持卡人姓名",
+ 'TXT': "有效日期",
+ 'TXT': "CVV2",
+ 'PWD': "PIN",
+ 'URL': "信用卡网站",
+ 'TXT': "用户名",
+ 'PWD': "密码"
+ }
+ },
+ 'AddressBookEntry': {
+ 'title': "通讯录条目",
+ 'description': "<p>Clipperz 同样可以为你的私人通讯录服务. 使用这个模板,轻易添加新的条目.</p> ",
+ 'fields': {
+ 'TXT': "姓名",
+ 'TXT': "电子邮件",
+ 'TXT': "电话",
+ 'TXT': "手机",
+ 'ADDR': "地址"
+ }
+ },
+ 'Custom': {
+ 'title': "定制密码卡片",
+ 'description': "<p>无论你需要保护哪种类型的机密数据,创建定制密码卡片便可满足你的需求</p> ",
+ 'fields': {
+ 'TXT': "标签 1",
+ 'TXT': "标签 2",
+ 'TXT': "标签 3"
+ }
+ }
+},
+'recordFieldTypologies': {
+ 'TXT': {
+ 'description': "simple text field",
+ 'shortDescription': "文字"
+ },
+ 'PWD': {
+ 'description': "simple text field, with default status set to hidden",
+ 'shortDescription': "密码"
+ },
+ 'URL': {
+ 'description': "simple text field in edit mode, that became an active url in view mode",
+ 'shortDescription': "网址"
+ },
+ 'DATE': {
+ 'description': "a value set with a calendar helper",
+ 'shortDescription': "数据"
+ },
+ 'ADDR': {
+ 'description': "just like the URL, but the active link points to Google Maps (or similar service) passing the address value as argument",
+ 'shortDescription': "地址"
+ },
+ 'CHECK': {
+ 'description': "check description",
+ 'shortDescription': "check"
+ },
+ 'RADIO': {
+ 'description': "radio description",
+ 'shortDescription': "radio"
+ },
+ 'SELECT': {
+ 'description': "select description",
+ 'shortDescription': "select"
+ }
+},
+'newRecordPanelGeneralExceptionTitle': "错误",
+'newRecordPanelGeneralExceptionMessage': "配置文本不正确,请从书签中确认你的文本并且再试一次",
+'newRecordPanelWrongBookmarkletVersionExceptionTitle': "错误",
+'newRecordPanelWrongBookmarkletVersionExceptionMessage': "配置文本已经产生了一个旧版本书签,请更新你的书签然后再试试。",
+'newRecordPanelExceptionPanelCloseButtonLabel': "取消",
+'mainPanelDeletingRecordPanelConfirmationTitle': "删除所选密码卡片",
+'mainPanelDeleteRecordPanelConfirmationText': "确认要删除选定的密码卡片?",
+'mainPanelDeleteRecordPanelConfirmButtonLabel': "是",
+'mainPanelDeleteRecordPanelDenyButtonLabel': "否",
+'mainPanelDeletingRecordPanelInitialTitle': "删除选定的密码卡片",
+'mainPanelDeletingRecordPanelCompletedText': "完成",
+'deleteRecordPanelCollectRecordDataMessageTitle': "删除密码卡片",
+'deleteRecordPanelCollectRecordDataMessageText': "更新密码卡片列表",
+'deleteRecordPanelEncryptUserDataMessageTitle': "删除密码卡片",
+'deleteRecordPanelEncryptUserDataMessageText': "加密卡报头本地解密",
+'deleteRecordPanelSendingDataToTheServerMessageTitle': "删除密码卡片",
+'deleteRecordPanelSendingDataToTheServerMessageText': "从 Clipperz 更新加密卡报头",
+'deleteRecordPanelUpdatingTheInterfaceMessageTitle': "删除密码卡片",
+'deleteRecordPanelUpdatingTheInterfaceMessageText': "更新界面",
+'recordDetailNoRecordSelectedTitle': "未选择密码卡片",
+'recordDetailNoRecordSelectedDescription': "<p>从左边的列表中选择一个密码卡片</p> ",
+'recordDetailLoadingRecordMessage': "正在从 Clipperz 下载加密卡片",
+'recordDetailDecryptingRecordMessage': "密码卡片数据本地解密",
+'recordDetailLoadingRecordVersionMessage': "下载最新版本的密码卡片",
+'recordDetailDecryptingRecordVersionMessage': "本地解密最新版本密码卡片",
+'recordDetailLoadingErrorMessageTitle': "密码卡片下载错误",
+'recordDetailNotesLabel': "注释",
+'recordDetailLabelFieldColumnLabel': "标签区域",
+'recordDetailDataFieldColumnLabel': "数据区域",
+'recordDetailTypeFieldColumnLabel': "类型",
+'recordDetailSavingChangesMessagePanelInitialTitle': "保存密码卡片",
+'recordDetailAddFieldButtonLabel': "添加新区域",
+'recordDetailPasswordFieldHelpLabel': "点击星星复制密码到剪贴板,然后用 Ctrl+V 使用",
+'recordDetailPasswordFieldScrambleLabel': "隐藏密码",
+'recordDetailPasswordFieldUnscrambleLabel': "显示密码",
+'recordDetailDirectLoginBlockTitle': "直接登录",
+'recordDetailNewDirectLoginDescription': "<p>直接登录配置</p> ",
+'recordDetailDirectLoginBlockNoDirectLoginConfiguredDescription': "<p>这个密码卡片包含在线服务证书吗?</p> <p>仅仅单击就可以从 Clipperz 使用书签配置 “直接登录”</p> ",
+'recordDetailAddNewDirectLoginButtonLabel': "添加新的直接登录",
+'recordDetailEditButtonLabel': "编辑",
+'recordDetailSaveButtonLabel': "保存",
+'recordDetailCancelButtonLabel': "取消",
+'newRecordTitleLabel': "_新密码卡片_",
+'recordSaveChangesPanelCollectRecordInfoMessageTitle': "保存密码卡片",
+'recordSaveChangesPanelCollectRecordInfoMessageText': "更新密码卡片报头",
+'recordSaveChangesPanelEncryptUserDataMessageTitle': "保存密码卡片",
+'recordSaveChangesPanelEncryptUserDataMessageText': "本地加密卡片报头",
+'recordSaveChangesPanelEncryptRecordDataMessageTitle': "保存密码卡片",
+'recordSaveChangesPanelEncryptRecordDataMessageText': "本地加密卡片数据",
+'recordSaveChangesPanelEncryptRecordVersionDataMessageTitle': "保存密码卡片",
+'recordSaveChangesPanelEncryptRecordVersionDataMessageText': "本地加密密码卡片版本数据",
+'recordSaveChangesPanelSendingDataToTheServerMessageTitle': "保存密码卡片",
+'recordSaveChangesPanelSendingDataToTheServerMessageText': "从 Clipperz 更新加密卡报头",
+'recordSaveChangesPanelUpdatingTheInterfaceMessageTitle': "保存密码卡片",
+'recordSaveChangesPanelUpdatingTheInterfaceMessageText': "更新界面",
+'passwordGeneratorPanelTitle': "密码生成器",
+'passwordGeneratorPanelOkLabel': "确认",
+'passwordGeneratorPanelCancelLabel': "取消",
+'passwordGeneratorLengthLabel': "长度:",
+//'DWRUtilLoadingMessage': "加载数据。。。",
+'comingSoon': "即将到来。。。",
+'panelCollectingEntryopyMessageText': "收集平均信息",
+'directLoginConfigurationCheckBoxFieldSelectedValue': "是",
+'directLoginConfigurationCheckBoxFieldNotSelectedValue': "否",
+'WELCOME_BACK': "欢迎回来!",
+'currentConnectionText': "你的连接 IP 地址是&nbsp;__ip__; 来自 __country__, 在 __browser__ 上使用 __operatingSystem__。",
+'latestConnectionText': "你上次的登录 IP 是&nbsp;__ip__ 在 __elapsedTimeDescription__ (__time__); 来自 __country__, 在 __browser__ 上使用 __operatingSystem__。",
+'fullLoginHistoryLinkLabel': "显示所有登录历史",
+'elapsedTimeDescriptions': {
+ 'MORE_THAN_A_MONTH_AGO': "一个月之前",
+ 'MORE_THAN_A_WEEK_AGO': "一周之前",
+ 'MORE_THAN_*_WEEKS_AGO': "__elapsed__ 周以前",
+ 'YESTERDAY': "昨天",
+ '*_DAYS_AGO': "__elapsed__ 天之前",
+ 'ABOUT_AN_HOUR_AGO': "大约一个小时前",
+ '*_HOURS_AGO': "__elapsed__ 小时前",
+ 'JUST_A_FEW_MINUTES_AGO': "仅仅几分钟之前",
+ 'ABOUT_*_MINUTES_AGO': "大约 __elapsed__ 几分钟前"
+},
+'unknown_ip': "未知",
+'calendarStrings': {
+ 'months': {
+ '0': "一月",
+ '1': "二月",
+ '2': "三月",
+ '3': "四月",
+ '4': "五月",
+ '5': "六月",
+ '6': "七月",
+ '7': "八月",
+ '8': "九月",
+ '9': "十月",
+ '10': "十一月",
+ '11': "十二月"
+ },
+ 'shortMonths': {
+ '0': "一月",
+ '1': "二月",
+ '2': "三月",
+ '3': "四月",
+ '4': "五月",
+ '5': "六月",
+ '6': "七月",
+ '7': "八月",
+ '8': "九月",
+ '9': "十月",
+ '10': "十一月",
+ '11': "十二月"
+ },
+ 'days': {
+ '0': "星期日",
+ '1': "星期一",
+ '2': "星期二",
+ '3': "星期三",
+ '4': "星期四",
+ '5': "星期五",
+ '6': "星期六"
+ },
+ 'shortDays': {
+ '0': "日",
+ '1': "一",
+ '2': "二",
+ '3': "三",
+ '4': "四",
+ '5': "五",
+ '6': "六"
+ },
+ 'veryShortDays': {
+ '0': "日",
+ '1': "一",
+ '2': "二",
+ '3': "三",
+ '4': "四",
+ '5': "五",
+ '6': "六"
+ },
+ 'amDesignation': "上午",
+ 'pmDesignation': "下午"
+},
+
+__syntaxFix__: "syntax fix"
+});
diff --git a/frontend/beta/js/Clipperz/PM/Toll.js b/frontend/beta/js/Clipperz/PM/Toll.js
new file mode 100644
index 0000000..6d412c1
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/PM/Toll.js
@@ -0,0 +1,193 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. 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) {
+ 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;
+ },
+
+ //=========================================================================
+
+ 'prefixMatchingBits': function(aValue1, aValue2) {
+ var result;
+ var i,c;
+
+ result = 0;
+
+ c = Math.min(aValue1.length(), aValue2.length());
+ i = 0;
+ while (i<c && (aValue1.byteAtIndex(i) == aValue2.byteAtIndex(i))) {
+ result += 8;
+ i++;
+ }
+
+ if (i<c) {
+ var xorValue;
+
+ xorValue = (aValue1.byteAtIndex(i) ^ aValue2.byteAtIndex(i));
+
+ if (xorValue >= 128) {
+ result += 0;
+ } else if (xorValue >= 64) {
+ result += 1;
+ } else if (xorValue >= 32) {
+ result += 2;
+ } else if (xorValue >= 16) {
+ result += 3;
+ } else if (xorValue >= 8) {
+ result += 4;
+ } else if (xorValue >= 4) {
+ result += 5;
+ } else if (xorValue >= 2) {
+ result += 6;
+ } else if (xorValue >= 1) {
+ result += 7;
+ }
+ }
+
+ return result;
+ },
+
+ //=========================================================================
+
+ 'pay': function() {
+ var result;
+ var targetData;
+ var targetMatchSize;
+ var prefixMatchingBits;
+ var payment;
+ var i;
+
+//MochiKit.Logging.logDebug(">>> Toll.pay");
+ if (this.toll() == null) {
+ i = 0;
+//MochiKit.Logging.logDebug("--- Proxy.payToll - 1");
+ targetData = new Clipperz.ByteArray("0x" + this.targetValue());
+//MochiKit.Logging.logDebug("--- Proxy.payToll - 2");
+ targetMatchSize = this.cost();
+//MochiKit.Logging.logDebug("--- Proxy.payToll - 3");
+
+ payment = Clipperz.Crypto.PRNG.defaultRandomGenerator().getRandomBytes(32);
+//MochiKit.Logging.logDebug("--- Proxy.payToll - 4");
+
+ do {
+ var paymentData;
+
+//MochiKit.Logging.logDebug("--- Proxy.payToll - 5");
+ //payment = Clipperz.Crypto.PRNG.defaultRandomGenerator().getRandomBytes(32);
+ payment.increment();
+//MochiKit.Logging.logDebug("--- Proxy.payToll - 6");
+ paymentData = Clipperz.Crypto.SHA.sha256(payment);
+//MochiKit.Logging.logDebug("--- Proxy.payToll - 7");
+ prefixMatchingBits = this.prefixMatchingBits(targetData, paymentData);
+//MochiKit.Logging.logDebug("--- Proxy.payToll - 8");
+ i++;
+//MochiKit.Logging.logDebug("--- Proxy.payToll - 9");
+ } while (prefixMatchingBits < targetMatchSize);
+//MochiKit.Logging.logDebug("--- Proxy.payToll - 10");
+
+ this._toll = payment.toHexString().substring(2)
+ }
+//MochiKit.Logging.logDebug("<<< Toll.pay");
+
+ return this;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'deferredPay': function() {
+ var deferredResult;
+ var toll;
+
+//MochiKit.Logging.logDebug(">>> Toll.deferredPay");
+ toll = this;
+ deferredResult = new MochiKit.Async.Deferred();
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("y.1 - Proxy.deferredPayToll - 1: " + res); return res;});
+ deferredResult.addCallback(MochiKit.Base.method(toll, 'pay'));
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("y.2 - Proxy.deferredPayToll - 2: " + res); return res;});
+ deferredResult.addCallback(function(aToll) {
+ var result;
+
+ result = {
+ targetValue:aToll.targetValue(),
+ toll:aToll.toll()
+ };
+
+ return result;
+ });
+//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("y.3 - Proxy.deferredPayToll - 3: " + res); return res;});
+ deferredResult.callback();
+//MochiKit.Logging.logDebug("<<< Toll.deferredPay");
+
+ return deferredResult;
+ },
+
+ //=========================================================================
+ __syntaxFix__: "syntax fix"
+
+});
+
diff --git a/frontend/beta/js/Clipperz/Profile.js b/frontend/beta/js/Clipperz/Profile.js
new file mode 100644
index 0000000..31888a9
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/Profile.js
@@ -0,0 +1,485 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+addEvent(window, "load", sortables_init);
+
+var SORT_COLUMN_INDEX;
+
+function sortables_init() {
+ // Find all tables with class sortable and make them sortable
+ if (!document.getElementsByTagName) return;
+ tbls = document.getElementsByTagName("table");
+ for (ti=0;ti<tbls.length;ti++) {
+ thisTbl = tbls[ti];
+ if (((' '+thisTbl.className+' ').indexOf("sortable") != -1) && (thisTbl.id)) {
+ //initTable(thisTbl.id);
+ ts_makeSortable(thisTbl);
+ }
+ }
+}
+
+function ts_makeSortable(table) {
+ if (table.rows && table.rows.length > 0) {
+ var firstRow = table.rows[0];
+ }
+ if (!firstRow) return;
+
+ // We have a first row: assume it's the header, and make its contents clickable links
+ for (var i=0;i<firstRow.cells.length;i++) {
+ var cell = firstRow.cells[i];
+ var txt = ts_getInnerText(cell);
+ cell.innerHTML = '<a href="#" class="sortheader" '+
+ 'onclick="ts_resortTable(this, '+i+');return false;">' +
+ txt+'<span class="sortarrow">&nbsp;&nbsp;&nbsp;</span></a>';
+ }
+}
+
+function ts_getInnerText(el) {
+ if (typeof el == "string") return el;
+ if (typeof el == "undefined") { return el };
+ if (el.innerText) return el.innerText; //Not needed but it is faster
+ var str = "";
+
+ var cs = el.childNodes;
+ var l = cs.length;
+ for (var i = 0; i < l; i++) {
+ switch (cs[i].nodeType) {
+ case 1: //ELEMENT_NODE
+ str += ts_getInnerText(cs[i]);
+ break;
+ case 3: //TEXT_NODE
+ str += cs[i].nodeValue;
+ break;
+ }
+ }
+ return str;
+}
+
+function ts_resortTable(lnk,clid) {
+ // get the span
+ var span;
+ for (var ci=0;ci<lnk.childNodes.length;ci++) {
+ if (lnk.childNodes[ci].tagName && lnk.childNodes[ci].tagName.toLowerCase() == 'span') span = lnk.childNodes[ci];
+ }
+ var spantext = ts_getInnerText(span);
+ var td = lnk.parentNode;
+ var column = clid || td.cellIndex;
+ var table = getParent(td,'TABLE');
+
+ // Work out a type for the column
+ if (table.rows.length <= 1) return;
+ var itm = ts_getInnerText(table.rows[1].cells[column]);
+ sortfn = ts_sort_caseinsensitive;
+ if (itm.match(/^\d\d[\/-]\d\d[\/-]\d\d\d\d$/)) {
+ sortfn = ts_sort_date;
+ }
+ if (itm.match(/^\d\d[\/-]\d\d[\/-]\d\d$/)) {
+ sortfn = ts_sort_date;
+ }
+ if (itm.match(/^[£$]/)) {
+ sortfn = ts_sort_currency;
+ }
+ if (itm.match(/^[\d\.]+$/)) {
+ sortfn = ts_sort_numeric;
+ }
+ SORT_COLUMN_INDEX = column;
+ var firstRow = new Array();
+ var newRows = new Array();
+ for (i=0;i<table.rows[0].length;i++) {
+ firstRow[i] = table.rows[0][i];
+ }
+
+ for (j=1;j<table.rows.length;j++) {
+ newRows[j-1] = table.rows[j];
+ }
+ newRows.sort(sortfn);
+
+ if (span.getAttribute("sortdir") == 'down') {
+ ARROW = '&nbsp;&nbsp;&uarr;';
+ newRows.reverse();
+ span.setAttribute('sortdir','up');
+ } else {
+ ARROW = '&nbsp;&nbsp;&darr;';
+ span.setAttribute('sortdir','down');
+ }
+
+ // We appendChild rows that already exist to the tbody, so it moves them rather than creating new ones
+ // don't do sortbottom rows
+ for (i=0;i<newRows.length;i++) {
+ if (!newRows[i].className || (newRows[i].className && (newRows[i].className.indexOf('sortbottom') == -1))) {
+ table.tBodies[0].appendChild(newRows[i]);
+ }
+ }
+ // do sortbottom rows only
+ for (i=0;i<newRows.length;i++) {
+ if (newRows[i].className && (newRows[i].className.indexOf('sortbottom') != -1)) {
+ table.tBodies[0].appendChild(newRows[i]);
+ }
+ }
+
+ // Delete any other arrows there may be showing
+ var allspans = document.getElementsByTagName("span");
+ for (var ci=0;ci<allspans.length;ci++) {
+ if (allspans[ci].className == 'sortarrow') {
+ if (getParent(allspans[ci],"table") == getParent(lnk,"table")) { // in the same table as us?
+ allspans[ci].innerHTML = '&nbsp;&nbsp;&nbsp;';
+ }
+ }
+ }
+
+ span.innerHTML = ARROW;
+}
+
+function getParent(el, pTagName) {
+ if (el == null) return null;
+ else if (el.nodeType == 1 && el.tagName.toLowerCase() == pTagName.toLowerCase()) // Gecko bug, supposed to be uppercase
+ return el;
+ else
+ return getParent(el.parentNode, pTagName);
+}
+function ts_sort_date(a,b) {
+ // y2k notes: two digit years less than 50 are treated as 20XX, greater than 50 are treated as 19XX
+ aa = ts_getInnerText(a.cells[SORT_COLUMN_INDEX]);
+ bb = ts_getInnerText(b.cells[SORT_COLUMN_INDEX]);
+ if (aa.length == 10) {
+ dt1 = aa.substr(6,4)+aa.substr(3,2)+aa.substr(0,2);
+ } else {
+ yr = aa.substr(6,2);
+ if (parseInt(yr) < 50) { yr = '20'+yr; } else { yr = '19'+yr; }
+ dt1 = yr+aa.substr(3,2)+aa.substr(0,2);
+ }
+ if (bb.length == 10) {
+ dt2 = bb.substr(6,4)+bb.substr(3,2)+bb.substr(0,2);
+ } else {
+ yr = bb.substr(6,2);
+ if (parseInt(yr) < 50) { yr = '20'+yr; } else { yr = '19'+yr; }
+ dt2 = yr+bb.substr(3,2)+bb.substr(0,2);
+ }
+ if (dt1==dt2) return 0;
+ if (dt1<dt2) return -1;
+ return 1;
+}
+
+function ts_sort_currency(a,b) {
+ aa = ts_getInnerText(a.cells[SORT_COLUMN_INDEX]).replace(/[^0-9.]/g,'');
+ bb = ts_getInnerText(b.cells[SORT_COLUMN_INDEX]).replace(/[^0-9.]/g,'');
+ return parseFloat(aa) - parseFloat(bb);
+}
+
+function ts_sort_numeric(a,b) {
+ aa = parseFloat(ts_getInnerText(a.cells[SORT_COLUMN_INDEX]));
+ if (isNaN(aa)) aa = 0;
+ bb = parseFloat(ts_getInnerText(b.cells[SORT_COLUMN_INDEX]));
+ if (isNaN(bb)) bb = 0;
+ return aa-bb;
+}
+
+function ts_sort_caseinsensitive(a,b) {
+ aa = ts_getInnerText(a.cells[SORT_COLUMN_INDEX]).toLowerCase();
+ bb = ts_getInnerText(b.cells[SORT_COLUMN_INDEX]).toLowerCase();
+ if (aa==bb) return 0;
+ if (aa<bb) return -1;
+ return 1;
+}
+
+function ts_sort_default(a,b) {
+ aa = ts_getInnerText(a.cells[SORT_COLUMN_INDEX]);
+ bb = ts_getInnerText(b.cells[SORT_COLUMN_INDEX]);
+ if (aa==bb) return 0;
+ if (aa<bb) return -1;
+ return 1;
+}
+
+
+function addEvent(elm, evType, fn, useCapture)
+// addEvent and removeEvent
+// cross-browser event handling for IE5+, NS6 and Mozilla
+// By Scott Andrew
+{
+ if (elm.addEventListener){
+ elm.addEventListener(evType, fn, useCapture);
+ return true;
+ } else if (elm.attachEvent){
+ var r = elm.attachEvent("on"+evType, fn);
+ return r;
+ } else {
+ alert("Handler could not be removed");
+ }
+}
+
+
+
+
+if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
+if (typeof(Clipperz.Profile) == 'undefined') { Clipperz.Profile = {}; }
+
+Clipperz.Profile.VERSION = "0.1";
+Clipperz.Profile.NAME = "Clipperz.Profile";
+
+MochiKit.Base.update(Clipperz.Profile, {
+
+ //-------------------------------------------------------------------------
+
+ '__repr__': function () {
+ var status;
+
+ if (Clipperz.Profile.isEnabled == true) {
+ status = ENABLED;
+ } else {
+ status = DISABLED;
+ }
+
+ return "[" + this.NAME + " " + this.VERSION + " - " + status + "]";
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'toString': function () {
+ return this.__repr__();
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'isEnabled': function() {
+ return false;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'initialValues': function() {
+ return {iters:0, total:0, min:Number.MAX_VALUE, max:0}
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'start': function(aName) {},
+ 'stop': function(aName) {},
+ 'dump': function(aName) {},
+ 'profileData': function(aName, aKey) {
+ var result;
+
+ if (typeof(aName) != 'undefined') {
+ result = this.initialValues();
+
+ if (typeof(aKey) != 'undefined') {
+ result = result[aKey];
+ }
+ } else {
+ result = null;
+ }
+
+ return result;
+
+ },
+ 'resetProfileData': function() {},
+ //-------------------------------------------------------------------------
+
+ 'end': function(aName) {
+ Clipperz.Profile.stop(aName);
+ },
+
+ //-------------------------------------------------------------------------
+
+ __syntaxFix__: "syntax fix"
+});
+
+
+
+if ((typeof(clipperz_profiling_enabled) != 'undefined') && (clipperz_profiling_enabled == true)) {
+
+var _clipperz_profile_profiles = {};
+var _clipperz_profile_pns = [];
+
+
+MochiKit.Base.update(Clipperz.Profile, {
+
+ //-------------------------------------------------------------------------
+
+ 'isEnabled': function() {
+ return true;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'start': function(aName) {
+ if (!_clipperz_profile_profiles[aName]) {
+ _clipperz_profile_profiles[aName] = this.initialValues();
+ _clipperz_profile_pns[_clipperz_profile_pns.length] = aName;
+ } else {
+ if (_clipperz_profile_profiles[aName]["start"]) {
+ Clipperz.Profile.stop(aName);
+ }
+ }
+
+ _clipperz_profile_profiles[aName].end = null;
+ _clipperz_profile_profiles[aName].start = new Date();
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'stop': function(aName) {
+ if ((_clipperz_profile_profiles[aName]) && (_clipperz_profile_profiles[aName]["start"])) {
+ with(_clipperz_profile_profiles[aName]) {
+ var now;
+ var elapsedTime;
+
+ now = new Date();
+ elapsedTime = (now - start);
+
+ end = now;
+ min = Math.min(min, elapsedTime);
+ max = Math.max(max, elapsedTime);
+ total += elapsedTime;
+ start = null;
+ iters++;
+ }
+ } else {
+ // oops! bad call to end(), what should we do here?
+ return true;
+ }
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'dump': function(appendToDoc) {
+// var tbl = document.createElement("table");
+ var tbl = MochiKit.DOM.TABLE(null, MochiKit.DOM.TBODY());
+ tbl.className = 'sortable';
+ tbl.id = "profileOutputTable_table";
+ with(tbl.style){
+ border = "1px solid black";
+ borderCollapse = "collapse";
+ }
+ var hdr = tbl.createTHead();
+ var hdrtr = hdr.insertRow(0);
+ // document.createElement("tr");
+ var cols = ["Identifier","#","Min", "Avg","Max","Total"];
+ for(var x=0; x<cols.length; x++){
+ var ntd = hdrtr.insertCell(x);
+ with(ntd.style){
+ backgroundColor = "#225d94";
+ color = "white";
+ borderBottom = "1px solid black";
+ borderRight = "1px solid black";
+ fontFamily = "tahoma";
+ fontWeight = "bolder";
+ paddingLeft = paddingRight = "5px";
+ }
+ ntd.appendChild(document.createTextNode(cols[x]));
+ }
+
+ for(var x=0; x < _clipperz_profile_pns.length; x++){
+ var prf = _clipperz_profile_profiles[_clipperz_profile_pns[x]];
+ this.end(_clipperz_profile_pns[x]);
+ if(prf.iters>0){
+ var bdytr = tbl.insertRow(true);
+ var vals = [_clipperz_profile_pns[x], prf.iters, prf.min, parseInt(Math.round(prf.total/prf.iters)), prf.max, prf.total];
+ for(var y=0; y<vals.length; y++){
+ var cc = bdytr.insertCell(y);
+ cc.appendChild(document.createTextNode(vals[y]));
+ with(cc.style){
+ borderBottom = "1px solid gray";
+ paddingLeft = paddingRight = "5px";
+ if(x%2){
+ backgroundColor = "#e1f1ff";
+ }
+ if(y>0){
+ textAlign = "right";
+ borderRight = "1px solid gray";
+ }else{
+ borderRight = "1px solid black";
+ }
+ }
+ }
+ }
+ }
+
+ if(appendToDoc){
+ var ne = document.createElement("div");
+ ne.id = "profileOutputTable";
+ with(ne.style){
+ fontFamily = "Courier New, monospace";
+ fontSize = "12px";
+ lineHeight = "16px";
+ borderTop = "1px solid black";
+ padding = "10px";
+ }
+ if(document.getElementById("profileOutputTable")){
+ MochiKit.DOM.swapDOM("profileOutputTable", ne);
+ }else{
+ document.body.appendChild(ne);
+ }
+ ne.appendChild(tbl);
+ }
+
+ return tbl;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'profileData': function(aName, aKey) {
+ var result;
+
+ if (typeof(aName) == 'undefined') {
+ result = _clipperz_profile_profiles;
+ } else {
+ if (typeof(_clipperz_profile_profiles[aName]) != 'undefined') {
+ result = _clipperz_profile_profiles[aName];
+ } else {
+ result = {};
+ }
+ }
+
+ if (typeof(aKey) != 'undefined') {
+ if (aKey == "average") {
+ result = Math.round(Clipperz.Profile.profileData(aName, 'total')/Clipperz.Profile.profileData(aName, 'iters'));
+ } else {
+ if (typeof(result[aKey]) != 'undefined') {
+ result = result[aKey];
+ } else {
+ result = 0;
+ }
+ }
+ }
+
+ return result;
+ },
+
+ //-------------------------------------------------------------------------
+
+ 'resetProfileData': function() {
+ _clipperz_profile_profiles = {};
+ _clipperz_profile_pns = [];
+ },
+
+ //-------------------------------------------------------------------------
+
+ __syntaxFix__: "syntax fix"
+});
+
+}
diff --git a/frontend/beta/js/Clipperz/Set.js b/frontend/beta/js/Clipperz/Set.js
new file mode 100644
index 0000000..61e0769
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/Set.js
@@ -0,0 +1,167 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. 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"
+
+ //-------------------------------------------------------------------------
+});
+
diff --git a/frontend/beta/js/Clipperz/Signal.js b/frontend/beta/js/Clipperz/Signal.js
new file mode 100644
index 0000000..1d3c9eb
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/Signal.js
@@ -0,0 +1,71 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. 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"
+
+});
+
+
+
diff --git a/frontend/beta/js/Clipperz/Style.js b/frontend/beta/js/Clipperz/Style.js
new file mode 100644
index 0000000..9762b1c
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/Style.js
@@ -0,0 +1,73 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. 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.ext.Element.get(tbodyRows[i]);
+ element.addClass(((i%2 == 0) ? "zebra_odd": "zebra_even"));
+ element.removeClass(((i%2 == 1) ? "zebra_odd": "zebra_even"));
+ }
+ },
+
+ //-------------------------------------------------------------------------
+ __syntaxFix__: "syntax fix"
+
+});
+
diff --git a/frontend/beta/js/Clipperz/YUI/Collapser.js b/frontend/beta/js/Clipperz/YUI/Collapser.js
new file mode 100644
index 0000000..5c0ac0f
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/YUI/Collapser.js
@@ -0,0 +1,73 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
+if (typeof(Clipperz.YUI) == 'undefined') { Clipperz.YUI = {}; }
+
+// found on YUI-EXT forum (http://www.yui-ext.com/forum/viewtopic.php?t=683&highlight=accordion)
+Clipperz.YUI.Collapser = function(clickEl, collapseEl, initiallyCollapsed) {
+ this.clickEl = getEl(clickEl);
+ this.collapseEl = getEl(collapseEl);
+ this.clickEl.addClass('collapser-expanded');
+ if (initiallyCollapsed == true) {
+ this.afterCollapse();
+ }
+ this.clickEl.mon('click', function(){
+ this.collapsed === true ? this.expand() : this.collapse();
+ }, this, true);
+};
+
+Clipperz.YUI.Collapser.prototype = {
+ 'collapse': function(){
+ this.collapseEl.clip();
+ this.collapseEl.setHeight(1, true, .35, this.afterCollapse.createDelegate(this), YAHOO.util.Easing.easeOut);
+ this.clickEl.replaceClass('collapser-expanded','collapser-collapsed');
+ },
+
+ 'afterCollapse': function(){
+ this.collapsed = true;
+ this.collapseEl.setDisplayed(false);
+ this.clickEl.replaceClass('collapser-expanded','collapser-collapsed');
+ },
+
+ 'expand': function(){
+ this.collapseEl.setDisplayed(true);
+ this.collapseEl.autoHeight(true, .35, this.afterExpand.createDelegate(this), YAHOO.util.Easing.easeOut);
+ this.clickEl.replaceClass('collapser-collapsed','collapser-expanded');
+ },
+
+ 'afterExpand': function(){
+ this.collapsed = false;
+ this.collapseEl.unclip();
+ this.collapseEl.setStyle('height', '');
+ this.clickEl.replaceClass('collapser-collapsed','collapser-expanded');
+ },
+
+ //-----------------------------------------------------
+ __syntaxFix__: '__syntaxFix__'
+};
diff --git a/frontend/beta/js/Clipperz/YUI/DomHelper.js b/frontend/beta/js/Clipperz/YUI/DomHelper.js
new file mode 100644
index 0000000..4f8acde
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/YUI/DomHelper.js
@@ -0,0 +1,465 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
+if (typeof(Clipperz.ext) == 'undefined') { Clipperz.ext = {}; }
+
+/**
+ * @class Clipperz.YUI.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;
+ }
+
+ 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 node;
+ if(tag == 'table' || tag == 'tbody'){
+ tempTableEl.innerHTML = '<table><tbody>'+html+'</tbody></table>';
+ node = tempTableEl.firstChild.firstChild.firstChild;
+ }else{
+ tempTableEl.innerHTML = '<table><tbody><tr>'+html+'</tr></tbody></table>';
+ node = tempTableEl.firstChild.firstChild.firstChild.firstChild;
+ }
+ if(where == 'beforebegin'){
+ el.parentNode.insertBefore(node, el);
+ return node;
+ }else if(where == 'afterbegin'){
+ el.insertBefore(node, el.firstChild);
+ return node;
+ }else if(where == 'beforeend'){
+ el.appendChild(node);
+ return node;
+ }else if(where == 'afterend'){
+ el.parentNode.insertBefore(node, el.nextSibling);
+ return node;
+ }
+ }
+
+ /**
+ * 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){
+ 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.ext.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.ext.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.ext.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.ext.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.ext.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.ext.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.ext.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.ext.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 YAHOO.ext.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.ext.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.ext.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.ext.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.ext.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.ext.Element
+ * @return {HTMLElement} The new node
+ */
+ append : function(el, values, returnElement){
+ var sanitizedValues;
+ var key;
+
+// sanitizedValues = MochiKit.Base.map(sanitizedValues)
+//console.log("values", values);
+ sanitizedValues = {};
+ for (key in values) {
+ sanitizedValues[key] = Clipperz.Base.sanitizeString(values[key]);
+ }
+//console.log("sanitizedValues", sanitizedValues);
+ el = el.dom ? el.dom : YAHOO.util.Dom.get(el);
+ var newNode = Clipperz.YUI.DomHelper.insertHtml('beforeEnd', el, this.applyTemplate(sanitizedValues));
+ return returnElement ? YAHOO.ext.Element.get(newNode, true) : 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.ext.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.ext.Element.get(newNode, true) : newNode;
+ }
+};
+/**
+ * Alias for applyTemplate
+ * @method
+ */
+Clipperz.YUI.DomHelper.Template.prototype.apply = Clipperz.YUI.DomHelper.Template.prototype.applyTemplate;
+
+YAHOO.ext.Template = Clipperz.YUI.DomHelper.Template;
diff --git a/frontend/beta/js/Clipperz/YUI/DomQuery.js b/frontend/beta/js/Clipperz/YUI/DomQuery.js
new file mode 100644
index 0000000..84aac08
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/YUI/DomQuery.js
@@ -0,0 +1,710 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+/*
+ * yui-ext 0.40
+ * Copyright(c) 2006, Jack Slocum.
+ */
+
+/**
+ * @class Ext.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
+ */
+Ext.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 = Ext.DomQuery.operators[op];
+ for(var i = 0, l = cs.length; i < l; i++){
+ var a;
+ if(st){
+ a = Ext.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 Ext.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 = Ext.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] = Ext.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 Ext.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] = Ext.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 = Ext.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 = Ext.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] = Ext.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 Ext.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 = Ext.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 = Ext.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 = Ext.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 Ext.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
+ */
+Ext.query = Ext.DomQuery.select;
diff --git a/frontend/beta/js/Clipperz/YUI/Drawer.js b/frontend/beta/js/Clipperz/YUI/Drawer.js
new file mode 100644
index 0000000..394912e
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/YUI/Drawer.js
@@ -0,0 +1,238 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
+if (typeof(Clipperz.YUI) == 'undefined') { Clipperz.YUI = {}; }
+
+
+Clipperz.YUI.Drawer = function(anElement, aRegion) {
+ this._status = 'slideIn';
+
+ this._element = YAHOO.ext.Element.get(anElement);
+ this._region = aRegion || null;
+
+ this._collapsedElement = this.element().getChildrenByClassName("drawer-collapsed")[0];
+ this._contentElement = this.element().getChildrenByClassName("drawer-content")[0];
+
+
+ this._wholeCollapedElement = this.enhanceCollapsedElement();
+ this._wholeCollapedElement.setWidth(this.region().element().getWidth());
+ this._wholeCollapedElement.setHeight(this.region().element().getHeight());
+
+ this._contentWrapper = this.enhanceContentElement();
+ this._contentElementActor = new YAHOO.ext.Actor(this.contentWrapper().dom);
+ this.contentElementActor().hide();
+
+ this._contentWidth = 200;
+};
+
+YAHOO.extendX(Clipperz.YUI.Drawer, YAHOO.ext.util.Observable, {
+
+ 'element': function() {
+ return this._element;
+ },
+
+ //-----------------------------------------------------
+
+ 'status': function() {
+ return this._status;
+ },
+
+ 'setStatus': function(aValue) {
+ this._status = aValue;
+ },
+
+ //-----------------------------------------------------
+
+ 'collapsedElement': function() {
+ return this._collapsedElement;
+ },
+
+ //-----------------------------------------------------
+
+ 'contentElement': function() {
+ return this._contentElement;
+ },
+
+ //-----------------------------------------------------
+
+ 'contentElementActor': function() {
+ return this._contentElementActor;
+ },
+
+ //-----------------------------------------------------
+
+ 'contentWrapper': function() {
+ return this._contentWrapper;
+ },
+
+ //-----------------------------------------------------
+
+ 'contentWidth': function() {
+ return this._contentWidth;
+ },
+
+ //-----------------------------------------------------
+
+ 'region': function() {
+ return this._region;
+ },
+
+ //-----------------------------------------------------
+
+ 'enhanceCollapsedElement': function() {
+ var wrapper;
+ var link;
+
+ wrapper = this.collapsedElement().wrap({tag:'div', cls:'drawer-collapsedElement-wrapper', children:[
+ {tag:'div', cls:'drawer-pin-button', children:[
+ {tag:'a', cls:'drawer-pin-button', href:"#", children:[
+ {tag:'img', src:'./images/directLogins/drawer/mm-expand.gif'}
+ ]}
+ ]}
+ ]});
+
+ link = wrapper.getChildrenByClassName('drawer-pin-button', 'a')[0];
+ MochiKit.Signal.connect(link.dom, 'onclick', this, 'pinDrawer');
+
+ this.collapsedElement().setHeight('100%');
+ this.collapsedElement().setStyle('cursor', 'pointer');
+ MochiKit.Signal.connect(this.collapsedElement().dom, 'onclick', this, 'showDrawer');
+
+ return wrapper;
+ },
+
+ //-----------------------------------------------------
+
+ 'enhanceContentElement': function() {
+ var wrapper;
+
+ wrapper = this.contentElement().wrap({tag:'div', cls:'drawer-content-wrapper', children:[
+ {tag:'div', cls:'drawer-content-header', html:'direct login', style:'width:100%;'}
+ ]});
+
+ MochiKit.Signal.connect(wrapper.dom, 'onclick', this, 'hideDrawer');
+ return wrapper;
+ },
+
+ //-----------------------------------------------------
+
+ 'pinDrawer': function() {
+ alert("pin drawer");
+ },
+
+ //-----------------------------------------------------
+
+ 'showDrawer': function() {
+ if (this.status() == 'slideIn') {
+ var actor;
+
+ this.setStatus('slidingOut');
+ actor = this.contentElementActor();
+ actor.setHeight(this.region().element().getHeight());
+
+ actor.startCapture(true);
+ actor.alignTo(this.element(), 'tr');
+ actor.blindShow('left', this.contentWidth(), .35);
+ actor.play(this.onSlideOut.createDelegate(this));
+ }
+ },
+
+ //-----------------------------------------------------
+
+ 'onSlideOut': function() {
+ this.setStatus('slideOut');
+MochiKit.Logging.logDebug(">>> onSlideOut");
+// alert("done");
+ },
+
+ //-----------------------------------------------------
+/*
+ 'showContentElement': function() {
+ var top, left, width, height;
+
+MochiKit.Logging.logDebug(">>> showContentElement");
+
+
+ top = this.element().getTop(true);
+ left = this.element().getRight();
+ width = this.contentWidth();
+ height = this.element().getHeight();
+
+ this.contentWrapper().setStyle('position', 'absolute');
+ this.contentWrapper().setStyle('overflow', 'none');
+ this.contentWrapper().setStyle('visibility', 'visible');
+ this.contentWrapper().setStyle('z-index', '10');
+
+ this.contentWrapper().setLeft(left);
+ this.contentWrapper().setTop(top);
+ this.contentWrapper().setHeight(height);
+ this.contentWrapper().setWidth(width);
+
+ this.contentWrapper().show();
+ },
+*/
+ //-----------------------------------------------------
+
+ 'hideDrawer': function() {
+ if (this.status() == 'slideOut') {
+ var actor;
+
+ this.setStatus('slidingIn');
+
+ actor = this.contentElementActor();
+ actor.setHeight(this.region().element().getHeight());
+
+ actor.startCapture(true);
+ actor.alignTo(this.element(), 'tr');
+ actor.blindHide('left', .35);
+ actor.setVisible(false);
+ actor.play(this.onSlideIn.createDelegate(this));
+ }
+ },
+
+ //-----------------------------------------------------
+
+ 'onSlideIn': function() {
+ this.setStatus('slideIn');
+MochiKit.Logging.logDebug(">>> onSlideIn");
+// alert("done");
+ },
+
+ //-----------------------------------------------------
+
+ 'hideContentElement': function() {
+ this.contentWrapper().hide();
+ },
+
+ //-----------------------------------------------------
+ //-----------------------------------------------------
+
+ //-----------------------------------------------------
+ __syntaxFix__: '__syntaxFix__'
+}); \ No newline at end of file
diff --git a/frontend/beta/js/Clipperz/YUI/IBLayoutManager.js b/frontend/beta/js/Clipperz/YUI/IBLayoutManager.js
new file mode 100644
index 0000000..626b699
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/YUI/IBLayoutManager.js
@@ -0,0 +1,114 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
+if (typeof(Clipperz.YUI) == 'undefined') { Clipperz.YUI = {}; }
+
+
+Clipperz.YUI.IBLayoutManager = function(container, config) {
+ var regionName;
+ var element;
+
+ config = config || {};
+
+ Clipperz.YUI.IBLayoutManager.superclass.constructor.call(this, container);
+ this.hideOnLayout = config.hideOnLayout || false;
+
+ element = YAHOO.ext.Element.get(container);
+ element.setStyle('position', 'absolute');
+ element.setStyle('overflow', 'hidden');
+
+ for (regionName in config.regions) {
+ var newRegion;
+
+ newRegion = new new Clipperz.YUI.IBLayoutRegion(this, regionName, config.regions[regionName]);
+ this.addRegion(regionName, newRegion);
+ }
+
+ this.layout();
+};
+
+YAHOO.extendX(Clipperz.YUI.IBLayoutManager, YAHOO.ext.LayoutManager, {
+
+ 'toString': function() {
+ return "IBLayoutManager (" + this.el.id + ")";
+ },
+
+ //-----------------------------------------------------
+
+ 'add': function(aName, aPanel) {
+ var regionName;
+
+ regionName = aName.toLowerCase();
+ return this.regions[regionName].add(aPanel);
+ },
+
+ //-----------------------------------------------------
+
+ 'addRegion': function(aRegion) {
+ var regionName;
+
+ regionName = aRegion.name().toLowerCase();
+ if (!this.regions[regionName]) {
+//MochiKit.Logging.logDebug("--- adding region with name: " + aRegion.name());
+ this.regions[regionName] = aRegion;
+ } else {
+ // ????
+ }
+
+ return aRegion;
+ },
+
+ //-----------------------------------------------------
+
+ 'getRegion': function(target){
+ return this.regions[target.toLowerCase()];
+ },
+
+ //-----------------------------------------------------
+
+ 'layout': function(){
+ var region;
+
+//MochiKit.Logging.logDebug(">>> IBLayoutManager.layout - regions: " + Clipperz.Base.serializeJSON(MochiKit.Base.keys(this.regions)));
+ for (region in this.regions) {
+//MochiKit.Logging.logDebug("--- IBLayoutManager.layout - region: " + region);
+ this.regions[region].layout();
+ }
+//MochiKit.Logging.logDebug("<<< IBLayoutManager.layout");
+ },
+
+ //-----------------------------------------------------
+
+ 'getSize': function() {
+ return this.el.getSize();
+ },
+
+ //-----------------------------------------------------
+ __syntaxFix__: '__syntaxFix__'
+});
diff --git a/frontend/beta/js/Clipperz/YUI/IBLayoutRegion.js b/frontend/beta/js/Clipperz/YUI/IBLayoutRegion.js
new file mode 100644
index 0000000..2fd4377
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/YUI/IBLayoutRegion.js
@@ -0,0 +1,249 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
+if (typeof(Clipperz.YUI) == 'undefined') { Clipperz.YUI = {}; }
+
+
+Clipperz.YUI.IBLayoutRegion = function(aManager, aName, aConfig) {
+ this._configuration = aConfig;
+
+// Clipperz.YUI.IBLayoutRegion.superclass.constructor.call();
+ Clipperz.YUI.IBLayoutRegion.superclass.constructor.call(this, aManager, aConfig, aName);
+};
+
+YAHOO.extendX(Clipperz.YUI.IBLayoutRegion, YAHOO.ext.LayoutRegion, {
+
+ 'toString': function() {
+ return "IBLayoutRegion (" + this.name() + ")";
+ },
+
+ //-----------------------------------------------------
+
+ 'name': function() {
+ return this.position;
+ },
+
+ //-----------------------------------------------------
+
+ 'manager': function() {
+ return this.mgr;
+ },
+
+ 'configuration': function() {
+ return this._configuration;
+ },
+
+ //-----------------------------------------------------
+
+ 'getAttributeValue': function(anAttribute) {
+ var result;
+
+ switch(anAttribute) {
+ case "top":
+ result = this.element().getTop();
+ break;
+ case "left":
+ result = this.element().getLeft();
+ break;
+ case "bottom":
+ result = this.element().getBottom();
+ break;
+ case "right":
+ result = this.element().getRight();
+ break;
+ case "height":
+ result = this.element().getHeight();
+ break;
+ case "width":
+ result = this.element().getWidth();
+ break;
+ }
+//MochiKit.Logging.logDebug("--- " + this.name() + " [" + anAttribute + "] = " + result);
+
+ return result;
+ },
+
+ //-----------------------------------------------------
+
+ 'normalizeConfigureValue': function(aConfigurationValue) {
+ var result;
+
+//MochiKit.Logging.logDebug("--- normalizeConfigureValue - " + aConfigurationValue);
+ if (typeof(aConfigurationValue) == 'number') {
+ result = aConfigurationValue;
+ } else if (aConfigurationValue == 'auto') {
+ result = aConfigurationValue;
+ } else {
+ var splitValues;
+ var referenceValue;
+ var deltaValue;
+ var targetRegion;
+ var targetAttribute;
+
+ splitValues = aConfigurationValue.split('+');
+ referenceValue = Clipperz.Base.trim(splitValues[0]);
+ deltaValue = Clipperz.Base.trim(splitValues[1] || "");
+
+ splitValues = referenceValue.split('.');
+ targetRegion = splitValues[0];
+ targetAttribute = splitValues[1];
+
+//MochiKit.Logging.logDebug("> " + aConfigurationValue);
+//MochiKit.Logging.logDebug(">> manager: " + this.manager());
+//MochiKit.Logging.logDebug(">> targetRegion: " + targetRegion);
+//MochiKit.Logging.logDebug(">>> " + this.manager().getRegion(targetRegion));
+ targetValue = this.manager().getRegion(targetRegion).getAttributeValue(targetAttribute);
+//MochiKit.Logging.logDebug(">>>> " + targetRegion + "." + targetAttribute + " + " + deltaValue + " = " + targetValue);
+
+ result = targetValue + (deltaValue - 0);
+
+//MochiKit.Logging.logDebug("<<< " + aConfigurationValue + " = " + result);
+ }
+
+ return result;
+ },
+
+ 'normalizedConfiguration': function(aConfiguration) {
+ var result;
+ var key;
+
+ result = {};
+
+//MochiKit.Logging.logDebug("--- normalizedConfiguration - keys: " + Clipperz.Base.serializeJSON(MochiKit.Base.keys(aConfiguration)));
+ for (key in aConfiguration) {
+ if ((key == 'top') || (key == 'bottom') || (key == 'left') || (key == 'rigth') || (key == 'width') || (key == 'height')) {
+ result[key] = this.normalizeConfigureValue(aConfiguration[key]);
+ } else {
+ result[key] = aConfiguration[key];
+ }
+ }
+
+ return result;
+ },
+
+ //-----------------------------------------------------
+
+ 'element': function() {
+ return this.el;
+ },
+
+ //-----------------------------------------------------
+/*
+ 'hide': function() {
+MochiKit.Logging.logDebug(">>> IBLayoutManager.hide()")
+ Clipperz.YUI.IBLayoutRegion.superclass.hide.call(this);
+ },
+*/
+ //-----------------------------------------------------
+/*
+ 'add': function(aPanel) {
+ Clipperz.YUI.IBLayoutRegion.superclass.add.call(this, aPanel);
+ aPanel.el.fitToParent(true);
+ },
+*/
+ //-----------------------------------------------------
+
+ 'updateBox': function(aBox) {
+//MochiKit.Logging.logDebug(">>> IBLayoutRegion.updateBox - " + aBox);
+ Clipperz.YUI.IBLayoutRegion.superclass.updateBox.call(this, aBox);
+ },
+
+ //-----------------------------------------------------
+
+ 'layout': function() {
+ var top, left, bottom, right, width, height;
+ var element;
+ var config;
+ var windowSize;
+ var containerSize;
+
+//MochiKit.Logging.logDebug(">>> IBLayoutRegion.layout - " + this);
+ config = this.normalizedConfiguration(this.configuration());
+ element = this.element();
+// containerSize = this.manager().getSize(true);
+ containerSize = this.manager().getSize(false);
+ windowSize = {width: YAHOO.util.Dom.getViewportWidth(), height: YAHOO.util.Dom.getViewportHeight()};
+
+// element.setStyle("position", "absolute");
+// element.setStyle("overflow", "none");
+
+ if (typeof(config.top) == 'number') {
+ top = config.top;
+
+ if (typeof(config.bottom) == 'number') {
+ height = containerSize.height - top - config.bottom;
+ } else if (typeof(config.height) == 'number') {
+ height = config.height;
+ } else {
+ // ???
+ }
+ } else {
+ if ((typeof(config.bottom) == 'number') && (typeof(config.height) == 'number')) {
+ top = containerSize.height - (config.height + config.bottom);
+ height = config.height;
+ } else if ((config.bottom == 'auto') && (typeof(config.height) == 'number')) {
+ top = ((containerSize.height - config.height) / 2);
+ height = config.height;
+ }
+ }
+
+ if (typeof(config.left) == 'number') {
+ left = config.left;
+
+ if (typeof(config.right) == 'number') {
+ width = (containerSize.width - left - config.right);
+ } else if (typeof(config.width) == 'number') {
+ width = config.width;
+ } else {
+ // ???
+ }
+ } else {
+ if ((typeof(config.right) == 'number') && (typeof(config.width) == 'number')) {
+ left = containerSize.width - (config.width + config.right);
+ width = config.width;
+ } else if ((config.right == 'auto') && (typeof(config.width) == 'number')) {
+ left = ((containerSize.width - config.width) / 2);
+ width = config.width;
+ }
+ }
+//MochiKit.Logging.logDebug("--- setting position (top: " + top + ", left: " + left + ", width: " + width + ", height: " + height + ")");
+ element.setTop(top);
+ element.setLeft(left);
+ element.setWidth(width);
+ element.setHeight(height);
+
+ if (this.activePanel != null) {
+ this.activePanel.setSize(width, height);
+ }
+//MochiKit.Logging.logDebug("<<< IBLayoutRegion.layout");
+ },
+
+ //-----------------------------------------------------
+ __syntaxFix__: '__syntaxFix__'
+});
diff --git a/frontend/beta/js/Clipperz/YUI/MessageBox.js b/frontend/beta/js/Clipperz/YUI/MessageBox.js
new file mode 100644
index 0000000..ec33d7d
--- a/dev/null
+++ b/frontend/beta/js/Clipperz/YUI/MessageBox.js
@@ -0,0 +1,265 @@
+/*
+
+Copyright 2008-2011 Clipperz Srl
+
+This file is part of Clipperz's Javascript Crypto Library.
+Javascript Crypto Library provides web developers with an extensive
+and efficient set of cryptographic functions. The library aims to
+obtain maximum execution speed while preserving modularity and
+reusability.
+For further information about its features and functionalities please
+refer to http://www.clipperz.com
+
+* Javascript Crypto Library 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.
+
+* Javascript Crypto Library 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 Javascript Crypto Library. If not, see
+ <http://www.gnu.org/licenses/>.
+
+*/
+
+Clipperz.YUI.MessageBox = function(){
+ var dlg, opt, mask;
+ var bodyEl, msgEl, textboxEl, textareaEl, progressEl, pp;
+ var buttons, activeTextEl, bwidth;
+
+ var handleButton = function(button){
+ if(typeof opt.fn == 'function'){
+ if(opt.fn.call(opt.scope||window, button, activeTextEl.dom.value) !== false){
+ dlg.hide();
+ }
+ }else{
+ dlg.hide();
+ }
+ };
+
+ return {
+ updateButtons: function(b){
+ var width = 0;
+ if(!b){
+ buttons['ok'].hide();
+ buttons['cancel'].hide();
+ buttons['yes'].hide();
+ buttons['no'].hide();
+ return width;
+ }
+ for(var k in buttons){
+ if(typeof buttons[k] != 'function'){
+ if(b[k]){
+ buttons[k].show();
+ buttons[k].setText(typeof b[k] == 'string' ? b[k] : YAHOO.ext.MessageBox.buttonText[k]);
+ width += buttons[k].el.getWidth()+15;
+ }else{
+ buttons[k].hide();
+ }
+ }
+ }
+ return width;
+ },
+
+ getDialog : function(){
+ if(!dlg){
+ dlg = new YAHOO.ext.BasicDialog('mb-dlg', {
+ autoCreate:true,
+ shadow:true,
+ draggable:true,
+ resizable:false,
+ constraintoviewport:true,
+ fixedcenter:true,
+ shim:true,
+ modal:true,
+ width:400, height:100,
+ buttonAlign:'center',
+ closeClick : function(){
+ if(opt && opt.buttons && opt.buttons.no && !opt.buttons.cancel){
+ handleButton('no');
+ }else{
+ handleButton('cancel');
+ }
+ }
+ });
+ dlg.closeClick = function(){
+ alert('wtf');
+ };
+ mask = dlg.mask;
+ dlg.addKeyListener(27, dlg.hide, dlg);
+ buttons = {};
+ buttons['ok'] = dlg.addButton(this.buttonText['ok'], handleButton.createCallback('ok'));
+ buttons['yes'] = dlg.addButton(this.buttonText['yes'], handleButton.createCallback('yes'));
+ buttons['no'] = dlg.addButton(this.buttonText['no'], handleButton.createCallback('no'));
+ buttons['cancel'] = dlg.addButton(this.buttonText['cancel'], handleButton.createCallback('cancel'));
+ bodyEl = dlg.body.createChild({
+ tag:'div',
+ html:'<span class="ext-mb-text"></span><br /><input type="text" class="ext-mb-input"><textarea class="ext-mb-textarea"></textarea><div class="ext-mb-progress-wrap"><div class="ext-mb-progress"><div class="ext-mb-progress-bar">&#160;</div></div></div>'
+ });
+ msgEl = bodyEl.dom.firstChild;
+ textboxEl = getEl(bodyEl.dom.childNodes[2]);
+ textboxEl.enableDisplayMode();
+ textboxEl.addKeyListener([10,13], function(){
+ if(dlg.isVisible() && opt && opt.buttons){
+ if(opt.buttons.ok){
+ handleButton('ok');
+ }else if(opt.buttons.yes){
+ handleButton('yes');
+ }
+ }
+ });
+ textareaEl = getEl(bodyEl.dom.childNodes[3]);
+ textareaEl.enableDisplayMode();
+ progressEl = getEl(bodyEl.dom.childNodes[4]);
+ progressEl.enableDisplayMode();
+ pp = getEl(progressEl.dom.firstChild.firstChild);
+ }
+ return dlg;
+ },
+
+ updateText : function(text){
+ if(!dlg.isVisible() && !opt.width){
+ dlg.resizeTo(this.maxWidth, 100); // resize first so content is never clipped from previous shows
+ }
+ msgEl.innerHTML = text;
+ var w = Math.max(Math.min(opt.width || msgEl.offsetWidth, this.maxWidth),
+ Math.max(opt.minWidth || this.minWidth, bwidth));
+ if(opt.prompt){
+ activeTextEl.setWidth(w);
+ }
+ dlg.setContentSize(w, bodyEl.getHeight());
+ },
+
+ updateProgress : function(value, text){
+ if(text){
+ this.updateText(text);
+ }
+ pp.setWidth(value*progressEl.dom.firstChild.offsetWidth);
+ },
+
+ isVisible : function(){
+ return dlg && dlg.isVisible();
+ },
+
+ hide : function(){
+ if(this.isVisible()){
+ dlg.hide();
+ }
+ },
+
+ show : function(options){
+ var d = this.getDialog();
+ opt = options;
+ d.setTitle(opt.title || '&#160;');
+ d.close.setDisplayed(opt.closable !== false);
+ activeTextEl = textboxEl;
+ opt.prompt = opt.prompt || (opt.multiline ? true : false)
+ if(opt.prompt){
+ if(opt.multiline){
+ textboxEl.hide();
+ textareaEl.show();
+ textareaEl.setHeight(typeof opt.multiline == 'number' ?
+ opt.multiline : this.defaultTextHeight);
+ activeTextEl = textareaEl;
+ }else{
+ textboxEl.show();
+ textareaEl.hide();
+ }
+ }else{
+ textboxEl.hide();
+ textareaEl.hide();
+ }
+ progressEl.setDisplayed(opt.progress === true);
+ this.updateProgress(0);
+ activeTextEl.dom.value = opt.value || '';
+ if(opt.prompt){
+ dlg.setDefaultButton(activeTextEl);
+ }else{
+ var bs = opt.buttons;
+ var db = null;
+ if(bs && bs.ok){
+ db = buttons['ok'];
+ }else if(bs && bs.yes){
+ db = buttons['yes'];
+ }
+ dlg.setDefaultButton(db);
+ }
+ bwidth = this.updateButtons(opt.buttons);
+ this.updateText(opt.msg);
+ d.modal = opt.modal !== false;
+ d.mask = opt.modal !== false ? mask : false;
+ d.animateTarget = null;
+ d.show(options.animEl);
+ },
+
+ progress : function(title, msg){
+ this.show({
+ title : title,
+ msg : msg,
+ buttons: false,
+ progress:true,
+ closable:false
+ });
+ },
+
+ progressElement : function() {
+ return progressEl;
+ },
+
+ opt: function() {
+ return opt;
+ },
+
+ alert : function(title, msg, fn, scope){
+ this.show({
+ title : title,
+ msg : msg,
+ buttons: this.OK,
+ fn: fn,
+ scope : scope
+ });
+ },
+
+ confirm : function(title, msg, fn, scope){
+ this.show({
+ title : title,
+ msg : msg,
+ buttons: this.YESNO,
+ fn: fn,
+ scope : scope
+ });
+ },
+
+ prompt : function(title, msg, fn, scope, multiline){
+ this.show({
+ title : title,
+ msg : msg,
+ buttons: this.OKCANCEL,
+ fn: fn,
+ minWidth:250,
+ scope : scope,
+ prompt:true,
+ multiline: multiline
+ });
+ },
+
+ OK : {ok:true},
+ YESNO : {yes:true, no:true},
+ OKCANCEL : {ok:true, cancel:true},
+ YESNOCANCEL : {yes:true, no:true, cancel:true},
+
+ defaultTextHeight:75,
+ maxWidth : 500,
+ minWidth : 100,
+ buttonText : {
+ ok : 'OK',
+ cancel : 'Cancel',
+ yes : 'Yes',
+ no : 'No'
+ }
+ };
+}();