summaryrefslogtreecommitdiff
path: root/frontend/beta/js/Clipperz/PM/DataModel
Side-by-side diff
Diffstat (limited to 'frontend/beta/js/Clipperz/PM/DataModel') (more/less context) (ignore whitespace changes)
-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
13 files changed, 5182 insertions, 0 deletions
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"
+});
+