2016-03-31 22:52:04 +02:00
|
|
|
'use strict';
|
|
|
|
|
|
|
|
var Backbone = require('backbone'),
|
|
|
|
Alerts = require('./alerts'),
|
|
|
|
Locale = require('../util/locale'),
|
|
|
|
Logger = require('../util/logger'),
|
|
|
|
FeatureDetector = require('../util/feature-detector'),
|
2016-04-01 23:09:16 +02:00
|
|
|
Otp = require('../util/otp'),
|
2016-03-31 22:52:04 +02:00
|
|
|
QrCode = require('qrcode');
|
|
|
|
|
|
|
|
var logger = new Logger('otp-qr-reader');
|
|
|
|
|
|
|
|
var OtpQrReader = {
|
|
|
|
alert: null,
|
|
|
|
|
2016-04-02 16:34:30 +02:00
|
|
|
fileInput: null,
|
|
|
|
|
2016-03-31 22:52:04 +02:00
|
|
|
read: function() {
|
|
|
|
var screenshotKey = FeatureDetector.screenshotToClipboardShortcut();
|
|
|
|
if (screenshotKey) {
|
|
|
|
screenshotKey = Locale.detSetupOtpAlertBodyWith.replace('{}', '<code>' + screenshotKey + '</code>');
|
|
|
|
}
|
|
|
|
var pasteKey = FeatureDetector.isMobile() ? '' :
|
|
|
|
Locale.detSetupOtpAlertBodyWith.replace('{}',
|
|
|
|
'<code>' + FeatureDetector.actionShortcutSymbol() + 'V</code>');
|
|
|
|
OtpQrReader.startListenClipoard();
|
2016-04-02 16:34:30 +02:00
|
|
|
var buttons = [Alerts.buttons.cancel];
|
|
|
|
if (FeatureDetector.isMobile()) {
|
|
|
|
buttons.unshift({result: 'select', title: Locale.detSetupOtoScanButton});
|
|
|
|
}
|
|
|
|
var lastLine = FeatureDetector.isMobile() ? Locale.detSetupOtpAlertBody3Mobile :
|
|
|
|
Locale.detSetupOtpAlertBody3.replace('{}', pasteKey || '');
|
2016-03-31 22:52:04 +02:00
|
|
|
OtpQrReader.alert = Alerts.alert({
|
|
|
|
icon: 'qrcode',
|
|
|
|
header: Locale.detSetupOtpAlert,
|
|
|
|
body: [Locale.detSetupOtpAlertBody,
|
|
|
|
Locale.detSetupOtpAlertBody1,
|
|
|
|
Locale.detSetupOtpAlertBody2.replace('{}', screenshotKey || ''),
|
2016-04-02 16:34:30 +02:00
|
|
|
lastLine
|
2016-03-31 22:52:04 +02:00
|
|
|
].join('<br/>'),
|
|
|
|
esc: '',
|
|
|
|
click: '',
|
|
|
|
enter: '',
|
2016-04-02 16:34:30 +02:00
|
|
|
buttons: buttons,
|
|
|
|
complete: function(res) {
|
2016-03-31 22:52:04 +02:00
|
|
|
OtpQrReader.alert = null;
|
|
|
|
OtpQrReader.stopListenClipboard();
|
2016-04-02 16:34:30 +02:00
|
|
|
if (res === 'select') {
|
|
|
|
OtpQrReader.selectFile();
|
|
|
|
}
|
2016-03-31 22:52:04 +02:00
|
|
|
}
|
|
|
|
});
|
2016-04-02 18:43:13 +02:00
|
|
|
// transparent window with QR scanner - is it better? check usability of this
|
2016-03-31 22:52:04 +02:00
|
|
|
// var BrowserWindow = require('../../comp/launcher').remReq('browser-window');
|
2016-04-02 18:43:13 +02:00
|
|
|
// new BrowserWindow({ width: 800, height: 600, show: false, alwaysOnTop: true, backgroundColor: '#80FFFFFF',
|
|
|
|
// transparent: true }).show();
|
2016-03-31 22:52:04 +02:00
|
|
|
},
|
|
|
|
|
2016-04-02 16:34:30 +02:00
|
|
|
selectFile: function() {
|
|
|
|
if (!OtpQrReader.fileInput) {
|
|
|
|
var input = document.createElement('input');
|
|
|
|
input.setAttribute('type', 'file');
|
|
|
|
input.setAttribute('capture', 'camera');
|
|
|
|
input.setAttribute('accept', 'image/*');
|
|
|
|
input.setAttribute('class', 'hide-by-pos');
|
|
|
|
OtpQrReader.fileInput = input;
|
|
|
|
OtpQrReader.fileInput.onchange = OtpQrReader.fileSelected;
|
|
|
|
}
|
|
|
|
OtpQrReader.fileInput.click();
|
|
|
|
},
|
|
|
|
|
|
|
|
fileSelected: function() {
|
|
|
|
var file = OtpQrReader.fileInput.files[0];
|
|
|
|
if (!file || file.type.indexOf('image') < 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
OtpQrReader.readFile(file);
|
|
|
|
},
|
|
|
|
|
2016-03-31 22:52:04 +02:00
|
|
|
startListenClipoard: function() {
|
|
|
|
document.addEventListener('paste', OtpQrReader.pasteEvent);
|
|
|
|
},
|
|
|
|
|
|
|
|
stopListenClipboard: function() {
|
|
|
|
document.removeEventListener('paste', OtpQrReader.pasteEvent);
|
|
|
|
},
|
|
|
|
|
|
|
|
pasteEvent: function(e) {
|
|
|
|
var item = _.find(e.clipboardData.items, function(item) {
|
|
|
|
return item.kind === 'file' && item.type.indexOf('image') !== -1;
|
|
|
|
});
|
|
|
|
if (!item) {
|
2016-04-02 16:34:30 +02:00
|
|
|
logger.debug('Paste without file');
|
2016-03-31 22:52:04 +02:00
|
|
|
return;
|
|
|
|
}
|
2016-04-02 16:34:30 +02:00
|
|
|
logger.info('Reading pasted image', item.type);
|
2016-03-31 22:52:04 +02:00
|
|
|
if (OtpQrReader.alert) {
|
|
|
|
OtpQrReader.alert.change({
|
|
|
|
header: Locale.detOtpImageReading
|
|
|
|
});
|
|
|
|
}
|
2016-04-02 16:34:30 +02:00
|
|
|
OtpQrReader.readFile(item.getAsFile());
|
|
|
|
},
|
|
|
|
|
|
|
|
readFile: function(file) {
|
2016-03-31 22:52:04 +02:00
|
|
|
var reader = new FileReader();
|
|
|
|
reader.onload = function() {
|
|
|
|
logger.debug('Image data loaded');
|
|
|
|
OtpQrReader.readQr(reader.result);
|
|
|
|
};
|
2016-04-02 16:34:30 +02:00
|
|
|
reader.readAsDataURL(file);
|
2016-03-31 22:52:04 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
readQr: function(imageData) {
|
|
|
|
var image = new Image();
|
|
|
|
image.onload = function() {
|
|
|
|
logger.debug('Image format loaded');
|
|
|
|
try {
|
|
|
|
var ts = logger.ts();
|
|
|
|
var url = new QrCode(image).decode();
|
2016-04-01 21:19:27 +02:00
|
|
|
logger.info('QR code read', logger.ts(ts));
|
2016-04-02 16:34:30 +02:00
|
|
|
OtpQrReader.removeAlert();
|
2016-03-31 22:52:04 +02:00
|
|
|
try {
|
|
|
|
var otp = Otp.parseUrl(url);
|
|
|
|
OtpQrReader.trigger('qr-read', otp);
|
|
|
|
} catch (err) {
|
2016-04-01 21:19:27 +02:00
|
|
|
logger.error('Error parsing QR code', err);
|
2016-03-31 22:52:04 +02:00
|
|
|
Alerts.error({
|
|
|
|
header: Locale.detOtpQrWrong,
|
|
|
|
body: Locale.detOtpQrWrongBody + '<pre class="modal__pre">' + _.escape(err.toString()) +'</pre>'
|
|
|
|
});
|
|
|
|
}
|
|
|
|
} catch (e) {
|
|
|
|
logger.error('Error reading QR code', e);
|
2016-04-02 16:34:30 +02:00
|
|
|
OtpQrReader.removeAlert();
|
2016-03-31 22:52:04 +02:00
|
|
|
Alerts.error({
|
|
|
|
header: Locale.detOtpQrError,
|
|
|
|
body: Locale.detOtpQrErrorBody
|
|
|
|
});
|
|
|
|
}
|
|
|
|
};
|
|
|
|
image.onerror = function() {
|
|
|
|
logger.debug('Image load error');
|
2016-04-02 16:34:30 +02:00
|
|
|
OtpQrReader.removeAlert();
|
2016-03-31 22:52:04 +02:00
|
|
|
Alerts.error({
|
|
|
|
header: Locale.detOtpImageError,
|
|
|
|
body: Locale.detOtpImageErrorBody
|
|
|
|
});
|
|
|
|
};
|
|
|
|
image.src = imageData;
|
2016-04-02 16:34:30 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
removeAlert: function() {
|
|
|
|
if (OtpQrReader.alert) {
|
2016-04-03 21:16:05 +02:00
|
|
|
OtpQrReader.alert.closeImmediate();
|
2016-04-02 16:34:30 +02:00
|
|
|
}
|
2016-03-31 22:52:04 +02:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
_.extend(OtpQrReader, Backbone.Events);
|
|
|
|
|
|
|
|
module.exports = OtpQrReader;
|