author | Giulio Cesare Solaroli <giulio.cesare@clipperz.com> | 2011-10-02 23:56:18 (UTC) |
---|---|---|
committer | Giulio Cesare Solaroli <giulio.cesare@clipperz.com> | 2011-10-02 23:56:18 (UTC) |
commit | ef68436ac04da078ffdcacd7e1f785473a303d45 (patch) (side-by-side diff) | |
tree | c403752d66a2c4775f00affd4fa8431b29c5b68c /frontend/beta/js/Clipperz/PM/DataModel | |
parent | 597ecfbc0249d83e1b856cbd558340c01237a360 (diff) | |
download | clipperz-ef68436ac04da078ffdcacd7e1f785473a303d45.zip clipperz-ef68436ac04da078ffdcacd7e1f785473a303d45.tar.gz clipperz-ef68436ac04da078ffdcacd7e1f785473a303d45.tar.bz2 |
First version of the newly restructured repository
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.js | 536 | ||||
-rw-r--r-- | frontend/beta/js/Clipperz/PM/DataModel/DirectLoginBinding.js | 113 | ||||
-rw-r--r-- | frontend/beta/js/Clipperz/PM/DataModel/DirectLoginInput.js | 229 | ||||
-rw-r--r-- | frontend/beta/js/Clipperz/PM/DataModel/DirectLoginReference.js | 192 | ||||
-rw-r--r-- | frontend/beta/js/Clipperz/PM/DataModel/Header.js | 751 | ||||
-rw-r--r-- | frontend/beta/js/Clipperz/PM/DataModel/OneTimePassword.js | 333 | ||||
-rw-r--r-- | frontend/beta/js/Clipperz/PM/DataModel/OneTimePasswordManager.js | 280 | ||||
-rw-r--r-- | frontend/beta/js/Clipperz/PM/DataModel/Record.js | 759 | ||||
-rw-r--r-- | frontend/beta/js/Clipperz/PM/DataModel/RecordField.js | 220 | ||||
-rw-r--r-- | frontend/beta/js/Clipperz/PM/DataModel/RecordVersion.js | 535 | ||||
-rw-r--r-- | frontend/beta/js/Clipperz/PM/DataModel/Statistics.js | 133 | ||||
-rw-r--r-- | frontend/beta/js/Clipperz/PM/DataModel/User.js | 904 | ||||
-rw-r--r-- | frontend/beta/js/Clipperz/PM/DataModel/UserPreferences.js | 197 |
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" +}); + |