2013-09-13 08:11:47 -04:00
|
|
|
define(function(require) {
|
2013-09-11 16:11:26 -04:00
|
|
|
'use strict';
|
|
|
|
|
2013-09-13 08:11:47 -04:00
|
|
|
var angular = require('angular'),
|
2013-09-15 11:05:37 -04:00
|
|
|
appController = require('js/app-controller'),
|
2013-09-13 08:11:47 -04:00
|
|
|
aes = require('cryptoLib/aes-cbc'),
|
|
|
|
util = require('cryptoLib/util'),
|
2013-09-15 11:05:37 -04:00
|
|
|
str = require('js/app-config').string,
|
|
|
|
emailDao;
|
2013-09-13 08:11:47 -04:00
|
|
|
|
|
|
|
//
|
|
|
|
// Controller
|
|
|
|
//
|
2013-09-12 11:22:17 -04:00
|
|
|
|
2013-10-18 21:32:00 -04:00
|
|
|
var WriteCtrl = function($scope, $filter) {
|
2013-09-13 08:11:47 -04:00
|
|
|
$scope.signature = str.signature;
|
2013-10-18 21:32:00 -04:00
|
|
|
emailDao = appController._emailDao;
|
2013-09-13 08:11:47 -04:00
|
|
|
|
2013-10-12 13:39:09 -04:00
|
|
|
//
|
|
|
|
// Init
|
|
|
|
//
|
|
|
|
|
2013-11-08 15:55:08 -05:00
|
|
|
$scope.state.writer = {
|
|
|
|
open: false,
|
|
|
|
write: function(replyTo) {
|
|
|
|
this.open = true;
|
|
|
|
|
|
|
|
resetFields();
|
|
|
|
if (replyTo) {
|
|
|
|
fillFields(replyTo);
|
|
|
|
$scope.updatePreview();
|
|
|
|
}
|
|
|
|
$scope.verifyTo();
|
|
|
|
},
|
|
|
|
close: function() {
|
|
|
|
this.open = false;
|
2013-10-18 21:32:00 -04:00
|
|
|
}
|
2013-11-08 15:55:08 -05:00
|
|
|
};
|
2013-10-18 21:32:00 -04:00
|
|
|
|
|
|
|
function resetFields() {
|
|
|
|
$scope.writerTitle = 'New email';
|
2013-10-21 09:02:54 -04:00
|
|
|
$scope.to = '';
|
|
|
|
$scope.subject = '';
|
|
|
|
$scope.body = '';
|
|
|
|
$scope.ciphertextPreview = '';
|
2013-10-18 21:32:00 -04:00
|
|
|
}
|
2013-10-12 13:39:09 -04:00
|
|
|
|
|
|
|
function fillFields(re) {
|
2013-11-07 08:50:32 -05:00
|
|
|
var from, cleaned, body;
|
2013-10-13 07:49:37 -04:00
|
|
|
|
2013-10-12 13:39:09 -04:00
|
|
|
if (!re) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-10-18 21:32:00 -04:00
|
|
|
$scope.writerTitle = 'Reply';
|
2013-10-12 13:39:09 -04:00
|
|
|
// fill recipient field
|
|
|
|
$scope.to = re.from[0].address;
|
|
|
|
// fill subject
|
|
|
|
$scope.subject = 'Re: ' + ((re.subject) ? re.subject.replace('Re: ', '') : '');
|
|
|
|
|
|
|
|
// fill text body
|
2013-10-13 07:49:37 -04:00
|
|
|
from = re.from[0].name || re.from[0].address;
|
2013-11-12 11:32:02 -05:00
|
|
|
body = '<br><br>' + $filter('date')(re.sentDate, 'EEEE, MMM d, yyyy h:mm a') + ' ' + from + ' wrote:<br><br>';
|
2013-11-06 02:36:22 -05:00
|
|
|
|
|
|
|
// clean text from markup if to prevent injection in contenteditable
|
|
|
|
if (!re.html) {
|
2013-11-07 08:50:32 -05:00
|
|
|
cleaned = angular.element('<p>' + re.body + '</p>').text();
|
|
|
|
body += cleaned.split('\n').join('<br>');
|
2013-11-06 02:36:22 -05:00
|
|
|
$scope.body = body;
|
|
|
|
}
|
2013-10-12 13:39:09 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
//
|
2013-11-04 15:07:32 -05:00
|
|
|
// Editing headers
|
|
|
|
//
|
|
|
|
|
|
|
|
$scope.verifyTo = function() {
|
|
|
|
if (!$scope.to) {
|
|
|
|
resetDisplay();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// set display to insecure while fetching keys
|
2013-11-11 10:11:06 -05:00
|
|
|
$scope.toKey = undefined;
|
2013-11-04 15:07:32 -05:00
|
|
|
displayInsecure();
|
|
|
|
// check if to address is contained in known public keys
|
|
|
|
emailDao._keychain.getReceiverPublicKey($scope.to, function(err, key) {
|
|
|
|
if (err) {
|
|
|
|
console.error(err);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// compare again since model could have changed during the roundtrip
|
|
|
|
if (key && key.userId === $scope.to) {
|
2013-11-11 10:11:06 -05:00
|
|
|
$scope.toKey = key;
|
2013-11-04 15:07:32 -05:00
|
|
|
displaySecure();
|
|
|
|
$scope.$apply();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
function resetDisplay() {
|
|
|
|
$scope.toSecure = undefined;
|
|
|
|
$scope.sendBtnText = undefined;
|
|
|
|
}
|
|
|
|
|
|
|
|
function displaySecure() {
|
|
|
|
$scope.toSecure = true;
|
|
|
|
$scope.sendBtnText = 'Send securely';
|
|
|
|
}
|
|
|
|
|
|
|
|
function displayInsecure() {
|
|
|
|
$scope.toSecure = false;
|
|
|
|
$scope.sendBtnText = 'Invite & send securely';
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Editing email body
|
2013-10-12 13:39:09 -04:00
|
|
|
//
|
|
|
|
|
2013-09-13 08:11:47 -04:00
|
|
|
// generate key,iv for encryption preview
|
|
|
|
var key = util.random(128),
|
|
|
|
iv = util.random(128);
|
|
|
|
|
|
|
|
$scope.updatePreview = function() {
|
2013-10-21 09:02:54 -04:00
|
|
|
var body = $scope.body;
|
2013-09-15 11:05:37 -04:00
|
|
|
// remove generated html from body
|
|
|
|
body = parseBody(body);
|
2013-09-14 08:23:46 -04:00
|
|
|
|
2013-10-05 08:16:04 -04:00
|
|
|
// Although this does encrypt live using AES, this is just for show. The plaintext is encrypted seperately before sending the email.
|
2013-10-18 20:58:53 -04:00
|
|
|
$scope.ciphertextPreview = (body) ? aes.encrypt(body, key, iv) : '';
|
2013-09-13 08:11:47 -04:00
|
|
|
};
|
2013-09-15 11:05:37 -04:00
|
|
|
|
2013-10-23 14:46:42 -04:00
|
|
|
$scope.sendToOutbox = function() {
|
2013-09-15 11:05:37 -04:00
|
|
|
var to, body, email;
|
|
|
|
|
|
|
|
// validate recipients
|
|
|
|
to = $scope.to.replace(/\s/g, '').split(/[,;]/);
|
|
|
|
if (!to || to.length < 1) {
|
2013-11-11 10:11:06 -05:00
|
|
|
$scope.onError({
|
|
|
|
errMsg: 'Seperate recipients with a comma!'
|
|
|
|
});
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// only allow secure recipients until invitation is implemented
|
|
|
|
if (!$scope.toKey) {
|
|
|
|
$scope.onError({
|
|
|
|
errMsg: 'Invitations not yet supported!'
|
|
|
|
});
|
2013-09-15 11:05:37 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// remove generated html from body
|
2013-11-05 16:33:19 -05:00
|
|
|
body = parseBody($scope.body);
|
2013-09-15 11:05:37 -04:00
|
|
|
|
|
|
|
email = {
|
|
|
|
to: [], // list of receivers
|
|
|
|
subject: $scope.subject, // Subject line
|
|
|
|
body: body // plaintext body
|
|
|
|
};
|
|
|
|
email.from = [{
|
|
|
|
name: '',
|
|
|
|
address: emailDao._account.emailAddress
|
|
|
|
}];
|
|
|
|
to.forEach(function(address) {
|
|
|
|
email.to.push({
|
|
|
|
name: '',
|
|
|
|
address: address
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2013-10-23 14:46:42 -04:00
|
|
|
// set an id for the email and store in outbox
|
|
|
|
email.id = util.UUID();
|
|
|
|
emailDao._devicestorage.storeList([email], 'email_OUTBOX', function(err) {
|
2013-09-15 11:05:37 -04:00
|
|
|
if (err) {
|
2013-10-23 14:46:42 -04:00
|
|
|
console.error(err);
|
2013-09-15 11:05:37 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-11-08 17:31:20 -05:00
|
|
|
$scope.state.writer.close();
|
2013-10-27 06:32:12 -04:00
|
|
|
$scope.$apply();
|
|
|
|
$scope.emptyOutbox();
|
2013-09-15 11:05:37 -04:00
|
|
|
});
|
|
|
|
};
|
2013-09-12 11:22:17 -04:00
|
|
|
};
|
2013-09-11 16:11:26 -04:00
|
|
|
|
2013-09-15 11:05:37 -04:00
|
|
|
function parseBody(body) {
|
2013-11-05 16:33:19 -05:00
|
|
|
var regex = /(\r\n|\n|\r)/gm;
|
|
|
|
|
|
|
|
var text = body.replace(regex, '').split('<div><br>').join('\n').split('<div>').join('\n').split('<br>').join('\n');
|
2013-09-15 11:05:37 -04:00
|
|
|
|
2013-11-07 08:50:32 -05:00
|
|
|
return angular.element('<p>' + text + '</p>').text();
|
2013-09-15 11:05:37 -04:00
|
|
|
}
|
|
|
|
|
2013-09-13 08:11:47 -04:00
|
|
|
//
|
|
|
|
// Directives
|
|
|
|
//
|
|
|
|
|
|
|
|
var ngModule = angular.module('write', []);
|
|
|
|
ngModule.directive('contenteditable', function() {
|
|
|
|
return {
|
|
|
|
require: 'ngModel',
|
|
|
|
link: function(scope, elm, attrs, ctrl) {
|
|
|
|
// view -> model
|
2013-10-13 07:49:37 -04:00
|
|
|
elm.on('keyup keydown', function() {
|
2013-09-13 08:11:47 -04:00
|
|
|
scope.$apply(function() {
|
|
|
|
ctrl.$setViewValue(elm.html());
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
// model -> view
|
2013-10-12 13:39:09 -04:00
|
|
|
ctrl.$render = function() {
|
|
|
|
elm.html(ctrl.$viewValue);
|
2013-09-13 08:11:47 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
// load init value from DOM
|
|
|
|
ctrl.$setViewValue(elm.html());
|
|
|
|
}
|
|
|
|
};
|
|
|
|
});
|
2013-10-12 13:39:09 -04:00
|
|
|
|
2013-10-19 09:06:23 -04:00
|
|
|
ngModule.directive('focusMe', function($timeout, $parse) {
|
2013-09-13 08:11:47 -04:00
|
|
|
return {
|
2013-10-19 09:06:23 -04:00
|
|
|
//scope: true, // optionally create a child scope
|
|
|
|
link: function(scope, element, attrs) {
|
|
|
|
var model = $parse(attrs.focusMe);
|
|
|
|
scope.$watch(model, function(value) {
|
|
|
|
if (value === true) {
|
|
|
|
$timeout(function() {
|
|
|
|
element[0].focus();
|
2013-11-07 14:00:36 -05:00
|
|
|
}, 100);
|
2013-10-19 09:06:23 -04:00
|
|
|
}
|
|
|
|
});
|
2013-09-13 08:11:47 -04:00
|
|
|
}
|
|
|
|
};
|
|
|
|
});
|
|
|
|
|
2013-11-04 15:07:32 -05:00
|
|
|
ngModule.directive('autoSize', function($parse) {
|
|
|
|
return {
|
|
|
|
require: 'ngModel',
|
|
|
|
link: function(scope, elm, attrs) {
|
|
|
|
var model = $parse(attrs.autoSize);
|
|
|
|
scope.$watch(model, function(value) {
|
|
|
|
if (!value) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
var width = ((value.length + 2) * 8) + 'px';
|
|
|
|
elm.css('width', width);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
};
|
|
|
|
});
|
|
|
|
|
2013-09-11 16:11:26 -04:00
|
|
|
return WriteCtrl;
|
|
|
|
});
|