diff --git a/app/scripts/models/app-model.js b/app/scripts/models/app-model.js index 912e7be8..24d9a8c2 100644 --- a/app/scripts/models/app-model.js +++ b/app/scripts/models/app-model.js @@ -396,6 +396,25 @@ var AppModel = Backbone.Model.extend({ }); }, + importFileWithXml: function(params, callback) { + var logger = new Logger('import', params.name); + logger.info('File import request with supplied xml'); + var file = new FileModel({ + name: params.name, + storage: params.storage, + path: params.path + }); + var that = this; + file.importWithXml(params.fileXml, function(err) { + logger.info('Import xml complete ' + (err ? 'with error' : ''), err); + if (err) { + return callback(err); + } + that.addFile(file); + that.fileOpened(file); + }); + }, + addToLastOpenFiles: function(file, rev) { this.appLogger.debug('Add last open file', file.get('cacheId'), file.get('name'), file.get('storage'), file.get('path'), rev); var dt = new Date(); diff --git a/app/scripts/models/file-model.js b/app/scripts/models/file-model.js index 159a1829..7db5e156 100644 --- a/app/scripts/models/file-model.js +++ b/app/scripts/models/file-model.js @@ -82,6 +82,29 @@ var FileModel = Backbone.Model.extend({ this.set({ open: true, created: true, name: name }); }, + importWithXml: function(fileXml, callback) { + try { + var ts = logger.ts(); + var password = kdbxweb.ProtectedValue.fromString(''); + var credentials = new kdbxweb.Credentials(password); + kdbxweb.Kdbx.loadXml(fileXml, credentials, (function(db, err) { + if (err) { + logger.error('Error importing file', err.code, err.message, err); + callback(err); + } else { + this.db = db; + this.readModel(); + this.set({ open: true, created: true }); + logger.info('Imported file ' + this.get('name') + ': ' + logger.ts(ts)); + callback(); + } + }).bind(this)); + } catch (e) { + logger.error('Error importing file', e, e.code, e.message, e); + callback(e); + } + }, + openDemo: function(callback) { var password = kdbxweb.ProtectedValue.fromString('demo'); var credentials = new kdbxweb.Credentials(password); diff --git a/app/scripts/views/open-view.js b/app/scripts/views/open-view.js index be26d438..243f0ea0 100644 --- a/app/scripts/views/open-view.js +++ b/app/scripts/views/open-view.js @@ -18,6 +18,7 @@ var OpenView = Backbone.View.extend({ 'click .open__icon-open': 'openFile', 'click .open__icon-new': 'createNew', 'click .open__icon-dropbox': 'openFromDropbox', + 'click .open__icon-import': 'importFromXml', 'click .open__icon-demo': 'createDemo', 'click .open__pass-input[readonly]': 'openFile', 'input .open__pass-input': 'inputInput', @@ -124,18 +125,29 @@ var OpenView = Backbone.View.extend({ processFile: function(file, complete) { var reader = new FileReader(); reader.onload = (function(e) { - if (this.reading === 'fileData') { - this.params.id = null; - this.params.fileData = e.target.result; - this.params.name = file.name.replace(/\.\w+$/i, ''); - this.params.path = file.path || null; - this.params.storage = file.path ? 'file' : null; - this.params.rev = null; - this.displayOpenFile(); - } else { - this.params.keyFileData = e.target.result; - this.params.keyFileName = file.name; - this.displayOpenKeyFile(); + switch (this.reading) { + case 'fileData': + this.params.id = null; + this.params.fileData = e.target.result; + this.params.name = file.name.replace(/\.\w+$/i, ''); + this.params.path = file.path || null; + this.params.storage = file.path ? 'file' : null; + this.params.rev = null; + this.displayOpenFile(); + break; + case 'fileXml': + this.params.id = null; + this.params.fileXml = e.target.result; + this.params.name = file.name.replace(/\.\w+$/i, ''); + this.params.path = null; + this.params.storage = null; + this.params.rev = null; + this.importDbWithXml(); + break; + default: + this.params.keyFileData = e.target.result; + this.params.keyFileName = file.name; + this.displayOpenKeyFile(); } if (complete) { complete(true); @@ -147,7 +159,11 @@ var OpenView = Backbone.View.extend({ complete(false); } }).bind(this); - reader.readAsArrayBuffer(file); + if (this.reading === 'fileXml') { + reader.readAsText(file); + } else { + reader.readAsArrayBuffer(file); + } }, displayOpenFile: function() { @@ -180,6 +196,12 @@ var OpenView = Backbone.View.extend({ } }, + importFromXml: function() { + if (!this.busy) { + this.openAny('fileXml', 'xml'); + } + }, + openKeyFile: function(e) { if ($(e.target).hasClass('open__settings-key-file-dropbox')) { this.openKeyFileFromDropbox(); @@ -451,6 +473,16 @@ var OpenView = Backbone.View.extend({ } else { this.trigger('close'); } + }, + + importDbWithXml: function() { + if (this.busy || !this.params.name) { + return; + } + this.$el.toggleClass('open--opening', true); + this.inputEl.attr('disabled', 'disabled'); + this.busy = true; + this.afterPaint(this.model.importFileWithXml.bind(this.model, this.params, this.openDbComplete.bind(this))); } }); diff --git a/release-notes.md b/release-notes.md index c6dd296a..b1c17f6f 100644 --- a/release-notes.md +++ b/release-notes.md @@ -15,6 +15,7 @@ Storage providers, usability improvements `+` shortcut to copy website `+` shortcuts while the app is in background `+` build for 32-bit linux +`+` ability to import xml `-` fix #88: capslock indicator `-` fix file settings input behavior