2015-10-17 23:49:24 +02:00
|
|
|
'use strict';
|
|
|
|
|
2015-10-18 16:02:00 +02:00
|
|
|
var Backbone = require('backbone'),
|
2015-10-24 21:06:44 +02:00
|
|
|
AppSettingsModel = require('../../models/app-settings-model'),
|
2015-10-18 16:02:00 +02:00
|
|
|
FeatureDetector = require('../../util/feature-detector'),
|
2015-10-25 10:44:19 +01:00
|
|
|
PasswordGenerator = require('../../util/password-generator'),
|
|
|
|
Alerts = require('../../comp/alerts'),
|
|
|
|
RuntimeInfo = require('../../comp/runtime-info'),
|
|
|
|
Launcher = require('../../comp/launcher'),
|
2015-10-23 23:21:21 +02:00
|
|
|
Links = require('../../const/links'),
|
2015-10-24 18:43:30 +02:00
|
|
|
kdbxweb = require('kdbxweb'),
|
2015-10-18 16:02:00 +02:00
|
|
|
FileSaver = require('filesaver');
|
2015-10-17 23:49:24 +02:00
|
|
|
|
|
|
|
var SettingsAboutView = Backbone.View.extend({
|
|
|
|
template: require('templates/settings/settings-file.html'),
|
|
|
|
|
2015-10-18 16:02:00 +02:00
|
|
|
events: {
|
|
|
|
'click .settings__file-button-save-file': 'saveToFile',
|
|
|
|
'click .settings__file-button-export-xml': 'exportAsXml',
|
2015-10-22 20:03:44 +02:00
|
|
|
'click .settings__file-button-save-dropbox': 'saveToDropbox',
|
2015-10-24 18:43:30 +02:00
|
|
|
'change #settings__file-key-file': 'keyFileChange',
|
|
|
|
'mousedown #settings__file-file-select-link': 'triggerSelectFile',
|
|
|
|
'change #settings__file-file-select': 'fileSelected',
|
2015-10-22 22:51:40 +02:00
|
|
|
'focus #settings__file-master-pass': 'focusMasterPass',
|
2015-10-24 18:43:30 +02:00
|
|
|
'blur #settings__file-master-pass': 'blurMasterPass',
|
|
|
|
'blur #settings__file-name': 'blurName',
|
|
|
|
'blur #settings__file-def-user': 'blurDefUser',
|
|
|
|
'change #settings__file-trash': 'changeTrash',
|
|
|
|
'blur #settings__file-hist-len': 'blurHistoryLength',
|
|
|
|
'blur #settings__file-hist-size': 'blurHistorySize',
|
|
|
|
'blur #settings__file-key-rounds': 'blurKeyRounds'
|
2015-10-18 16:02:00 +02:00
|
|
|
},
|
|
|
|
|
2015-10-23 22:12:12 +02:00
|
|
|
initialize: function() {
|
|
|
|
},
|
|
|
|
|
2015-10-17 23:49:24 +02:00
|
|
|
render: function() {
|
2015-10-18 16:02:00 +02:00
|
|
|
this.renderTemplate({
|
2015-10-22 22:39:30 +02:00
|
|
|
cmd: FeatureDetector.actionShortcutSymbol(true),
|
2015-10-23 22:12:12 +02:00
|
|
|
supportFiles: RuntimeInfo.launcher,
|
2015-10-23 23:21:21 +02:00
|
|
|
desktopLink: Links.Desktop,
|
2015-10-23 22:12:12 +02:00
|
|
|
|
2015-10-22 22:39:30 +02:00
|
|
|
name: this.model.get('name'),
|
2015-10-23 22:12:12 +02:00
|
|
|
path: this.model.get('path'),
|
2015-10-25 10:44:19 +01:00
|
|
|
password: PasswordGenerator.present(this.model.get('passwordLength')),
|
2015-10-22 22:39:30 +02:00
|
|
|
defaultUser: this.model.get('defaultUser'),
|
|
|
|
recycleBinEnabled: this.model.get('recycleBinEnabled'),
|
|
|
|
historyMaxItems: this.model.get('historyMaxItems'),
|
|
|
|
historyMaxSize: Math.round(this.model.get('historyMaxSize') / 1024 / 1024),
|
|
|
|
keyEncryptionRounds: this.model.get('keyEncryptionRounds')
|
2015-10-18 16:02:00 +02:00
|
|
|
});
|
2015-10-24 18:43:30 +02:00
|
|
|
if (!this.model.get('created')) {
|
|
|
|
this.$el.find('.settings__file-master-pass-warning').toggle(this.model.get('passwordChanged'));
|
|
|
|
}
|
|
|
|
this.renderKeyFileSelect();
|
|
|
|
},
|
|
|
|
|
|
|
|
renderKeyFileSelect: function() {
|
|
|
|
var keyFileName = this.model.get('keyFileName'),
|
|
|
|
oldKeyFileName = this.model.get('oldKeyFileName'),
|
|
|
|
keyFileChanged = this.model.get('keyFileChanged');
|
|
|
|
var sel = this.$el.find('#settings__file-key-file');
|
|
|
|
sel.html('');
|
|
|
|
if (keyFileName && keyFileChanged) {
|
|
|
|
var text = keyFileName !== 'Generated' ? 'Use key file ' + keyFileName : 'Use generated key file';
|
|
|
|
$('<option/>').val('ex').text(text).appendTo(sel);
|
|
|
|
}
|
|
|
|
if (oldKeyFileName) {
|
|
|
|
$('<option/>').val('old').text('Use ' + (keyFileChanged ? 'old ' : '') + 'key file ' + oldKeyFileName).appendTo(sel);
|
|
|
|
}
|
|
|
|
$('<option/>').val('gen').text('Generate new key file').appendTo(sel);
|
|
|
|
$('<option/>').val('none').text('Don\'t use key file').appendTo(sel);
|
|
|
|
if (keyFileName && keyFileChanged) {
|
|
|
|
sel.val('ex');
|
|
|
|
} else if (!keyFileName) {
|
|
|
|
sel.val('none');
|
|
|
|
} else if (oldKeyFileName && keyFileName === oldKeyFileName && !keyFileChanged) {
|
|
|
|
sel.val('old');
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
validate: function() {
|
|
|
|
if (!this.model.get('passwordLength')) {
|
|
|
|
Alerts.error({
|
|
|
|
header: 'Empty password',
|
|
|
|
body: 'Please, enter the password. You will use it the next time you open this file.',
|
|
|
|
complete: (function() {
|
|
|
|
this.$el.find('#settings__file-master-pass').focus();
|
|
|
|
}).bind(this)
|
|
|
|
});
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
2015-10-18 16:02:00 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
saveToFile: function() {
|
2015-10-24 18:43:30 +02:00
|
|
|
if (!this.validate()) {
|
|
|
|
return;
|
|
|
|
}
|
2015-10-18 16:02:00 +02:00
|
|
|
var data = this.model.getData();
|
2015-10-24 21:06:44 +02:00
|
|
|
var fileName = this.model.get('name') + '.kdbx';
|
|
|
|
if (Launcher) {
|
|
|
|
if (this.model.get('path')) {
|
|
|
|
this.saveToFileWithPath(this.model.get('path'), data);
|
|
|
|
} else {
|
|
|
|
Launcher.getSaveFileName(fileName, (function (path) {
|
|
|
|
if (path) {
|
|
|
|
this.saveToFileWithPath(path, data);
|
|
|
|
}
|
|
|
|
}).bind(this));
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
var blob = new Blob([data], {type: 'application/octet-stream'});
|
|
|
|
FileSaver.saveAs(blob, fileName);
|
|
|
|
this.model.saved();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
saveToFileWithPath: function(path, data) {
|
|
|
|
try {
|
|
|
|
Launcher.writeFile(path, data);
|
|
|
|
this.model.saved(path);
|
|
|
|
if (!AppSettingsModel.instance.get('lastOpenFile')) {
|
|
|
|
AppSettingsModel.instance.set('lastOpenFile', path);
|
|
|
|
}
|
|
|
|
} catch (e) {
|
|
|
|
Alerts.error({
|
|
|
|
header: 'Save error',
|
|
|
|
body: 'Error saving to file ' + path + ': \n' + e
|
|
|
|
});
|
|
|
|
}
|
2015-10-18 16:02:00 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
exportAsXml: function() {
|
2015-10-24 18:43:30 +02:00
|
|
|
if (!this.validate()) {
|
|
|
|
return;
|
|
|
|
}
|
2015-10-18 16:02:00 +02:00
|
|
|
var data = this.model.getXml();
|
|
|
|
var blob = new Blob([data], {type: 'text/xml'});
|
|
|
|
FileSaver.saveAs(blob, this.model.get('name') + '.xml');
|
|
|
|
},
|
|
|
|
|
|
|
|
saveToDropbox: function() {
|
2015-10-24 18:43:30 +02:00
|
|
|
if (!this.validate()) {
|
|
|
|
return;
|
|
|
|
}
|
2015-10-18 16:02:00 +02:00
|
|
|
Alerts.notImplemented();
|
2015-10-22 20:03:44 +02:00
|
|
|
},
|
|
|
|
|
2015-10-24 18:43:30 +02:00
|
|
|
keyFileChange: function(e) {
|
2015-10-22 20:03:44 +02:00
|
|
|
switch (e.target.value) {
|
2015-10-24 18:43:30 +02:00
|
|
|
case 'old':
|
|
|
|
this.selectOldKeyFile();
|
2015-10-22 20:03:44 +02:00
|
|
|
break;
|
|
|
|
case 'gen':
|
|
|
|
this.generateKeyFile();
|
|
|
|
break;
|
2015-10-24 18:43:30 +02:00
|
|
|
case 'none':
|
2015-10-22 20:03:44 +02:00
|
|
|
this.clearKeyFile();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2015-10-24 18:43:30 +02:00
|
|
|
selectOldKeyFile: function() {
|
|
|
|
this.model.resetKeyFile();
|
|
|
|
this.renderKeyFileSelect();
|
2015-10-22 20:03:44 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
generateKeyFile: function() {
|
2015-10-24 18:43:30 +02:00
|
|
|
var keyFile = this.model.generateAndSetKeyFile();
|
|
|
|
var blob = new Blob([keyFile], {type: 'application/octet-stream'});
|
|
|
|
FileSaver.saveAs(blob, this.model.get('name') + '.key');
|
|
|
|
this.renderKeyFileSelect();
|
2015-10-22 20:03:44 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
clearKeyFile: function() {
|
2015-10-24 18:43:30 +02:00
|
|
|
this.model.removeKeyFile();
|
|
|
|
this.renderKeyFileSelect();
|
|
|
|
},
|
|
|
|
|
|
|
|
triggerSelectFile: function() {
|
|
|
|
this.$el.find('#settings__file-file-select').click();
|
|
|
|
},
|
|
|
|
|
|
|
|
fileSelected: function(e) {
|
|
|
|
var file = e.target.files[0];
|
|
|
|
var reader = new FileReader();
|
|
|
|
reader.onload = (function(e) {
|
|
|
|
var res = e.target.result;
|
|
|
|
this.model.setKeyFile(res, file.name);
|
|
|
|
this.renderKeyFileSelect();
|
|
|
|
}).bind(this);
|
|
|
|
reader.readAsArrayBuffer(file);
|
2015-10-22 22:39:30 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
focusMasterPass: function(e) {
|
2015-10-23 22:12:12 +02:00
|
|
|
if (!this.passwordChanged) {
|
|
|
|
e.target.value = '';
|
|
|
|
}
|
|
|
|
e.target.setAttribute('type', 'text');
|
2015-10-22 22:51:40 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
blurMasterPass: function(e) {
|
|
|
|
if (!e.target.value) {
|
2015-10-23 22:12:12 +02:00
|
|
|
this.passwordChanged = false;
|
2015-10-24 18:43:30 +02:00
|
|
|
this.model.resetPassword();
|
2015-10-25 10:44:19 +01:00
|
|
|
e.target.value = PasswordGenerator.present(this.model.get('passwordLength'));
|
2015-10-24 18:43:30 +02:00
|
|
|
this.$el.find('.settings__file-master-pass-warning').hide();
|
2015-10-23 22:12:12 +02:00
|
|
|
} else {
|
|
|
|
this.passwordChanged = true;
|
2015-10-24 18:43:30 +02:00
|
|
|
this.model.setPassword(kdbxweb.ProtectedValue.fromString(e.target.value));
|
|
|
|
if (!this.model.get('created')) {
|
|
|
|
this.$el.find('.settings__file-master-pass-warning').show();
|
|
|
|
}
|
2015-10-22 22:51:40 +02:00
|
|
|
}
|
2015-10-23 22:12:12 +02:00
|
|
|
e.target.setAttribute('type', 'password');
|
2015-10-24 18:43:30 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
blurName: function(e) {
|
|
|
|
var value = $.trim(e.target.value);
|
|
|
|
if (!value) {
|
|
|
|
e.target.value = this.model.get('name');
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
this.model.setName(value);
|
|
|
|
},
|
|
|
|
|
|
|
|
blurDefUser: function(e) {
|
|
|
|
var value = $.trim(e.target.value);
|
|
|
|
this.model.setDefaultUser(value);
|
|
|
|
},
|
|
|
|
|
|
|
|
changeTrash: function(e) {
|
|
|
|
this.model.setRecycleBinEnabled(e.target.checked);
|
|
|
|
},
|
|
|
|
|
|
|
|
blurHistoryLength: function(e) {
|
|
|
|
var value = +e.target.value;
|
|
|
|
if (isNaN(value)) {
|
|
|
|
e.target.value = this.model.get('historyMaxItems');
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
this.model.setHistoryMaxItems(value);
|
|
|
|
},
|
|
|
|
|
|
|
|
blurHistorySize: function(e) {
|
|
|
|
var value = +e.target.value;
|
|
|
|
if (isNaN(value)) {
|
|
|
|
e.target.value = this.model.get('historyMaxSize') / 1024 / 1024;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
this.model.setHistoryMaxSize(value * 1024 * 1024);
|
|
|
|
},
|
|
|
|
|
|
|
|
blurKeyRounds: function(e) {
|
|
|
|
var value = +e.target.value;
|
|
|
|
if (isNaN(value)) {
|
|
|
|
e.target.value = this.model.get('keyEncryptionRounds');
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
this.model.setKeyEncryptionRounds(value);
|
2015-10-17 23:49:24 +02:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
module.exports = SettingsAboutView;
|