Merge pull request #141 from whiteout-io/dev/WO-567

Dev/wo 567
This commit is contained in:
Tankred Hase 2014-10-16 12:12:07 +02:00
commit 5d09e32320
100 changed files with 19058 additions and 19615 deletions

6
.gitignore vendored
View File

@ -7,7 +7,7 @@ src/css/
dist/ dist/
release/ release/
test/integration/src/ test/integration/src/
src/lib/*.js
src/js/crypto/aes-gcm.js
src/js/crypto/util.js
.elasticbeanstalk/ .elasticbeanstalk/
test/*/index.js
**/*.browserified.js
**/*.js.map

View File

@ -18,31 +18,29 @@
"unused": true, "unused": true,
"predef": [ "predef": [
"console",
"Notification",
"importScripts",
"process",
"Event",
"QUnit",
"test",
"asyncTest",
"ok",
"equal",
"deepEqual",
"start",
"chrome",
"requirejs",
"define",
"self", "self",
"describe", "importScripts",
"it", "console",
"chai", "process",
"chrome",
"Notification",
"Event",
"sinon", "sinon",
"mocha", "mocha",
"chai",
"expect",
"describe",
"it",
"before", "before",
"beforeEach", "beforeEach",
"after", "after",
"afterEach" "afterEach",
"FastClick",
"angular",
"forge",
"Lawnchair",
"_",
"openpgp"
], ],
"globals": { "globals": {

View File

@ -1,11 +1,22 @@
module.exports = function(grunt) { module.exports = function(grunt) {
'use strict'; 'use strict';
require('time-grunt')(grunt);
var version = grunt.option('release'), var version = grunt.option('release'),
zipName = (version) ? version : 'DEV'; zipName = (version) ? version : 'DEV';
var browserifyOpt = {
exclude: ['openpgp', 'node-forge', 'net', 'tls', 'crypto'], // node apis not required at build time
ignore: ['buffer'], // node apis to be stubbed for runtime
browserifyOptions: {
debug: true
}
};
// Project configuration. // Project configuration.
grunt.initConfig({ grunt.initConfig({
connect: { connect: {
dev: { dev: {
options: { options: {
@ -23,32 +34,27 @@ module.exports = function(grunt) {
}, },
jshint: { jshint: {
all: ['Gruntfile.js', 'src/*.js', 'src/js/**/*.js', 'test/unit/*.js', 'test/integration/*.js'], all: ['Gruntfile.js', 'src/*.js', 'src/js/**/*.js', 'test/unit/*-test.js', 'test/integration/*-test.js'],
options: { options: {
jshintrc: '.jshintrc' jshintrc: '.jshintrc'
} }
}, },
mocha: { mocha_phantomjs: {
all: { all: {
options: { options: {
urls: [ urls: [
'http://localhost:<%= connect.test.options.port %>/test/unit/index.html', 'http://localhost:<%= connect.test.options.port %>/test/unit/index.html',
'http://localhost:<%= connect.test.options.port %>/test/integration/index.html' 'http://localhost:<%= connect.test.options.port %>/test/integration/index.html'
], ]
run: false,
reporter: 'Spec',
log: false,
// phanotmjs is soooo slow
timeout: 100000
} }
} }
}, },
clean: { clean: {
dist: ['dist', 'src/lib/*.js', 'test/lib', 'test/integration/src'] dist: ['dist', 'test/lib', 'test/integration/src']
}, },
sass: { sass: {
dist: { dist: {
files: { files: {
@ -57,6 +63,7 @@ module.exports = function(grunt) {
} }
} }
}, },
autoprefixer: { autoprefixer: {
options: { options: {
browsers: ['last 2 versions'] browsers: ['last 2 versions']
@ -68,9 +75,10 @@ module.exports = function(grunt) {
} }
} }
}, },
csso: { csso: {
options: { options: {
banner: '/*! Copyright © 2013, Whiteout Networks GmbH. All rights reserved.*/\n' banner: '/*! Copyright © <%= grunt.template.today("yyyy") %>, Whiteout Networks GmbH.*/\n'
}, },
dist: { dist: {
files: { files: {
@ -79,6 +87,7 @@ module.exports = function(grunt) {
} }
} }
}, },
watch: { watch: {
css: { css: {
files: ['src/sass/**/*.scss'], files: ['src/sass/**/*.scss'],
@ -86,7 +95,7 @@ module.exports = function(grunt) {
}, },
js: { js: {
files: ['src/js/**/*.js'], files: ['src/js/**/*.js'],
tasks: ['copy:js', 'copy:integration', 'manifest'] tasks: ['dist-js', 'copy:integration', 'manifest']
}, },
lib: { lib: {
files: ['src/lib/**/*.js'], files: ['src/lib/**/*.js'],
@ -97,59 +106,234 @@ module.exports = function(grunt) {
tasks: ['copy:app', 'copy:ca', 'copy:tpl', 'copy:img', 'copy:font', 'manifest-dev', 'manifest'] tasks: ['copy:app', 'copy:ca', 'copy:tpl', 'copy:img', 'copy:font', 'manifest-dev', 'manifest']
} }
}, },
copy: {
npm: { browserify: {
expand: true, app: {
flatten: true, files: {
cwd: 'node_modules/', 'dist/js/app.browserified.js': ['src/js/app.js']
src: [
'requirejs/require.js',
'imap-client/src/*.js',
'imap-client/node_modules/browserbox/src/*.js',
'imap-client/node_modules/browserbox/node_modules/wo-imap-handler/src/*.js',
'imap-client/node_modules/browserbox/node_modules/mimefuncs/src/*.js',
'imap-client/node_modules/browserbox/node_modules/tcp-socket/src/*.js',
'imap-client/node_modules/browserbox/node_modules/wo-utf7/src/*.js',
'mailreader/src/*.js',
'mailreader/node_modules/mimeparser/src/*.js',
'mailreader/node_modules/mimeparser/node_modules/wo-addressparser/src/*.js',
'pgpbuilder/src/*.js',
'pgpbuilder/node_modules/mailbuild/src/*.js',
'pgpbuilder/node_modules/mailbuild/node_modules/mimetypes/src/*.js',
'pgpbuilder/node_modules/mailbuild/node_modules/punycode/punycode.min.js',
'pgpmailer/src/*.js',
'pgpmailer/node_modules/wo-smtpclient/src/*.js',
'pgpmailer/node_modules/wo-smtpclient/node_modules/wo-stringencoding/dist/stringencoding.js',
'axe-logger/axe.js',
'dompurify/purify.js',
'jquery/dist/jquery.min.js',
'ng-infinite-scroll/build/ng-infinite-scroll.min.js'
],
dest: 'src/lib/'
}, },
options: browserifyOpt
},
pbkdf2Worker: {
files: {
'dist/js/pbkdf2-worker.browserified.js': ['src/js/crypto/pbkdf2-worker.js']
},
options: browserifyOpt
},
mailreaderWorker: {
files: {
'dist/js/mailreader-parser-worker.browserified.js': ['node_modules/mailreader/src/mailreader-parser-worker-browserify.js']
},
options: browserifyOpt
},
tlsWorker: {
files: {
'dist/js/tcp-socket-tls-worker.browserified.js': ['node_modules/tcp-socket/src/tcp-socket-tls-worker.js']
},
options: browserifyOpt
},
unitTest: {
files: {
'test/unit/index.browserified.js': [
'test/unit/oauth-test.js',
'test/unit/auth-test.js',
'test/unit/email-dao-test.js',
'test/unit/app-controller-test.js',
'test/unit/pgp-test.js',
'test/unit/crypto-test.js',
'test/unit/backbutton-handler-test.js',
'test/unit/rest-dao-test.js',
'test/unit/admin-dao-test.js',
'test/unit/publickey-dao-test.js',
'test/unit/privatekey-dao-test.js',
'test/unit/lawnchair-dao-test.js',
'test/unit/keychain-dao-test.js',
'test/unit/devicestorage-dao-test.js',
'test/unit/dialog-ctrl-test.js',
'test/unit/add-account-ctrl-test.js',
'test/unit/account-ctrl-test.js',
'test/unit/set-passphrase-ctrl-test.js',
'test/unit/contacts-ctrl-test.js',
'test/unit/login-existing-ctrl-test.js',
'test/unit/login-initial-ctrl-test.js',
'test/unit/login-new-device-ctrl-test.js',
'test/unit/login-privatekey-download-ctrl-test.js',
'test/unit/login-set-credentials-ctrl-test.js',
'test/unit/privatekey-upload-ctrl-test.js',
'test/unit/login-ctrl-test.js',
'test/unit/read-ctrl-test.js',
'test/unit/navigation-ctrl-test.js',
'test/unit/mail-list-ctrl-test.js',
'test/unit/write-ctrl-test.js',
'test/unit/outbox-bo-test.js',
'test/unit/invitation-dao-test.js',
'test/unit/update-handler-test.js',
'test/unit/connection-doctor-test.js',
'test/main.js'
]
},
options: browserifyOpt
},
integrationTest: {
files: {
'test/integration/index.browserified.js': [
'test/integration/email-dao-test.js',
'test/main.js'
]
},
options: browserifyOpt
}
},
exorcise: {
app: {
files: {
'dist/js/app.browserified.js.map': ['dist/js/app.browserified.js'],
}
},
unitTest: {
files: {
'test/unit/index.browserified.js.map': ['test/unit/index.browserified.js'],
}
},
integrationTest: {
files: {
'test/integration/index.browserified.js.map': ['test/integration/index.browserified.js'],
}
}
},
uglify: {
app: {
files: {
'dist/js/app.min.js': [
'src/lib/underscore/underscore-min.js',
'node_modules/jquery/dist/jquery.min.js',
'src/lib/angular/angular.min.js',
'src/lib/angular/angular-route.min.js',
'src/lib/angular/angular-animate.min.js',
'src/lib/ngtagsinput/ng-tags-input.min.js',
'node_modules/ng-infinite-scroll/build/ng-infinite-scroll.min.js',
'src/lib/fastclick/fastclick.js',
'src/lib/lawnchair/lawnchair-git.js',
'src/lib/lawnchair/lawnchair-adapter-webkit-sqlite-git.js',
'src/lib/lawnchair/lawnchair-adapter-indexed-db-git.js',
'dist/js/app.browserified.js'
]
},
options: {
mangle: false,
sourceMap: true,
sourceMapIn: 'dist/js/app.browserified.js.map',
sourceMapIncludeSources: true,
sourceMapName: 'dist/js/app.min.js.map'
}
},
readSandbox: {
files: {
'dist/js/read-sandbox.min.js': [
'node_modules/dompurify/purify.js',
'src/js/controller/read-sandbox.js'
]
},
options: {
sourceMap: true,
sourceMapName: 'dist/js/read-sandbox.min.js.map'
}
},
pbkdf2Worker: {
files: {
'dist/js/pbkdf2-worker.min.js': ['dist/js/pbkdf2-worker.browserified.js']
}
},
mailreaderWorker: {
files: {
'dist/js/mailreader-parser-worker.min.js': ['dist/js/mailreader-parser-worker.browserified.js']
},
options: {
sourceMap: true,
sourceMapName: 'dist/js/mailreader-parser-worker.min.js.map'
}
},
tlsWorker: {
files: {
'dist/js/tcp-socket-tls-worker.min.js': ['dist/js/tcp-socket-tls-worker.browserified.js']
},
options: {
sourceMap: true,
sourceMapName: 'dist/js/tcp-socket-tls-worker.min.js.map'
}
},
unitTest: {
files: {
'test/unit/index.js': [
'src/lib/underscore/underscore-min.js',
'node_modules/jquery/dist/jquery.min.js',
'src/lib/angular/angular.min.js',
'src/lib/angular/angular-route.min.js',
'src/lib/angular/angular-animate.min.js',
'node_modules/angularjs/src/ngMock/angular-mocks.js',
'src/lib/lawnchair/lawnchair-git.js',
'src/lib/lawnchair/lawnchair-adapter-webkit-sqlite-git.js',
'src/lib/lawnchair/lawnchair-adapter-indexed-db-git.js',
'test/unit/index.browserified.js'
]
},
options: {
mangle: false,
sourceMap: true,
sourceMapIn: 'test/unit/index.browserified.js.map',
sourceMapIncludeSources: true,
sourceMapName: 'test/unit/index.js.map'
}
},
integrationTest: {
files: {
'test/integration/index.js': [
'src/lib/underscore/underscore-min.js',
'src/lib/lawnchair/lawnchair-git.js',
'src/lib/lawnchair/lawnchair-adapter-webkit-sqlite-git.js',
'src/lib/lawnchair/lawnchair-adapter-indexed-db-git.js',
'test/integration/index.browserified.js'
]
},
options: {
mangle: false,
sourceMap: true,
sourceMapIn: 'test/integration/index.browserified.js.map',
sourceMapIncludeSources: true,
sourceMapName: 'test/integration/index.js.map'
}
},
options: {
banner: '/*! Copyright © <%= grunt.template.today("yyyy") %>, Whiteout Networks GmbH.*/\n'
}
},
copy: {
npmDev: { npmDev: {
expand: true, expand: true,
flatten: true, flatten: true,
cwd: 'node_modules/', cwd: './',
src: ['requirejs/require.js', 'mocha/mocha.css', 'mocha/mocha.js', 'chai/chai.js', 'sinon/pkg/sinon.js', 'angularjs/src/ngMock/angular-mocks.js', 'browsercrow/src/*.js', 'browsersmtp/src/*.js'], src: [
'node_modules/mocha/mocha.css',
'node_modules/mocha/mocha.js',
'node_modules/chai/chai.js',
'node_modules/sinon/pkg/sinon.js',
'node_modules/browsercrow/src/*.js',
'node_modules/browsersmtp/src/*.js',
'src/lib/openpgp/openpgp.js',
'src/lib/openpgp/openpgp.worker.js',
'src/lib/forge/forge.min.js',
'dist/js/pbkdf2-worker.min.js'
],
dest: 'test/lib/' dest: 'test/lib/'
}, },
cryptoLib: {
expand: true,
cwd: 'node_modules/crypto-lib/src/',
src: ['*.js'],
dest: 'src/js/crypto/'
},
lib: { lib: {
expand: true, expand: true,
flatten: true,
cwd: 'src/lib/', cwd: 'src/lib/',
src: ['**'], src: ['openpgp/openpgp.js', 'openpgp/openpgp.worker.js', 'forge/forge.min.js'],
dest: 'dist/lib/'
},
js: {
expand: true,
cwd: 'src/js/',
src: ['**'],
dest: 'dist/js/' dest: 'dist/js/'
}, },
font: { font: {
@ -170,23 +354,11 @@ module.exports = function(grunt) {
src: ['*'], src: ['*'],
dest: 'dist/tpl/' dest: 'dist/tpl/'
}, },
ca: {
expand: true,
cwd: 'src/ca/',
src: ['*'],
dest: 'dist/ca/'
},
app: { app: {
expand: true, expand: true,
cwd: 'src/', cwd: 'src/',
src: ['*.html', '*.js', '*.json', 'manifest.*'], src: ['*.html', '*.js', '*.json', 'manifest.*'],
dest: 'dist/' dest: 'dist/'
},
integration: {
expand: true,
cwd: 'src/',
src: ['**'],
dest: 'test/integration/src/'
} }
}, },
@ -200,16 +372,6 @@ module.exports = function(grunt) {
cwd: 'dist/', cwd: 'dist/',
src: ['**/*'], src: ['**/*'],
dest: 'release/' dest: 'release/'
},
nodeWebkit: {
options: {
mode: 'zip',
archive: 'release/whiteout-mail_' + zipName + '.nw'
},
expand: true,
cwd: 'dist/',
src: ['**/*'],
dest: '/'
} }
}, },
@ -220,31 +382,30 @@ module.exports = function(grunt) {
timestamp: true, timestamp: true,
hash: true, hash: true,
cache: ['socket.io/socket.io.js'], cache: ['socket.io/socket.io.js'],
exclude: ['appcache.manifest', 'manifest.webapp'], exclude: [
'appcache.manifest',
'manifest.webapp',
'js/app.min.js.map',
'js/app.browserified.js',
'js/app.browserified.js.map',
'js/crypto/pbkdf2-worker.browserified.js',
'js/pbkdf2-worker.browserified.js',
'js/read-sandbox.min.js.map'
],
master: ['index.html'] master: ['index.html']
}, },
src: ['**/*.*'], src: ['**/*.*'],
dest: 'dist/appcache.manifest' dest: 'dist/appcache.manifest'
} }
}, }
nodewebkit: {
options: {
version: '0.9.2', // node-webkit version
build_dir: './release/node-webkit/', // Where the build version of my node-webkit app is saved
mac: true, // We want to build it for mac
win: false, // We want to build it for win
linux32: false, // We don't need linux32
linux64: false, // We don't need linux64
},
src: ['./dist/**/*'] // Your node-webkit app
},
}); });
// Load the plugin(s) // Load the plugin(s)
grunt.loadNpmTasks('grunt-browserify');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-connect'); grunt.loadNpmTasks('grunt-contrib-connect');
grunt.loadNpmTasks('grunt-contrib-jshint'); grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-mocha');
grunt.loadNpmTasks('grunt-contrib-clean'); grunt.loadNpmTasks('grunt-contrib-clean');
grunt.loadNpmTasks('grunt-csso'); grunt.loadNpmTasks('grunt-csso');
grunt.loadNpmTasks('grunt-contrib-sass'); grunt.loadNpmTasks('grunt-contrib-sass');
@ -252,18 +413,19 @@ module.exports = function(grunt) {
grunt.loadNpmTasks('grunt-contrib-watch'); grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-contrib-copy'); grunt.loadNpmTasks('grunt-contrib-copy');
grunt.loadNpmTasks('grunt-contrib-compress'); grunt.loadNpmTasks('grunt-contrib-compress');
grunt.loadNpmTasks('grunt-node-webkit-builder');
grunt.loadNpmTasks('grunt-manifest'); grunt.loadNpmTasks('grunt-manifest');
grunt.loadNpmTasks('grunt-mocha-phantomjs');
grunt.loadNpmTasks('grunt-exorcise');
// Build tasks // Build tasks
grunt.registerTask('dist-npm', ['copy:npm', 'copy:npmDev', 'copy:cryptoLib']);
grunt.registerTask('dist-css', ['sass', 'autoprefixer', 'csso']); grunt.registerTask('dist-css', ['sass', 'autoprefixer', 'csso']);
grunt.registerTask('dist-js', ['browserify', 'exorcise', 'uglify']);
grunt.registerTask('dist-copy', ['copy']); grunt.registerTask('dist-copy', ['copy']);
grunt.registerTask('dist', ['clean', 'dist-npm', 'dist-css', 'dist-copy', 'manifest']); grunt.registerTask('dist', ['clean', 'dist-css', 'dist-js', 'dist-copy', 'manifest']);
// Test/Dev tasks // Test/Dev tasks
grunt.registerTask('dev', ['connect:dev']); grunt.registerTask('dev', ['connect:dev']);
grunt.registerTask('test', ['jshint', 'connect:test', 'mocha']); grunt.registerTask('test', ['jshint', 'connect:test', 'mocha_phantomjs']);
grunt.registerTask('prod', ['connect:prod']); grunt.registerTask('prod', ['connect:prod']);
// //

View File

@ -24,25 +24,27 @@
}, },
"scripts": { "scripts": {
"test": "grunt && grunt test", "test": "grunt && grunt test",
"start": "node server.js" "start": "node server.js",
"postinstall": "dir=$(pwd) && cd node_modules/mailreader/ && npm install --production && cd $dir"
}, },
"dependencies": { "dependencies": {
"axe-logger": "~0.0.2", "axe-logger": "~0.0.2",
"compression": "^1.0.11", "compression": "^1.0.11",
"config": "^1.0.2",
"crypto-lib": "~0.2.1", "crypto-lib": "~0.2.1",
"dompurify": "~0.4.2", "dompurify": "~0.4.2",
"express": "^4.8.3", "express": "^4.8.3",
"imap-client": "~0.4.3", "imap-client": "~0.4.3",
"jquery": "~2.1.1", "jquery": "~2.1.1",
"mailreader": "~0.3.5", "mailreader": "~0.4.0",
"morgan": "^1.2.3",
"ng-infinite-scroll": "~1.1.2", "ng-infinite-scroll": "~1.1.2",
"npmlog": "^0.1.1",
"pgpbuilder": "~0.4.0", "pgpbuilder": "~0.4.0",
"pgpmailer": "~0.4.0", "pgpmailer": "~0.4.0",
"requirejs": "~2.1.14", "socket.io": "^1.0.6",
"config": "^1.0.2", "tcp-socket": "~0.3.13",
"morgan": "^1.2.3", "wo-smtpclient": "^0.3.8"
"npmlog": "^0.1.1",
"socket.io": "^1.0.6"
}, },
"devDependencies": { "devDependencies": {
"angularjs": "https://github.com/whiteout-io/angular.js/tarball/npm-version", "angularjs": "https://github.com/whiteout-io/angular.js/tarball/npm-version",
@ -50,19 +52,22 @@
"browsersmtp": "https://github.com/whiteout-io/browsersmtp/tarball/master", "browsersmtp": "https://github.com/whiteout-io/browsersmtp/tarball/master",
"chai": "~1.7.2", "chai": "~1.7.2",
"grunt": "~0.4.1", "grunt": "~0.4.1",
"grunt-contrib-clean": "~0.5.0",
"grunt-contrib-copy": "~0.4.1",
"grunt-manifest": "^0.4.0",
"grunt-autoprefixer": "~0.7.2", "grunt-autoprefixer": "~0.7.2",
"grunt-browserify": "^3.0.1",
"grunt-contrib-clean": "~0.5.0",
"grunt-contrib-compress": "~0.5.2", "grunt-contrib-compress": "~0.5.2",
"grunt-contrib-connect": "~0.5.0", "grunt-contrib-connect": "~0.5.0",
"grunt-contrib-copy": "~0.4.1",
"grunt-contrib-jshint": "~0.6.4", "grunt-contrib-jshint": "~0.6.4",
"grunt-contrib-sass": "~0.7.3", "grunt-contrib-sass": "~0.7.3",
"grunt-contrib-uglify": "^0.6.0",
"grunt-contrib-watch": "~0.5.3", "grunt-contrib-watch": "~0.5.3",
"grunt-csso": "~0.6.1", "grunt-csso": "~0.6.1",
"grunt-mocha": "~0.4.1", "grunt-exorcise": "^0.2.0",
"grunt-node-webkit-builder": "~0.1.17", "grunt-manifest": "^0.4.0",
"mocha": "~1.13.0", "grunt-mocha-phantomjs": "^0.6.0",
"sinon": "~1.7.3" "mocha": "^1.21.4",
"sinon": "~1.7.3",
"time-grunt": "^1.0.0"
} }
} }

View File

@ -26,9 +26,9 @@
<!-- The Scripts --> <!-- The Scripts -->
<script src="socket.io/socket.io.js"></script> <script src="socket.io/socket.io.js"></script>
<script src="lib/require.js"></script> <script src="js/openpgp.js"></script>
<script src="require-config.js"></script> <script src="js/forge.min.js"></script>
<script src="js/app.js"></script> <script src="js/app.min.js"></script>
</head> </head>
<body key-shortcuts> <body key-shortcuts>

View File

@ -1,9 +1,6 @@
define(function(require) {
'use strict'; 'use strict';
var _ = require('underscore'), var appVersion, cloudUrl, keychainUrl, clientId;
app = {},
appVersion, cloudUrl, keychainUrl, clientId;
// parse manifest to get configurations for current runtime // parse manifest to get configurations for current runtime
try { try {
@ -29,7 +26,7 @@ define(function(require) {
/** /**
* Global app configurations * Global app configurations
*/ */
app.config = { exports.config = {
cloudUrl: cloudUrl || 'https://keys.whiteout.io', cloudUrl: cloudUrl || 'https://keys.whiteout.io',
privkeyServerUrl: keychainUrl || 'https://keychain.whiteout.io', privkeyServerUrl: keychainUrl || 'https://keychain.whiteout.io',
adminUrl: 'https://admin-node.whiteout.io', adminUrl: 'https://admin-node.whiteout.io',
@ -185,7 +182,7 @@ define(function(require) {
/** /**
* Strings are maintained here * Strings are maintained here
*/ */
app.string = { exports.string = {
fallbackSubject: '(no subject)', fallbackSubject: '(no subject)',
invitationSubject: 'Invitation to a private conversation', invitationSubject: 'Invitation to a private conversation',
invitationMessage: 'Hi,\n\nI use Whiteout Mail to send and receive encrypted email. I would like to exchange encrypted messages with you as well.\n\nPlease install the Whiteout Mail application. This application makes it easy to read and write messages securely with PGP encryption applied.\n\nGo to the Whiteout Networks homepage to learn more and to download the application: https://whiteout.io\n\n', invitationMessage: 'Hi,\n\nI use Whiteout Mail to send and receive encrypted email. I would like to exchange encrypted messages with you as well.\n\nPlease install the Whiteout Mail application. This application makes it easy to read and write messages securely with PGP encryption applied.\n\nGo to the Whiteout Networks homepage to learn more and to download the application: https://whiteout.io\n\n',
@ -218,6 +215,3 @@ define(function(require) {
connDocNoInbox: 'We could not detect an IMAP inbox folder on {0}. Please have a look at the FAQ for information on how to fix this error.', connDocNoInbox: 'We could not detect an IMAP inbox folder on {0}. Please have a look at the FAQ for information on how to fix this error.',
connDocGenericError: 'There was an error connecting to {0}: {1}' connDocGenericError: 'There was an error connecting to {0}: {1}'
}; };
return app;
});

View File

@ -1,46 +1,46 @@
/** /**
* The main application controller * The main application controller
*/ */
define(function(require) {
'use strict'; 'use strict';
var axe = require('axe'), var axe = require('axe-logger'),
Auth = require('js/bo/auth'), Auth = require('./bo/auth'),
PGP = require('js/crypto/pgp'), PGP = require('./crypto/pgp'),
PgpMailer = require('pgpmailer'), PgpMailer = require('pgpmailer'),
OAuth = require('js/util/oauth'), OAuth = require('./util/oauth'),
PgpBuilder = require('pgpbuilder'), PgpBuilder = require('pgpbuilder'),
OutboxBO = require('js/bo/outbox'), OutboxBO = require('./bo/outbox'),
mailreader = require('mailreader'), mailreader = require('mailreader'),
ImapClient = require('imap-client'), ImapClient = require('imap-client'),
Crypto = require('js/crypto/crypto'), Crypto = require('./crypto/crypto'),
RestDAO = require('js/dao/rest-dao'), RestDAO = require('./dao/rest-dao'),
appConfig = require('js/app-config'), appConfig = require('./app-config'),
EmailDAO = require('js/dao/email-dao'), EmailDAO = require('./dao/email-dao'),
AdminDao = require('js/dao/admin-dao'), AdminDao = require('./dao/admin-dao'),
KeychainDAO = require('js/dao/keychain-dao'), KeychainDAO = require('./dao/keychain-dao'),
PublicKeyDAO = require('js/dao/publickey-dao'), PublicKeyDAO = require('./dao/publickey-dao'),
LawnchairDAO = require('js/dao/lawnchair-dao'), LawnchairDAO = require('./dao/lawnchair-dao'),
PrivateKeyDAO = require('js/dao/privatekey-dao'), PrivateKeyDAO = require('./dao/privatekey-dao'),
InvitationDAO = require('js/dao/invitation-dao'), InvitationDAO = require('./dao/invitation-dao'),
DeviceStorageDAO = require('js/dao/devicestorage-dao'), DeviceStorageDAO = require('./dao/devicestorage-dao'),
ConnectionDoctor = require('js/util/connection-doctor'), ConnectionDoctor = require('./util/connection-doctor'),
UpdateHandler = require('js/util/update/update-handler'), UpdateHandler = require('./util/update/update-handler'),
config = appConfig.config, config = appConfig.config,
str = appConfig.string; str = appConfig.string;
var self = {}; var ctrl = {};
/** /**
* Start the application. * Start the application.
*/ */
self.start = function(options, callback) { ctrl.start = function(options, callback) {
if (self.started) { if (ctrl.started) {
return callback(); return callback();
} }
self.started = true; ctrl.started = true;
self.onError = options.onError; ctrl.onError = options.onError;
// are we running in a cordova app or in a browser environment? // are we running in a cordova app or in a browser environment?
if (window.cordova) { if (window.cordova) {
@ -56,24 +56,24 @@ define(function(require) {
function onDeviceReady() { function onDeviceReady() {
axe.debug('Starting app.'); axe.debug('Starting app.');
self.buildModules(); ctrl.buildModules();
// Handle offline and online gracefully // Handle offline and online gracefully
window.addEventListener('online', self.onConnect.bind(self, self.onError)); window.addEventListener('online', ctrl.onConnect.bind(ctrl, ctrl.onError));
window.addEventListener('offline', self.onDisconnect.bind(self)); window.addEventListener('offline', ctrl.onDisconnect.bind(ctrl));
self._appConfigStore.init('app-config', callback); ctrl._appConfigStore.init('app-config', callback);
} }
}; };
/** /**
* Initialize the dependency tree. * Initialize the dependency tree.
*/ */
self.buildModules = function() { ctrl.buildModules = function() {
var lawnchairDao, restDao, pubkeyDao, privkeyDao, crypto, emailDao, keychain, pgp, userStorage, pgpbuilder, oauth, appConfigStore, auth; var lawnchairDao, restDao, pubkeyDao, privkeyDao, crypto, emailDao, keychain, pgp, userStorage, pgpbuilder, oauth, appConfigStore, auth;
// start the mailreader's worker thread // start the mailreader's worker thread
mailreader.startWorker(config.workerPath + '/../lib/mailreader-parser-worker.js'); mailreader.startWorker(config.workerPath + '/mailreader-parser-worker.min.js');
// init objects and inject dependencies // init objects and inject dependencies
restDao = new RestDAO(); restDao = new RestDAO();
@ -83,13 +83,13 @@ define(function(require) {
oauth = new OAuth(new RestDAO('https://www.googleapis.com')); oauth = new OAuth(new RestDAO('https://www.googleapis.com'));
crypto = new Crypto(); crypto = new Crypto();
self._pgp = pgp = new PGP(); ctrl._pgp = pgp = new PGP();
self._keychain = keychain = new KeychainDAO(lawnchairDao, pubkeyDao, privkeyDao, crypto, pgp); ctrl._keychain = keychain = new KeychainDAO(lawnchairDao, pubkeyDao, privkeyDao, crypto, pgp);
keychain.requestPermissionForKeyUpdate = function(params, callback) { keychain.requestPermissionForKeyUpdate = function(params, callback) {
var message = params.newKey ? str.updatePublicKeyMsgNewKey : str.updatePublicKeyMsgRemovedKey; var message = params.newKey ? str.updatePublicKeyMsgNewKey : str.updatePublicKeyMsgRemovedKey;
message = message.replace('{0}', params.userId); message = message.replace('{0}', params.userId);
self.onError({ ctrl.onError({
title: str.updatePublicKeyTitle, title: str.updatePublicKeyTitle,
message: message, message: message,
positiveBtnStr: str.updatePublicKeyPosBtn, positiveBtnStr: str.updatePublicKeyPosBtn,
@ -99,40 +99,40 @@ define(function(require) {
}); });
}; };
self._appConfigStore = appConfigStore = new DeviceStorageDAO(new LawnchairDAO()); ctrl._appConfigStore = appConfigStore = new DeviceStorageDAO(new LawnchairDAO());
self._auth = auth = new Auth(appConfigStore, oauth, pgp); ctrl._auth = auth = new Auth(appConfigStore, oauth, pgp);
self._userStorage = userStorage = new DeviceStorageDAO(lawnchairDao); ctrl._userStorage = userStorage = new DeviceStorageDAO(lawnchairDao);
self._invitationDao = new InvitationDAO(restDao); ctrl._invitationDao = new InvitationDAO(restDao);
self._pgpbuilder = pgpbuilder = new PgpBuilder(); ctrl._pgpbuilder = pgpbuilder = new PgpBuilder();
self._emailDao = emailDao = new EmailDAO(keychain, pgp, userStorage, pgpbuilder, mailreader); ctrl._emailDao = emailDao = new EmailDAO(keychain, pgp, userStorage, pgpbuilder, mailreader);
self._outboxBo = new OutboxBO(emailDao, keychain, userStorage); ctrl._outboxBo = new OutboxBO(emailDao, keychain, userStorage);
self._updateHandler = new UpdateHandler(appConfigStore, userStorage, auth); ctrl._updateHandler = new UpdateHandler(appConfigStore, userStorage, auth);
self._adminDao = new AdminDao(new RestDAO(config.adminUrl)); ctrl._adminDao = new AdminDao(new RestDAO(config.adminUrl));
self._doctor = new ConnectionDoctor(); ctrl._doctor = new ConnectionDoctor();
emailDao.onError = self.onError; emailDao.onError = ctrl.onError;
}; };
/** /**
* Calls runtime hooks to check if an app update is available. * Calls runtime hooks to check if an app update is available.
*/ */
self.checkForUpdate = function() { ctrl.checkForUpdate = function() {
self._updateHandler.checkForUpdate(self.onError); ctrl._updateHandler.checkForUpdate(ctrl.onError);
}; };
/** /**
* Instanciate the mail email data access object and its dependencies. Login to imap on init. * Instanciate the mail email data access object and its dependencies. Login to imap on init.
*/ */
self.init = function(options, callback) { ctrl.init = function(options, callback) {
// init user's local database // init user's local database
self._userStorage.init(options.emailAddress, function(err) { ctrl._userStorage.init(options.emailAddress, function(err) {
if (err) { if (err) {
callback(err); callback(err);
return; return;
} }
// Migrate the databases if necessary // Migrate the databases if necessary
self._updateHandler.update(onUpdate); ctrl._updateHandler.update(onUpdate);
}); });
function onUpdate(err) { function onUpdate(err) {
@ -152,7 +152,7 @@ define(function(require) {
}; };
// init email dao // init email dao
self._emailDao.init({ ctrl._emailDao.init({
account: account account: account
}, function(err, keypair) { }, function(err, keypair) {
if (err) { if (err) {
@ -168,34 +168,32 @@ define(function(require) {
/** /**
* Check if the user agent is online. * Check if the user agent is online.
*/ */
self.isOnline = function() { ctrl.isOnline = function() {
return navigator.onLine; return navigator.onLine;
}; };
/** /**
* Event handler that is called when the user agent goes offline. * Event handler that is called when the user agent goes offline.
*/ */
self.onDisconnect = function() { ctrl.onDisconnect = function() {
self._emailDao.onDisconnect(); ctrl._emailDao.onDisconnect();
}; };
/** /**
* Log the current user out by clear the app config store and deleting instances of imap-client and pgp-mailer. * Log the current user out by clear the app config store and deleting instances of imap-client and pgp-mailer.
*/ */
self.logout = function() { ctrl.logout = function() {
var self = this;
// clear app config store // clear app config store
self._auth.logout(function(err) { ctrl._auth.logout(function(err) {
if (err) { if (err) {
self.onError(err); ctrl.onError(err);
return; return;
} }
// delete instance of imap-client and pgp-mailer // delete instance of imap-client and pgp-mailer
self._emailDao.onDisconnect(function(err) { ctrl._emailDao.onDisconnect(function(err) {
if (err) { if (err) {
self.onError(err); ctrl.onError(err);
return; return;
} }
@ -208,14 +206,14 @@ define(function(require) {
/** /**
* Event that is called when the user agent goes online. This create new instances of the imap-client and pgp-mailer and connects to the mail server. * Event that is called when the user agent goes online. This create new instances of the imap-client and pgp-mailer and connects to the mail server.
*/ */
self.onConnect = function(callback) { ctrl.onConnect = function(callback) {
if (!self.isOnline() || !self._emailDao || !self._emailDao._account) { if (!ctrl.isOnline() || !ctrl._emailDao || !ctrl._emailDao._account) {
// prevent connection infinite loop // prevent connection infinite loop
callback(); callback();
return; return;
} }
self._auth.getCredentials(function(err, credentials) { ctrl._auth.getCredentials(function(err, credentials) {
if (err) { if (err) {
callback(err); callback(err);
return; return;
@ -228,22 +226,25 @@ define(function(require) {
// add the maximum update batch size for imap folders to the imap configuration // add the maximum update batch size for imap folders to the imap configuration
credentials.imap.maxUpdateSize = config.imapUpdateBatchSize; credentials.imap.maxUpdateSize = config.imapUpdateBatchSize;
var pgpMailer = new PgpMailer(credentials.smtp, self._pgpbuilder); // tls socket worker path for multithreaded tls in non-native tls environments
credentials.imap.tlsWorkerPath = credentials.smtp.tlsWorkerPath = config.workerPath + '/tcp-socket-tls-worker.min.js';
var pgpMailer = new PgpMailer(credentials.smtp, ctrl._pgpbuilder);
var imapClient = new ImapClient(credentials.imap); var imapClient = new ImapClient(credentials.imap);
imapClient.onError = onConnectionError; imapClient.onError = onConnectionError;
pgpMailer.onError = onConnectionError; pgpMailer.onError = onConnectionError;
// certificate update handling // certificate update handling
imapClient.onCert = self._auth.handleCertificateUpdate.bind(self._auth, 'imap', self.onConnect, self.onError); imapClient.onCert = ctrl._auth.handleCertificateUpdate.bind(ctrl._auth, 'imap', ctrl.onConnect, ctrl.onError);
pgpMailer.onCert = self._auth.handleCertificateUpdate.bind(self._auth, 'smtp', self.onConnect, self.onError); pgpMailer.onCert = ctrl._auth.handleCertificateUpdate.bind(ctrl._auth, 'smtp', ctrl.onConnect, ctrl.onError);
// after-setup configuration depending on the provider: // after-setup configuration depending on the provider:
// gmail does not require you to upload to the sent items folder // gmail does not require you to upload to the sent items folder
// after successful sending, whereas most other providers do // after successful sending, whereas most other providers do
self._emailDao.ignoreUploadOnSent = !!(config[self._auth.provider] && config[self._auth.provider].ignoreUploadOnSent); ctrl._emailDao.ignoreUploadOnSent = !!(config[ctrl._auth.provider] && config[ctrl._auth.provider].ignoreUploadOnSent);
// connect to clients // connect to clients
self._emailDao.onConnect({ ctrl._emailDao.onConnect({
imapClient: imapClient, imapClient: imapClient,
pgpMailer: pgpMailer pgpMailer: pgpMailer
}, callback); }, callback);
@ -255,7 +256,7 @@ define(function(require) {
setTimeout(function() { setTimeout(function() {
axe.debug('Reconnecting...'); axe.debug('Reconnecting...');
// re-init client modules on error // re-init client modules on error
self.onConnect(function(err) { ctrl.onConnect(function(err) {
if (err) { if (err) {
axe.error('Reconnect attempt failed! ' + (err.errMsg || err.message) + (err.stack ? ('\n' + err.stack) : '')); axe.error('Reconnect attempt failed! ' + (err.errMsg || err.message) + (err.stack ? ('\n' + err.stack) : ''));
return; return;
@ -267,5 +268,4 @@ define(function(require) {
} }
}; };
return self; module.exports = ctrl;
});

View File

@ -14,64 +14,26 @@ if (typeof window.applicationCache !== 'undefined') {
}; };
} }
// hey Angular, we're bootstrapping manually! var DialogCtrl = require('./controller/dialog'),
window.name = 'NG_DEFER_BOOTSTRAP!'; PopoverCtrl = require('./controller/popover'),
AddAccountCtrl = require('./controller/add-account'),
requirejs([ AccountCtrl = require('./controller/account'),
'angular', SetPassphraseCtrl = require('./controller/set-passphrase'),
'js/controller/dialog', PrivateKeyUploadCtrl = require('./controller/privatekey-upload'),
'js/controller/popover', ContactsCtrl = require('./controller/contacts'),
'js/controller/add-account', AboutCtrl = require('./controller/about'),
'js/controller/account', LoginCtrl = require('./controller/login'),
'js/controller/set-passphrase', LoginInitialCtrl = require('./controller/login-initial'),
'js/controller/privatekey-upload', LoginNewDeviceCtrl = require('./controller/login-new-device'),
'js/controller/contacts', LoginExistingCtrl = require('./controller/login-existing'),
'js/controller/about', LoginPrivateKeyDownloadCtrl = require('./controller/login-privatekey-download'),
'js/controller/login', LoginSetCredentialsCtrl = require('./controller/login-set-credentials'),
'js/controller/login-initial', MailListCtrl = require('./controller/mail-list'),
'js/controller/login-new-device', ReadCtrl = require('./controller/read'),
'js/controller/login-existing', WriteCtrl = require('./controller/write'),
'js/controller/login-privatekey-download', NavigationCtrl = require('./controller/navigation'),
'js/controller/login-set-credentials', errorUtil = require('./util/error'),
'js/controller/mail-list', backButtonUtil = require('./util/backbutton-handler');
'js/controller/read',
'js/controller/write',
'js/controller/navigation',
'js/crypto/util',
'js/util/error',
'js/util/backbutton-handler',
'fastclick',
'angularRoute',
'angularAnimate',
'ngInfiniteScroll',
'ngTagsInput'
], function(
angular,
DialogCtrl,
PopoverCtrl,
AddAccountCtrl,
AccountCtrl,
SetPassphraseCtrl,
PrivateKeyUploadCtrl,
ContactsCtrl,
AboutCtrl,
LoginCtrl,
LoginInitialCtrl,
LoginNewDeviceCtrl,
LoginExistingCtrl,
LoginPrivateKeyDownloadCtrl,
LoginSetCredentialsCtrl,
MailListCtrl,
ReadCtrl,
WriteCtrl,
NavigationCtrl,
util,
errorUtil,
backButtonUtil,
FastClick
) {
// reset window.name
window.name = util.UUID();
// init main angular module including dependencies // init main angular module including dependencies
var app = angular.module('mail', [ var app = angular.module('mail', [
@ -153,9 +115,3 @@ requirejs([
app.controller('AboutCtrl', AboutCtrl); app.controller('AboutCtrl', AboutCtrl);
app.controller('DialogCtrl', DialogCtrl); app.controller('DialogCtrl', DialogCtrl);
app.controller('PopoverCtrl', PopoverCtrl); app.controller('PopoverCtrl', PopoverCtrl);
// manually bootstrap angular due to require.js
angular.element().ready(function() {
angular.bootstrap(document, ['mail']);
});
});

View File

@ -1,8 +1,7 @@
define(function(require) {
'use strict'; 'use strict';
var axe = require('axe'), var axe = require('axe-logger'),
str = require('js/app-config').string; str = require('../app-config').string;
var EMAIL_ADDR_DB_KEY = 'emailaddress'; var EMAIL_ADDR_DB_KEY = 'emailaddress';
var USERNAME_DB_KEY = 'username'; var USERNAME_DB_KEY = 'username';
@ -449,5 +448,4 @@ define(function(require) {
}); });
}; };
return Auth; module.exports = Auth;
});

View File

@ -1,9 +1,7 @@
define(function(require) {
'use strict'; 'use strict';
var _ = require('underscore'), var util = require('crypto-lib').util,
util = require('js/crypto/util'), config = require('../app-config').config,
config = require('js/app-config').config,
outboxDb = 'email_OUTBOX'; outboxDb = 'email_OUTBOX';
/** /**
@ -228,5 +226,4 @@ define(function(require) {
} }
}; };
return OutboxBO; module.exports = OutboxBO;
});

View File

@ -1,7 +1,6 @@
define(function(require) {
'use strict'; 'use strict';
var cfg = require('js/app-config').config; var cfg = require('../app-config').config;
// //
// Controller // Controller
@ -27,5 +26,4 @@ define(function(require) {
// //
}; };
return AboutCtrl; module.exports = AboutCtrl;
});

View File

@ -1,9 +1,8 @@
define(function(require) {
'use strict'; 'use strict';
var appController = require('js/app-controller'), var appController = require('../app-controller'),
dl = require('js/util/download'), dl = require('../util/download'),
config = require('js/app-config').config, config = require('../app-config').config,
pgp, keychain, userId; pgp, keychain, userId;
// //
@ -57,5 +56,4 @@ define(function(require) {
}; };
}; };
return AccountCtrl; module.exports = AccountCtrl;
});

View File

@ -1,8 +1,7 @@
define(function(require) {
'use strict'; 'use strict';
var appCtrl = require('js/app-controller'), var appCtrl = require('../app-controller'),
cfg = require('js/app-config').config; cfg = require('../app-config').config;
var AddAccountCtrl = function($scope, $location, $routeParams) { var AddAccountCtrl = function($scope, $location, $routeParams) {
if (!appCtrl._auth && !$routeParams.dev) { if (!appCtrl._auth && !$routeParams.dev) {
@ -116,5 +115,4 @@ define(function(require) {
}; };
}; };
return AddAccountCtrl; module.exports = AddAccountCtrl;
});

View File

@ -1,9 +1,6 @@
define(function(require) {
'use strict'; 'use strict';
var angular = require('angular'), var appController = require('../app-controller'),
_ = require('underscore'),
appController = require('js/app-controller'),
keychain, pgp; keychain, pgp;
// //
@ -139,5 +136,4 @@ define(function(require) {
}; };
}); });
return ContactsCtrl; module.exports = ContactsCtrl;
});

View File

@ -1,4 +1,3 @@
define(function() {
'use strict'; 'use strict';
var DialogCtrl = function($scope) { var DialogCtrl = function($scope) {
@ -12,5 +11,4 @@ define(function() {
}; };
}; };
return DialogCtrl; module.exports = DialogCtrl;
});

View File

@ -1,7 +1,6 @@
define(function(require) {
'use strict'; 'use strict';
var appController = require('js/app-controller'); var appController = require('../app-controller');
var LoginExistingCtrl = function($scope, $location, $routeParams) { var LoginExistingCtrl = function($scope, $location, $routeParams) {
if (!appController._emailDao && !$routeParams.dev) { if (!appController._emailDao && !$routeParams.dev) {
@ -69,5 +68,4 @@ define(function(require) {
} }
}; };
return LoginExistingCtrl; module.exports = LoginExistingCtrl;
});

View File

@ -1,7 +1,6 @@
define(function(require) {
'use strict'; 'use strict';
var appController = require('js/app-controller'); var appController = require('../app-controller');
var LoginInitialCtrl = function($scope, $location, $routeParams) { var LoginInitialCtrl = function($scope, $location, $routeParams) {
if (!appController._emailDao && !$routeParams.dev) { if (!appController._emailDao && !$routeParams.dev) {
@ -117,5 +116,4 @@ define(function(require) {
}; };
}; };
return LoginInitialCtrl; module.exports = LoginInitialCtrl;
});

View File

@ -1,8 +1,6 @@
define(function(require) {
'use strict'; 'use strict';
var angular = require('angular'), var appController = require('../app-controller');
appController = require('js/app-controller');
var LoginExistingCtrl = function($scope, $location, $routeParams) { var LoginExistingCtrl = function($scope, $location, $routeParams) {
if (!appController._emailDao && !$routeParams.dev) { if (!appController._emailDao && !$routeParams.dev) {
@ -137,5 +135,4 @@ define(function(require) {
}; };
}); });
return LoginExistingCtrl; module.exports = LoginExistingCtrl;
});

View File

@ -1,7 +1,6 @@
define(function(require) {
'use strict'; 'use strict';
var appController = require('js/app-controller'); var appController = require('../app-controller');
var LoginPrivateKeyDownloadCtrl = function($scope, $location, $routeParams) { var LoginPrivateKeyDownloadCtrl = function($scope, $location, $routeParams) {
if (!appController._emailDao && !$routeParams.dev) { if (!appController._emailDao && !$routeParams.dev) {
@ -130,5 +129,4 @@ define(function(require) {
}; };
}; };
return LoginPrivateKeyDownloadCtrl; module.exports = LoginPrivateKeyDownloadCtrl;
});

View File

@ -1,12 +1,11 @@
define(function(require) {
'use strict'; 'use strict';
var ENCRYPTION_METHOD_NONE = 0; var ENCRYPTION_METHOD_NONE = 0;
var ENCRYPTION_METHOD_STARTTLS = 1; var ENCRYPTION_METHOD_STARTTLS = 1;
var ENCRYPTION_METHOD_TLS = 2; var ENCRYPTION_METHOD_TLS = 2;
var appCtrl = require('js/app-controller'), var appCtrl = require('../app-controller'),
config = require('js/app-config').config; config = require('../app-config').config;
var SetCredentialsCtrl = function($scope, $location, $routeParams) { var SetCredentialsCtrl = function($scope, $location, $routeParams) {
if (!appCtrl._auth && !$routeParams.dev) { if (!appCtrl._auth && !$routeParams.dev) {
@ -116,5 +115,4 @@ define(function(require) {
}; };
}; };
return SetCredentialsCtrl; module.exports = SetCredentialsCtrl;
});

View File

@ -1,7 +1,6 @@
define(function(require) {
'use strict'; 'use strict';
var appController = require('js/app-controller'); var appController = require('../app-controller');
var LoginCtrl = function($scope, $location) { var LoginCtrl = function($scope, $location) {
@ -99,5 +98,4 @@ define(function(require) {
} }
}; };
return LoginCtrl; module.exports = LoginCtrl;
});

View File

@ -1,10 +1,7 @@
define(function(require) {
'use strict'; 'use strict';
var angular = require('angular'), var appController = require('../app-controller'),
_ = require('underscore'), notification = require('../util/notification'),
appController = require('js/app-controller'),
notification = require('js/util/notification'),
emailDao, outboxBo, keychainDao, searchTimeout, firstSelect; emailDao, outboxBo, keychainDao, searchTimeout, firstSelect;
var INIT_DISPLAY_LEN = 20, var INIT_DISPLAY_LEN = 20,
@ -596,5 +593,4 @@ define(function(require) {
return dummies; return dummies;
} }
return MailListCtrl; module.exports = MailListCtrl;
});

View File

@ -1,12 +1,9 @@
define(function(require) {
'use strict'; 'use strict';
var angular = require('angular'), var appController = require('../app-controller'),
appController = require('js/app-controller'), config = require('../app-config').config,
config = require('js/app-config').config, notification = require('../util/notification'),
notification = require('js/util/notification'), backBtnHandler = require('../util/backbutton-handler'),
backBtnHandler = require('js/util/backbutton-handler'),
_ = require('underscore'),
emailDao, outboxBo; emailDao, outboxBo;
// //
@ -206,5 +203,4 @@ define(function(require) {
}; };
}); });
return NavigationCtrl; module.exports = NavigationCtrl;
});

View File

@ -1,8 +1,5 @@
define(function(require) {
'use strict'; 'use strict';
var angular = require('angular');
// //
// Controller // Controller
// //
@ -43,5 +40,4 @@ define(function(require) {
}; };
}); });
return PopoverCtrl; module.exports = PopoverCtrl;
});

View File

@ -1,9 +1,7 @@
define(function(require) {
'use strict'; 'use strict';
var angular = require('angular'), var appController = require('../app-controller'),
appController = require('js/app-controller'), util = require('crypto-lib').util,
util = require('js/crypto/util'),
keychain, pgp; keychain, pgp;
var PrivateKeyUploadCtrl = function($scope) { var PrivateKeyUploadCtrl = function($scope) {
@ -200,5 +198,4 @@ define(function(require) {
}; };
}); });
return PrivateKeyUploadCtrl; module.exports = PrivateKeyUploadCtrl;
});

View File

@ -1,4 +1,3 @@
(function() {
'use strict'; 'use strict';
// set listener for event from main window // set listener for event from main window
@ -214,5 +213,3 @@
view.style['-webkit-transform'] = scale; view.style['-webkit-transform'] = scale;
view.style.transform = scale; view.style.transform = scale;
} }
})();

View File

@ -1,10 +1,8 @@
define(function(require) {
'use strict'; 'use strict';
var appController = require('js/app-controller'), var appController = require('../app-controller'),
download = require('js/util/download'), download = require('../util/download'),
angular = require('angular'), str = require('../app-config').string,
str = require('js/app-config').string,
emailDao, invitationDao, outbox, pgp, keychain; emailDao, invitationDao, outbox, pgp, keychain;
// //
@ -282,5 +280,4 @@ define(function(require) {
}; };
}); });
return ReadCtrl; module.exports = ReadCtrl;
});

View File

@ -1,7 +1,6 @@
define(function(require) {
'use strict'; 'use strict';
var appController = require('js/app-controller'), var appController = require('../app-controller'),
pgp, keychain; pgp, keychain;
// //
@ -134,5 +133,4 @@ define(function(require) {
} }
}; };
return SetPassphraseCtrl; module.exports = SetPassphraseCtrl;
});

View File

@ -1,12 +1,9 @@
define(function(require) {
'use strict'; 'use strict';
var angular = require('angular'), var appController = require('../app-controller'),
_ = require('underscore'), axe = require('axe-logger'),
appController = require('js/app-controller'), util = require('crypto-lib').util,
axe = require('axe'), str = require('../app-config').string,
util = require('js/crypto/util'),
str = require('js/app-config').string,
pgp, emailDao, outbox, keychainDao, auth; pgp, emailDao, outbox, keychainDao, auth;
// //
@ -530,5 +527,4 @@ define(function(require) {
}; };
}); });
return WriteCtrl; module.exports = WriteCtrl;
});

View File

@ -2,15 +2,13 @@
* High level crypto api that invokes native crypto (if available) and * High level crypto api that invokes native crypto (if available) and
* gracefully degrades to JS crypto (if unavailable) * gracefully degrades to JS crypto (if unavailable)
*/ */
define(function(require) {
'use strict'; 'use strict';
var aes = require('js/crypto/aes-gcm'), var aes = require('crypto-lib').aes,
pbkdf2 = require('js/crypto/pbkdf2'), pbkdf2 = require('./pbkdf2'),
config = require('js/app-config').config, config = require('../app-config').config,
axe = require('axe'); axe = require('axe-logger');
var PBKDF2_WORKER = '/crypto/pbkdf2-worker.js';
var Crypto = function() {}; var Crypto = function() {};
@ -61,7 +59,7 @@ define(function(require) {
*/ */
Crypto.prototype.deriveKey = function(password, salt, keySize, callback) { Crypto.prototype.deriveKey = function(password, salt, keySize, callback) {
startWorker({ startWorker({
script: PBKDF2_WORKER, script: config.workerPath + '/pbkdf2-worker.min.js',
args: { args: {
password: password, password: password,
salt: salt, salt: salt,
@ -82,7 +80,7 @@ define(function(require) {
// check for WebWorker support // check for WebWorker support
if (window.Worker) { if (window.Worker) {
// init webworker thread // init webworker thread
var worker = new Worker(config.workerPath + options.script); var worker = new Worker(options.script);
worker.onmessage = function(e) { worker.onmessage = function(e) {
if (e.data.err) { if (e.data.err) {
options.callback(e.data.err); options.callback(e.data.err);
@ -119,5 +117,4 @@ define(function(require) {
options.callback(null, result); options.callback(null, result);
} }
return Crypto; module.exports = Crypto;
});

View File

@ -1,22 +1,14 @@
(function() {
'use strict'; 'use strict';
// import web worker dependencies importScripts('forge.min.js');
importScripts('../../lib/require.js');
var pbkdf2 = require('./pbkdf2');
/** /**
* In the web worker thread context, 'this' and 'self' can be used as a global * In the web worker thread context, 'this' and 'self' can be used as a global
* variable namespace similar to the 'window' object in the main thread * variable namespace similar to the 'window' object in the main thread
*/ */
self.onmessage = function(e) { self.onmessage = function(e) {
// fetch dependencies via require.js
require(['../../require-config'], function() {
require.config({
baseUrl: '../../lib'
});
require(['js/crypto/pbkdf2'], function(pbkdf2) {
var i = e.data, var i = e.data,
key = null; key = null;
@ -30,9 +22,4 @@
// pass output back to main thread // pass output back to main thread
self.postMessage(key); self.postMessage(key);
});
});
}; };
}());

View File

@ -1,10 +1,10 @@
/** /**
* A Wrapper for Forge's PBKDF2 function * A Wrapper for Forge's PBKDF2 function
*/ */
define(['forge'], function(forge) {
'use strict'; 'use strict';
var self = {}; var pbkdf2 = {};
/** /**
* PBKDF2-HMAC-SHA256 key derivation with a random salt and 10000 iterations * PBKDF2-HMAC-SHA256 key derivation with a random salt and 10000 iterations
@ -13,7 +13,7 @@ define(['forge'], function(forge) {
* @param {String} keySize The key size in bits * @param {String} keySize The key size in bits
* @return {String} The base64 encoded key * @return {String} The base64 encoded key
*/ */
self.getKey = function(password, salt, keySize) { pbkdf2.getKey = function(password, salt, keySize) {
var saltUtf8 = forge.util.decode64(salt); var saltUtf8 = forge.util.decode64(salt);
var md = forge.md.sha256.create(); var md = forge.md.sha256.create();
var key = forge.pkcs5.pbkdf2(password, saltUtf8, 10000, keySize / 8, md); var key = forge.pkcs5.pbkdf2(password, saltUtf8, 10000, keySize / 8, md);
@ -21,5 +21,4 @@ define(['forge'], function(forge) {
return forge.util.encode64(key); return forge.util.encode64(key);
}; };
return self; module.exports = pbkdf2;
});

View File

@ -1,16 +1,15 @@
/** /**
* High level crypto api that handles all calls to OpenPGP.js * High level crypto api that handles all calls to OpenPGP.js
*/ */
define(function(require) {
'use strict'; 'use strict';
var openpgp = require('openpgp'), var util = openpgp.util,
util = require('openpgp').util, config = require('../app-config').config;
config = require('js/app-config').config;
var PGP = function() { var PGP = function() {
openpgp.config.prefer_hash_algorithm = openpgp.enums.hash.sha256; openpgp.config.prefer_hash_algorithm = openpgp.enums.hash.sha256;
openpgp.initWorker(config.workerPath + '/../lib/openpgp/openpgp.worker.js'); openpgp.initWorker(config.workerPath + '/openpgp.worker.js');
}; };
/** /**
@ -448,5 +447,4 @@ define(function(require) {
return true; return true;
} }
return PGP; module.exports = PGP;
});

View File

@ -1,4 +1,3 @@
define(function() {
'use strict'; 'use strict';
var AdminDAO = function(restDao) { var AdminDAO = function(restDao) {
@ -59,5 +58,4 @@ define(function() {
}); });
}; };
return AdminDAO; module.exports = AdminDAO;
});

View File

@ -1,10 +1,7 @@
/** /**
* High level storage api that handles all persistence on the device. If * High level storage api that handles all persistence on the device.
* SQLcipher/SQLite is available, all data is securely persisted there,
* through transparent encryption. If not, the crypto API is
* used to encrypt data on the fly before persisting via a JSON store.
*/ */
define(function() {
'use strict'; 'use strict';
var DeviceStorageDAO = function(localDbDao) { var DeviceStorageDAO = function(localDbDao) {
@ -93,5 +90,4 @@ define(function() {
return key; return key;
} }
return DeviceStorageDAO; module.exports = DeviceStorageDAO;
});

View File

@ -1,11 +1,8 @@
define(function(require) {
'use strict'; 'use strict';
var util = require('js/crypto/util'), var util = require('crypto-lib').util,
_ = require('underscore'), config = require('../app-config').config,
config = require('js/app-config').config, str = require('../app-config').string;
str = require('js/app-config').string;
// //
// //
@ -1727,5 +1724,4 @@ define(function(require) {
}); });
} }
return EmailDAO; module.exports = EmailDAO;
});

View File

@ -1,4 +1,3 @@
define(function() {
'use strict'; 'use strict';
/** /**
@ -58,5 +57,4 @@ define(function() {
} }
}; };
return InvitationDAO; module.exports = InvitationDAO;
});

View File

@ -2,12 +2,11 @@
* A high-level Data-Access Api for handling Keypair synchronization * A high-level Data-Access Api for handling Keypair synchronization
* between the cloud service and the device's local storage * between the cloud service and the device's local storage
*/ */
define(function(require) {
'use strict'; 'use strict';
var _ = require('underscore'), var util = require('crypto-lib').util,
util = require('js/crypto/util'), config = require('../app-config').config;
config = require('js/app-config').config;
var DB_PUBLICKEY = 'publickey', var DB_PUBLICKEY = 'publickey',
DB_PRIVATEKEY = 'privatekey', DB_PRIVATEKEY = 'privatekey',
@ -934,5 +933,4 @@ define(function(require) {
this._localDbDao.persist(prkLookupKey, privkey, callback); this._localDbDao.persist(prkLookupKey, privkey, callback);
}; };
return KeychainDAO; module.exports = KeychainDAO;
});

View File

@ -1,13 +1,8 @@
/** /**
* Handles generic caching of JSON objects in a lawnchair adapter * Handles generic caching of JSON objects in a lawnchair adapter
*/ */
define(function(require) {
'use strict';
var _ = require('underscore'), 'use strict';
Lawnchair = require('lawnchair');
require('lawnchairSQL');
require('lawnchairIDB');
var LawnchairDAO = function() {}; var LawnchairDAO = function() {};
@ -218,5 +213,4 @@ define(function(require) {
this._db.nuke(callback); this._db.nuke(callback);
}; };
return LawnchairDAO; module.exports = LawnchairDAO;
});

View File

@ -1,4 +1,3 @@
define(function() {
'use strict'; 'use strict';
var PrivateKeyDAO = function(restDao) { var PrivateKeyDAO = function(restDao) {
@ -194,5 +193,4 @@ define(function() {
}, callback); }, callback);
}; };
return PrivateKeyDAO; module.exports = PrivateKeyDAO;
});

View File

@ -1,4 +1,3 @@
define(function() {
'use strict'; 'use strict';
var PublicKeyDAO = function(restDao) { var PublicKeyDAO = function(restDao) {
@ -101,5 +100,4 @@ define(function() {
this._restDao.remove(uri, callback); this._restDao.remove(uri, callback);
}; };
return PublicKeyDAO; module.exports = PublicKeyDAO;
});

View File

@ -1,7 +1,6 @@
define(function(require) {
'use strict'; 'use strict';
var config = require('js/app-config').config; var config = require('../app-config').config;
var RestDAO = function(baseUri) { var RestDAO = function(baseUri) {
if (baseUri) { if (baseUri) {
@ -119,5 +118,4 @@ define(function(require) {
xhr.send(options.payload ? JSON.stringify(options.payload) : undefined); xhr.send(options.payload ? JSON.stringify(options.payload) : undefined);
}; };
return RestDAO; module.exports = RestDAO;
});

View File

@ -1,7 +1,6 @@
define(function(require) {
'use strict'; 'use strict';
var axe = require('axe'), var axe = require('axe-logger'),
DEBUG_TAG = 'backbutton handler'; DEBUG_TAG = 'backbutton handler';
/** /**
@ -53,5 +52,4 @@ define(function(require) {
} }
} }
return backBtnHandler; module.exports = backBtnHandler;
});

View File

@ -1,12 +1,11 @@
define(function(require) {
'use strict'; 'use strict';
var TCPSocket = require('tcp-socket'), var TCPSocket = require('tcp-socket'),
appConfig = require('js/app-config'), appConfig = require('../app-config'),
cfg = appConfig.config, cfg = appConfig.config,
strings = appConfig.string, strings = appConfig.string,
ImapClient = require('imap-client'), ImapClient = require('imap-client'),
SmtpClient = require('smtpclient'); SmtpClient = require('wo-smtpclient');
/** /**
* The connection doctor can check your connection. In essence, it reconstructs what happens when * The connection doctor can check your connection. In essence, it reconstructs what happens when
@ -31,6 +30,8 @@ define(function(require) {
var GENERIC_ERROR = ConnectionDoctor.GENERIC_ERROR = 48; var GENERIC_ERROR = ConnectionDoctor.GENERIC_ERROR = 48;
var WORKER_PATH = cfg.workerPath + '/tcp-socket-tls-worker.min.js';
// //
// Public API // Public API
// //
@ -53,6 +54,7 @@ define(function(require) {
secure: this.credentials.imap.secure, secure: this.credentials.imap.secure,
ignoreTLS: this.credentials.imap.ignoreTLS, ignoreTLS: this.credentials.imap.ignoreTLS,
ca: this.credentials.imap.ca, ca: this.credentials.imap.ca,
tlsWorkerPath: WORKER_PATH,
auth: { auth: {
user: this.credentials.username, user: this.credentials.username,
pass: this.credentials.password, pass: this.credentials.password,
@ -64,6 +66,7 @@ define(function(require) {
useSecureTransport: this.credentials.smtp.secure, useSecureTransport: this.credentials.smtp.secure,
ignoreTLS: this.credentials.smtp.ignoreTLS, ignoreTLS: this.credentials.smtp.ignoreTLS,
ca: this.credentials.smtp.ca, ca: this.credentials.smtp.ca,
tlsWorkerPath: WORKER_PATH,
auth: { auth: {
user: this.credentials.username, user: this.credentials.username,
pass: this.credentials.password, pass: this.credentials.password,
@ -157,7 +160,8 @@ define(function(require) {
socket = TCPSocket.open(options.host, options.port, { socket = TCPSocket.open(options.host, options.port, {
binaryType: 'arraybuffer', binaryType: 'arraybuffer',
useSecureTransport: options.secure, useSecureTransport: options.secure,
ca: options.ca ca: options.ca,
tlsWorkerPath: WORKER_PATH
}); });
socket.ondata = function() {}; // we don't actually care about the data socket.ondata = function() {}; // we don't actually care about the data
@ -291,5 +295,4 @@ define(function(require) {
return error; return error;
} }
return ConnectionDoctor; module.exports = ConnectionDoctor;
});

View File

@ -1,7 +1,6 @@
define(function(require) {
'use strict'; 'use strict';
var util = require('js/crypto/util'); var util = require('crypto-lib').util;
var dl = {}; var dl = {};
@ -56,5 +55,4 @@ define(function(require) {
} }
}; };
return dl; module.exports = dl;
});

View File

@ -1,7 +1,6 @@
define(function(require) {
'use strict'; 'use strict';
var axe = require('axe'); var axe = require('axe-logger');
var er = {}; var er = {};
er.attachHandler = function(scope) { er.attachHandler = function(scope) {
@ -31,5 +30,4 @@ define(function(require) {
}; };
}; };
return er; module.exports = er;
});

View File

@ -1,12 +1,11 @@
define(function(require) {
'use strict'; 'use strict';
var cfg = require('js/app-config').config; var cfg = require('../app-config').config;
var self = {}; var notif = {};
if (window.Notification) { if (window.Notification) {
self.hasPermission = Notification.permission === "granted"; notif.hasPermission = Notification.permission === "granted";
} }
/** /**
@ -18,18 +17,18 @@ define(function(require) {
* @param {Function} options.onClick (optional) callback when the notification is clicked * @param {Function} options.onClick (optional) callback when the notification is clicked
* @returns {Notification} A notification instance * @returns {Notification} A notification instance
*/ */
self.create = function(options) { notif.create = function(options) {
options.onClick = options.onClick || function() {}; options.onClick = options.onClick || function() {};
if (!window.Notification) { if (!window.Notification) {
return; return;
} }
if (!self.hasPermission) { if (!notif.hasPermission) {
// don't wait until callback returns // don't wait until callback returns
Notification.requestPermission(function(permission) { Notification.requestPermission(function(permission) {
if (permission === "granted") { if (permission === "granted") {
self.hasPermission = true; notif.hasPermission = true;
} }
}); });
} }
@ -52,9 +51,8 @@ define(function(require) {
return notification; return notification;
}; };
self.close = function(notification) { notif.close = function(notification) {
notification.close(); notification.close();
}; };
return self; module.exports = notif;
});

View File

@ -1,4 +1,3 @@
define(function() {
'use strict'; 'use strict';
var OAuth = function(googleApi) { var OAuth = function(googleApi) {
@ -97,5 +96,4 @@ define(function() {
}); });
}; };
return OAuth; module.exports = OAuth;
});

View File

@ -1,13 +1,12 @@
define(function(require) {
'use strict'; 'use strict';
var axe = require('axe'), var axe = require('axe-logger'),
cfg = require('js/app-config').config, cfg = require('../../app-config').config,
updateV1 = require('js/util/update/update-v1'), updateV1 = require('./update-v1'),
updateV2 = require('js/util/update/update-v2'), updateV2 = require('./update-v2'),
updateV3 = require('js/util/update/update-v3'), updateV3 = require('./update-v3'),
updateV4 = require('js/util/update/update-v4'), updateV4 = require('./update-v4'),
updateV5 = require('js/util/update/update-v5'); updateV5 = require('./update-v5');
/** /**
* Handles database migration * Handles database migration
@ -128,5 +127,4 @@ define(function(require) {
} }
}; };
return UpdateHandler; module.exports = UpdateHandler;
});

View File

@ -1,4 +1,3 @@
define(function() {
'use strict'; 'use strict';
/** /**
@ -25,5 +24,4 @@ define(function() {
}); });
} }
return updateV1; module.exports = updateV1;
});

View File

@ -1,4 +1,3 @@
define(function() {
'use strict'; 'use strict';
/** /**
@ -24,5 +23,4 @@ define(function() {
}); });
} }
return updateV2; module.exports = updateV2;
});

View File

@ -1,4 +1,3 @@
define(function() {
'use strict'; 'use strict';
/** /**
@ -24,5 +23,4 @@ define(function() {
}); });
} }
return update; module.exports = update;
});

View File

@ -1,7 +1,6 @@
define(function(require) {
'use strict'; 'use strict';
var config = require('js/app-config').config; var config = require('../../app-config').config;
/** /**
@ -101,5 +100,4 @@ define(function(require) {
} }
} }
return update; module.exports = update;
});

View File

@ -1,4 +1,3 @@
define(function() {
'use strict'; 'use strict';
var FOLDER_TYPE_INBOX = 'Inbox'; var FOLDER_TYPE_INBOX = 'Inbox';
@ -52,5 +51,4 @@ define(function() {
}); });
} }
return update; module.exports = update;
});

File diff suppressed because one or more lines are too long

View File

@ -1,245 +0,0 @@
// uuid.js
//
// (c) 2010-2012 Robert Kieffer
// MIT License
// https://github.com/broofa/node-uuid
(function() {
var _global = this;
// Unique ID creation requires a high quality random # generator. We feature
// detect to determine the best RNG source, normalizing to a function that
// returns 128-bits of randomness, since that's what's usually required
var _rng;
// Node.js crypto-based RNG - http://nodejs.org/docs/v0.6.2/api/crypto.html
//
// Moderately fast, high quality
if (typeof(require) == 'function') {
try {
var _rb = require('crypto').randomBytes;
_rng = _rb && function() {return _rb(16);};
} catch(e) {}
}
if (!_rng && _global.crypto && crypto.getRandomValues) {
// WHATWG crypto-based RNG - http://wiki.whatwg.org/wiki/Crypto
//
// Moderately fast, high quality
var _rnds8 = new Uint8Array(16);
_rng = function whatwgRNG() {
crypto.getRandomValues(_rnds8);
return _rnds8;
};
}
if (!_rng) {
// Math.random()-based (RNG)
//
// If all else fails, use Math.random(). It's fast, but is of unspecified
// quality.
var _rnds = new Array(16);
_rng = function() {
for (var i = 0, r; i < 16; i++) {
if ((i & 0x03) === 0) r = Math.random() * 0x100000000;
_rnds[i] = r >>> ((i & 0x03) << 3) & 0xff;
}
return _rnds;
};
}
// Buffer class to use
var BufferClass = typeof(Buffer) == 'function' ? Buffer : Array;
// Maps for number <-> hex string conversion
var _byteToHex = [];
var _hexToByte = {};
for (var i = 0; i < 256; i++) {
_byteToHex[i] = (i + 0x100).toString(16).substr(1);
_hexToByte[_byteToHex[i]] = i;
}
// **`parse()` - Parse a UUID into it's component bytes**
function parse(s, buf, offset) {
var i = (buf && offset) || 0, ii = 0;
buf = buf || [];
s.toLowerCase().replace(/[0-9a-f]{2}/g, function(oct) {
if (ii < 16) { // Don't overflow!
buf[i + ii++] = _hexToByte[oct];
}
});
// Zero out remaining bytes if string was short
while (ii < 16) {
buf[i + ii++] = 0;
}
return buf;
}
// **`unparse()` - Convert UUID byte array (ala parse()) into a string**
function unparse(buf, offset) {
var i = offset || 0, bth = _byteToHex;
return bth[buf[i++]] + bth[buf[i++]] +
bth[buf[i++]] + bth[buf[i++]] + '-' +
bth[buf[i++]] + bth[buf[i++]] + '-' +
bth[buf[i++]] + bth[buf[i++]] + '-' +
bth[buf[i++]] + bth[buf[i++]] + '-' +
bth[buf[i++]] + bth[buf[i++]] +
bth[buf[i++]] + bth[buf[i++]] +
bth[buf[i++]] + bth[buf[i++]];
}
// **`v1()` - Generate time-based UUID**
//
// Inspired by https://github.com/LiosK/UUID.js
// and http://docs.python.org/library/uuid.html
// random #'s we need to init node and clockseq
var _seedBytes = _rng();
// Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1)
var _nodeId = [
_seedBytes[0] | 0x01,
_seedBytes[1], _seedBytes[2], _seedBytes[3], _seedBytes[4], _seedBytes[5]
];
// Per 4.2.2, randomize (14 bit) clockseq
var _clockseq = (_seedBytes[6] << 8 | _seedBytes[7]) & 0x3fff;
// Previous uuid creation time
var _lastMSecs = 0, _lastNSecs = 0;
// See https://github.com/broofa/node-uuid for API details
function v1(options, buf, offset) {
var i = buf && offset || 0;
var b = buf || [];
options = options || {};
var clockseq = options.clockseq != null ? options.clockseq : _clockseq;
// UUID timestamps are 100 nano-second units since the Gregorian epoch,
// (1582-10-15 00:00). JSNumbers aren't precise enough for this, so
// time is handled internally as 'msecs' (integer milliseconds) and 'nsecs'
// (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00.
var msecs = options.msecs != null ? options.msecs : new Date().getTime();
// Per 4.2.1.2, use count of uuid's generated during the current clock
// cycle to simulate higher resolution clock
var nsecs = options.nsecs != null ? options.nsecs : _lastNSecs + 1;
// Time since last uuid creation (in msecs)
var dt = (msecs - _lastMSecs) + (nsecs - _lastNSecs)/10000;
// Per 4.2.1.2, Bump clockseq on clock regression
if (dt < 0 && options.clockseq == null) {
clockseq = clockseq + 1 & 0x3fff;
}
// Reset nsecs if clock regresses (new clockseq) or we've moved onto a new
// time interval
if ((dt < 0 || msecs > _lastMSecs) && options.nsecs == null) {
nsecs = 0;
}
// Per 4.2.1.2 Throw error if too many uuids are requested
if (nsecs >= 10000) {
throw new Error('uuid.v1(): Can\'t create more than 10M uuids/sec');
}
_lastMSecs = msecs;
_lastNSecs = nsecs;
_clockseq = clockseq;
// Per 4.1.4 - Convert from unix epoch to Gregorian epoch
msecs += 12219292800000;
// `time_low`
var tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000;
b[i++] = tl >>> 24 & 0xff;
b[i++] = tl >>> 16 & 0xff;
b[i++] = tl >>> 8 & 0xff;
b[i++] = tl & 0xff;
// `time_mid`
var tmh = (msecs / 0x100000000 * 10000) & 0xfffffff;
b[i++] = tmh >>> 8 & 0xff;
b[i++] = tmh & 0xff;
// `time_high_and_version`
b[i++] = tmh >>> 24 & 0xf | 0x10; // include version
b[i++] = tmh >>> 16 & 0xff;
// `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant)
b[i++] = clockseq >>> 8 | 0x80;
// `clock_seq_low`
b[i++] = clockseq & 0xff;
// `node`
var node = options.node || _nodeId;
for (var n = 0; n < 6; n++) {
b[i + n] = node[n];
}
return buf ? buf : unparse(b);
}
// **`v4()` - Generate random UUID**
// See https://github.com/broofa/node-uuid for API details
function v4(options, buf, offset) {
// Deprecated - 'format' argument, as supported in v1.2
var i = buf && offset || 0;
if (typeof(options) == 'string') {
buf = options == 'binary' ? new BufferClass(16) : null;
options = null;
}
options = options || {};
var rnds = options.random || (options.rng || _rng)();
// Per 4.4, set bits for version and `clock_seq_hi_and_reserved`
rnds[6] = (rnds[6] & 0x0f) | 0x40;
rnds[8] = (rnds[8] & 0x3f) | 0x80;
// Copy bytes to buffer, if provided
if (buf) {
for (var ii = 0; ii < 16; ii++) {
buf[i + ii] = rnds[ii];
}
}
return buf || unparse(rnds);
}
// Export public API
var uuid = v4;
uuid.v1 = v1;
uuid.v4 = v4;
uuid.parse = parse;
uuid.unparse = unparse;
uuid.BufferClass = BufferClass;
if (_global.define && define.amd) {
// Publish as AMD module
define(function() {return uuid;});
} else if (typeof(module) != 'undefined' && module.exports) {
// Publish as node.js module
module.exports = uuid;
} else {
// Publish as global (in browsers)
var _previousRoot = _global.uuid;
// **`noConflict()` - (browser only) to reset global 'uuid' var**
uuid.noConflict = function() {
_global.uuid = _previousRoot;
return uuid;
};
_global.uuid = uuid;
}
}());

View File

@ -1,10 +0,0 @@
{
"name": "Whiteout Mail",
"version": "0.0.1",
"main": "index.html",
"window": {
"toolbar": false,
"width": 1024,
"height": 768
}
}

View File

@ -1,68 +0,0 @@
(function() {
'use strict';
requirejs.config({
nodeRequire: (typeof module !== 'undefined' && module.exports) ? require : undefined,
baseUrl: 'lib',
paths: {
js: '../js',
test: '../../test',
jquery: 'jquery.min',
underscore: 'underscore/underscore-min',
lawnchair: 'lawnchair/lawnchair-git',
lawnchairSQL: 'lawnchair/lawnchair-adapter-webkit-sqlite-git',
lawnchairIDB: 'lawnchair/lawnchair-adapter-indexed-db-git',
angular: 'angular/angular.min',
angularRoute: 'angular/angular-route.min',
angularAnimate: 'angular/angular-animate.min',
ngInfiniteScroll: 'ng-infinite-scroll.min',
ngTagsInput: 'ngtagsinput/ng-tags-input.min',
uuid: 'uuid/uuid',
forge: 'forge/forge.min',
punycode: 'punycode.min',
openpgp: 'openpgp/openpgp',
fastclick: 'fastclick/fastclick'
},
shim: {
forge: {
exports: 'forge'
},
jquery: {
exports: '$'
},
angular: {
exports: 'angular',
deps: ['jquery']
},
angularRoute: {
exports: 'angular',
deps: ['angular']
},
angularAnimate: {
exports: 'angular',
deps: ['angular']
},
ngInfiniteScroll: {
exports: 'angular',
deps: ['jquery', 'angular']
},
ngTagsInput: {
exports: 'angular',
deps: ['angular']
},
lawnchair: {
exports: 'Lawnchair'
},
lawnchairSQL: {
deps: ['lawnchair']
},
lawnchairIDB: {
deps: ['lawnchair', 'lawnchairSQL']
},
underscore: {
exports: '_'
}
}
});
}());

View File

@ -5,8 +5,7 @@
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" media="all" href="../css/read-sandbox.min.css" type="text/css"> <link rel="stylesheet" media="all" href="../css/read-sandbox.min.css" type="text/css">
<script src="../lib/purify.js"></script> <script src="../js/read-sandbox.min.js"></script>
<script src="../js/controller/read-sandbox.js"></script>
</head> </head>
<body></body> <body></body>

View File

@ -1,10 +0,0 @@
'use strict';
chrome.app.runtime.onLaunched.addListener(function() {
chrome.app.window.create('integration/index.html', {
'bounds': {
'width': 1024,
'height': 768
}
});
});

View File

@ -1,19 +1,16 @@
define(function(require) {
'use strict'; 'use strict';
var expect = chai.expect, var ImapClient = require('imap-client'),
ImapClient = require('imap-client'),
BrowserCrow = require('browsercrow'), BrowserCrow = require('browsercrow'),
BrowserSMTP = require('browsersmtp'), BrowserSMTP = require('browsersmtp'),
SmtpClient = require('smtpclient'), SmtpClient = require('wo-smtpclient'),
LawnchairDAO = require('js/dao/lawnchair-dao'), LawnchairDAO = require('../../src/js/dao/lawnchair-dao'),
DeviceStorageDAO = require('js/dao/devicestorage-dao'), DeviceStorageDAO = require('../../src/js/dao/devicestorage-dao'),
appController = require('js/app-controller'), appController = require('../../src/js/app-controller'),
mailreader = require('mailreader'), mailreader = require('mailreader'),
openpgp = require('openpgp'),
PgpMailer = require('pgpmailer'), PgpMailer = require('pgpmailer'),
config = require('js/app-config').config, config = require('../../src/js/app-config').config,
str = require('js/app-config').string; str = require('../../src/js/app-config').string;
describe('Email DAO integration tests', function() { describe('Email DAO integration tests', function() {
this.timeout(100000); this.timeout(100000);
@ -272,6 +269,10 @@ define(function(require) {
}, function(err) { }, function(err) {
expect(err).to.not.exist; expect(err).to.not.exist;
// stub rest request to key server
sinon.stub(appController._emailDao._keychain._publicKeyDao, 'get').yields(null, mockKeyPair.publicKey);
sinon.stub(appController._emailDao._keychain._publicKeyDao, 'getByUserId').yields(null, mockKeyPair.publicKey);
userStorage = appController._userStorage; userStorage = appController._userStorage;
appController.init({ appController.init({
@ -827,4 +828,3 @@ define(function(require) {
}); });
}); });
}); });
});

View File

@ -2,7 +2,7 @@
<html style="overflow-y: auto"> <html style="overflow-y: auto">
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<title>JavaScript Unit Tests</title> <title>JavaScript Integration Tests</title>
<link rel="stylesheet" href="../lib/mocha.css" /> <link rel="stylesheet" href="../lib/mocha.css" />
</head> </head>
@ -10,10 +10,24 @@
<div id="mocha"></div> <div id="mocha"></div>
<script src="../lib/chai.js"></script> <script src="../lib/chai.js"></script>
<script src="../lib/sinon.js"></script>
<script src="../lib/mocha.js"></script> <script src="../lib/mocha.js"></script>
<script src="../lib/sinon.js"></script>
<script data-main="main.js" src="../lib/require.js"></script> <script>
window.expect = chai.expect;
mocha.setup('bdd');
</script>
<script src="../lib/openpgp.js"></script>
<script src="../lib/forge.min.js"></script>
<script src="index.js"></script>
<script>
if (window.mochaPhantomJS) {
mochaPhantomJS.run();
} else {
mocha.run();
}
</script>
</body> </body>
</html> </html>

View File

@ -1,61 +0,0 @@
'use strict';
// Mozilla bind polyfill because phantomjs is stupid
if (!Function.prototype.bind) {
Function.prototype.bind = function(oThis) {
if (typeof this !== "function") {
// closest thing possible to the ECMAScript 5 internal IsCallable function
throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
}
var aArgs = Array.prototype.slice.call(arguments, 1),
fToBind = this,
FNOP = function() {},
fBound = function() {
return fToBind.apply(this instanceof FNOP && oThis ? this : oThis, aArgs.concat(Array.prototype.slice.call(arguments)));
};
FNOP.prototype = this.prototype;
fBound.prototype = new FNOP();
return fBound;
};
}
require(['src/require-config'], function() {
require.config({
baseUrl: 'src/lib',
paths: {
'browsercrow': '../../../lib/browsercrow',
'browsercrow-envelope': '../../../lib/browsercrow-envelope',
'browsercrow-bodystructure': '../../../lib/browsercrow-bodystructure',
'browsercrow-mimeparser': '../../../lib/browsercrow-mimeparser',
'browsersmtp': '../../../lib/browsersmtp'
}
});
// Start the main app logic.
require(['js/app-config', 'axe'], function(app, axe) {
window.Worker = undefined; // disable web workers since mocha doesn't support them
app.config.workerPath = '../../src/js';
//app.config.cloudUrl = 'http://localhost:8888';
axe.removeAppender(axe.defaultAppender);
startTests();
});
});
function startTests() {
mocha.setup('bdd');
require(
[
'../../email-dao-test'
], function() {
//Tests loaded, run tests
mocha.run();
}
);
}

50
test/main.js Normal file
View File

@ -0,0 +1,50 @@
'use strict';
//
// Polyfills
//
// Mozilla bind polyfill because phantomjs is stupid
if (!Function.prototype.bind) {
Function.prototype.bind = function(oThis) {
if (typeof this !== "function") {
// closest thing possible to the ECMAScript 5 internal IsCallable function
throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
}
var aArgs = Array.prototype.slice.call(arguments, 1),
fToBind = this,
FNOP = function() {},
fBound = function() {
return fToBind.apply(this instanceof FNOP && oThis ? this : oThis, aArgs.concat(Array.prototype.slice.call(arguments)));
};
FNOP.prototype = this.prototype;
fBound.prototype = new FNOP();
return fBound;
};
}
// a warm round of applause for phantomjs for missing events
(function() {
if (!window.CustomEvent) {
var CustomEvent = function(event, params) {
params = params || {
bubbles: false,
cancelable: false,
detail: undefined
};
var evt = document.createEvent('CustomEvent');
evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);
return evt;
};
CustomEvent.prototype = window.Event.prototype;
window.CustomEvent = CustomEvent;
}
})();
// set worker path for tests
require('../src/js/app-config').config.workerPath = '../lib';

View File

@ -1,14 +1,11 @@
define(function(require) {
'use strict'; 'use strict';
var expect = chai.expect, var mocks = angular.mock,
angular = require('angular'), AccountCtrl = require('../../src/js/controller/account'),
mocks = require('angularMocks'), PGP = require('../../src/js/crypto/pgp'),
AccountCtrl = require('js/controller/account'), dl = require('../../src/js/util/download'),
PGP = require('js/crypto/pgp'), appController = require('../../src/js/app-controller'),
dl = require('js/util/download'), KeychainDAO = require('../../src/js/dao/keychain-dao');
appController = require('js/app-controller'),
KeychainDAO = require('js/dao/keychain-dao');
describe('Account Controller unit test', function() { describe('Account Controller unit test', function() {
var scope, accountCtrl, var scope, accountCtrl,
@ -98,4 +95,3 @@ define(function(require) {
}); });
}); });
}); });
});

View File

@ -1,13 +1,10 @@
define(function(require) {
'use strict'; 'use strict';
var expect = chai.expect, var mocks = angular.mock,
angular = require('angular'), AddAccountCtrl = require('../../src/js/controller/add-account'),
mocks = require('angularMocks'), Auth = require('../../src/js/bo/auth'),
AddAccountCtrl = require('js/controller/add-account'), AdminDao = require('../../src/js/dao/admin-dao'),
Auth = require('js/bo/auth'), appController = require('../../src/js/app-controller');
AdminDao = require('js/dao/admin-dao'),
appController = require('js/app-controller');
describe('Add Account Controller unit test', function() { describe('Add Account Controller unit test', function() {
var scope, location, ctrl, authStub, origAuth, adminStub; var scope, location, ctrl, authStub, origAuth, adminStub;
@ -213,4 +210,3 @@ define(function(require) {
}); });
}); });
});

View File

@ -1,9 +1,7 @@
define(function(require) {
'use strict'; 'use strict';
var RestDAO = require('js/dao/rest-dao'), var RestDAO = require('../../src/js/dao/rest-dao'),
AdminDAO = require('js/dao/admin-dao'), AdminDAO = require('../../src/js/dao/admin-dao');
expect = chai.expect;
describe('Admin DAO unit tests', function() { describe('Admin DAO unit tests', function() {
@ -142,5 +140,3 @@ define(function(require) {
}); });
}); });
});

View File

@ -1,13 +1,11 @@
define(function(require) {
'use strict'; 'use strict';
var controller = require('js/app-controller'), var controller = require('../../src/js/app-controller'),
EmailDAO = require('js/dao/email-dao'), EmailDAO = require('../../src/js/dao/email-dao'),
OutboxBO = require('js/bo/outbox'), OutboxBO = require('../../src/js/bo/outbox'),
DeviceStorageDAO = require('js/dao/devicestorage-dao'), DeviceStorageDAO = require('../../src/js/dao/devicestorage-dao'),
UpdateHandler = require('js/util/update/update-handler'), UpdateHandler = require('../../src/js/util/update/update-handler'),
Auth = require('js/bo/auth'), Auth = require('../../src/js/bo/auth');
expect = chai.expect;
describe('App Controller unit tests', function() { describe('App Controller unit tests', function() {
var emailDaoStub, outboxStub, updateHandlerStub, appConfigStoreStub, devicestorageStub, isOnlineStub, authStub; var emailDaoStub, outboxStub, updateHandlerStub, appConfigStoreStub, devicestorageStub, isOnlineStub, authStub;
@ -210,4 +208,3 @@ define(function(require) {
}); });
}); });
}); });
});

View File

@ -1,11 +1,9 @@
define(function(require) {
'use strict'; 'use strict';
var Auth = require('js/bo/auth'), var Auth = require('../../src/js/bo/auth'),
OAuth = require('js/util/oauth'), OAuth = require('../../src/js/util/oauth'),
PGP = require('js/crypto/pgp'), PGP = require('../../src/js/crypto/pgp'),
DeviceStorageDAO = require('js/dao/devicestorage-dao'), DeviceStorageDAO = require('../../src/js/dao/devicestorage-dao');
expect = chai.expect;
describe('Auth unit tests', function() { describe('Auth unit tests', function() {
// Constancts // Constancts
@ -375,4 +373,3 @@ define(function(require) {
}); });
}); });
}); });
});

View File

@ -1,8 +1,6 @@
define(function(require) {
'use strict'; 'use strict';
var btnHandler = require('js/util/backbutton-handler'), var btnHandler = require('../../src/js/util/backbutton-handler');
expect = chai.expect;
describe('Backbutton Handler', function() { describe('Backbutton Handler', function() {
chai.Assertion.includeStack = true; chai.Assertion.includeStack = true;
@ -64,4 +62,3 @@ define(function(require) {
document.dispatchEvent(event); document.dispatchEvent(event);
}); });
}); });
});

View File

@ -1,16 +1,14 @@
define(function(require) {
'use strict'; 'use strict';
var ConnectionDoctor = require('js/util/connection-doctor'), var TCPSocket = require('tcp-socket'),
TCPSocket = require('tcp-socket'),
ImapClient = require('imap-client'), ImapClient = require('imap-client'),
SmtpClient = require('smtpclient'), SmtpClient = require('wo-smtpclient'),
cfg = require('js/app-config').config, ConnectionDoctor = require('../../src/js/util/connection-doctor'),
expect = chai.expect; cfg = require('../../src/js/app-config').config;
describe('Connection Doctor', function() { describe('Connection Doctor', function() {
var doctor; var doctor;
var socketStub, imapStub, smtpStub, credentials; var socketStub, imapStub, smtpStub, credentials, workerPath;
beforeEach(function() { beforeEach(function() {
// //
@ -24,6 +22,7 @@ define(function(require) {
} }
}; };
workerPath = 'js/tcp-socket-tls-worker.min.js';
imapStub = sinon.createStubInstance(ImapClient); imapStub = sinon.createStubInstance(ImapClient);
smtpStub = sinon.createStubInstance(SmtpClient); smtpStub = sinon.createStubInstance(SmtpClient);
@ -86,7 +85,8 @@ define(function(require) {
expect(TCPSocket.open.calledWith(credentials.imap.host, credentials.imap.port, { expect(TCPSocket.open.calledWith(credentials.imap.host, credentials.imap.port, {
binaryType: 'arraybuffer', binaryType: 'arraybuffer',
useSecureTransport: credentials.imap.secure, useSecureTransport: credentials.imap.secure,
ca: credentials.imap.ca ca: credentials.imap.ca,
tlsWorkerPath: workerPath
})).to.be.true; })).to.be.true;
done(); done();
@ -110,7 +110,8 @@ define(function(require) {
expect(TCPSocket.open.calledWith(credentials.imap.host, credentials.imap.port, { expect(TCPSocket.open.calledWith(credentials.imap.host, credentials.imap.port, {
binaryType: 'arraybuffer', binaryType: 'arraybuffer',
useSecureTransport: credentials.imap.secure, useSecureTransport: credentials.imap.secure,
ca: credentials.imap.ca ca: credentials.imap.ca,
tlsWorkerPath: workerPath
})).to.be.true; })).to.be.true;
done(); done();
@ -127,7 +128,8 @@ define(function(require) {
expect(TCPSocket.open.calledWith(credentials.imap.host, credentials.imap.port, { expect(TCPSocket.open.calledWith(credentials.imap.host, credentials.imap.port, {
binaryType: 'arraybuffer', binaryType: 'arraybuffer',
useSecureTransport: credentials.imap.secure, useSecureTransport: credentials.imap.secure,
ca: credentials.imap.ca ca: credentials.imap.ca,
tlsWorkerPath: workerPath
})).to.be.true; })).to.be.true;
done(); done();
@ -411,4 +413,3 @@ define(function(require) {
}); });
}); });
}); });
});

View File

@ -1,13 +1,10 @@
define(function(require) {
'use strict'; 'use strict';
var expect = chai.expect, var mocks = angular.mock,
angular = require('angular'), ContactsCtrl = require('../../src/js/controller/contacts'),
mocks = require('angularMocks'), appController = require('../../src/js/app-controller'),
ContactsCtrl = require('js/controller/contacts'), KeychainDAO = require('../../src/js/dao/keychain-dao'),
appController = require('js/app-controller'), PGP = require('../../src/js/crypto/pgp');
KeychainDAO = require('js/dao/keychain-dao'),
PGP = require('js/crypto/pgp');
describe('Contacts Controller unit test', function() { describe('Contacts Controller unit test', function() {
var scope, contactsCtrl, var scope, contactsCtrl,
@ -187,4 +184,3 @@ define(function(require) {
}); });
}); });
}); });
});

View File

@ -1,10 +1,8 @@
define(function(require) {
'use strict'; 'use strict';
var Crypto = require('js/crypto/crypto'), var Crypto = require('../../src/js/crypto/crypto'),
util = require('js/crypto/util'), config = require('../../src/js/app-config').config,
config = require('js/app-config').config, util = require('crypto-lib').util;
expect = chai.expect;
describe('Crypto unit tests', function() { describe('Crypto unit tests', function() {
this.timeout(20000); this.timeout(20000);
@ -55,4 +53,3 @@ define(function(require) {
}); });
}); });
});

View File

@ -1,9 +1,7 @@
define(function(require) {
'use strict'; 'use strict';
var LawnchairDAO = require('js/dao/lawnchair-dao'), var LawnchairDAO = require('../../src/js/dao/lawnchair-dao'),
DeviceStorageDAO = require('js/dao/devicestorage-dao'), DeviceStorageDAO = require('../../src/js/dao/devicestorage-dao');
expect = chai.expect;
var testUser = 'test@example.com'; var testUser = 'test@example.com';
@ -101,5 +99,3 @@ define(function(require) {
}); });
}); });
});

View File

@ -1,10 +1,7 @@
define(function(require) {
'use strict'; 'use strict';
var expect = chai.expect, var mocks = angular.mock,
angular = require('angular'), DialogCtrl = require('../../src/js/controller/dialog');
mocks = require('angularMocks'),
DialogCtrl = require('js/controller/dialog');
describe('Dialog Controller unit test', function() { describe('Dialog Controller unit test', function() {
var scope, dialogCtrl; var scope, dialogCtrl;
@ -47,4 +44,3 @@ define(function(require) {
}); });
}); });
}); });
});

View File

@ -1,16 +1,14 @@
define(function(require) {
'use strict'; 'use strict';
var EmailDAO = require('js/dao/email-dao'), var mailreader = require('mailreader'),
KeychainDAO = require('js/dao/keychain-dao'),
ImapClient = require('imap-client'), ImapClient = require('imap-client'),
PgpMailer = require('pgpmailer'), PgpMailer = require('pgpmailer'),
PgpBuilder = require('pgpbuilder'), PgpBuilder = require('pgpbuilder'),
PGP = require('js/crypto/pgp'), cfg = require('../../src/js/app-config').config,
DeviceStorageDAO = require('js/dao/devicestorage-dao'), EmailDAO = require('../../src/js/dao/email-dao'),
mailreader = require('mailreader'), KeychainDAO = require('../../src/js/dao/keychain-dao'),
cfg = require('js/app-config').config, PGP = require('../../src/js/crypto/pgp'),
expect = chai.expect; DeviceStorageDAO = require('../../src/js/dao/devicestorage-dao');
describe('Email DAO unit tests', function() { describe('Email DAO unit tests', function() {
@ -2301,4 +2299,3 @@ define(function(require) {
}); });
}); });
}); });
});

View File

@ -10,10 +10,27 @@
<div id="mocha"></div> <div id="mocha"></div>
<script src="../lib/chai.js"></script> <script src="../lib/chai.js"></script>
<script src="../lib/sinon.js"></script>
<script src="../lib/mocha.js"></script> <script src="../lib/mocha.js"></script>
<script src="../lib/sinon.js"></script>
<script data-main="main.js" src="../../src/lib/require.js"></script> <script>
window.expect = chai.expect;
mocha.setup('bdd');
</script>
<script src="../lib/openpgp.js"></script>
<script src="../lib/forge.min.js"></script>
<script src="index.js"></script>
<script>
mocha.checkLeaks();
mocha.globals(['chrome']);
if (window.mochaPhantomJS) {
mochaPhantomJS.run();
} else {
mocha.run();
}
</script>
</body> </body>
</html> </html>

View File

@ -1,9 +1,7 @@
define(function(require) {
'use strict'; 'use strict';
var RestDAO = require('js/dao/rest-dao'), var RestDAO = require('../../src/js/dao/rest-dao'),
InvitationDAO = require('js/dao/invitation-dao'), InvitationDAO = require('../../src/js/dao/invitation-dao');
expect = chai.expect;
describe('Invitation DAO unit tests', function() { describe('Invitation DAO unit tests', function() {
var restDaoStub, invitationDao, var restDaoStub, invitationDao,
@ -105,4 +103,3 @@ define(function(require) {
}); });
}); });
}); });
});

View File

@ -1,13 +1,11 @@
define(function(require) {
'use strict'; 'use strict';
var LawnchairDAO = require('js/dao/lawnchair-dao'), var LawnchairDAO = require('../../src/js/dao/lawnchair-dao'),
PublicKeyDAO = require('js/dao/publickey-dao'), PublicKeyDAO = require('../../src/js/dao/publickey-dao'),
KeychainDAO = require('js/dao/keychain-dao'), KeychainDAO = require('../../src/js/dao/keychain-dao'),
PrivateKeyDAO = require('js/dao/privatekey-dao'), PrivateKeyDAO = require('../../src/js/dao/privatekey-dao'),
Crypto = require('js/crypto/crypto'), Crypto = require('../../src/js/crypto/crypto'),
PGP = require('js/crypto/pgp'), PGP = require('../../src/js/crypto/pgp');
expect = chai.expect;
var testUser = 'test@example.com'; var testUser = 'test@example.com';
@ -1382,5 +1380,3 @@ define(function(require) {
}); });
}); });
});

View File

@ -1,8 +1,6 @@
define(function(require) {
'use strict'; 'use strict';
var LawnchairDAO = require('js/dao/lawnchair-dao'), var LawnchairDAO = require('../../src/js/dao/lawnchair-dao');
expect = chai.expect;
var dbName = 'lawnchair@test.com'; var dbName = 'lawnchair@test.com';
@ -148,5 +146,3 @@ define(function(require) {
}); });
}); });
});

View File

@ -1,14 +1,11 @@
define(function(require) {
'use strict'; 'use strict';
var expect = chai.expect, var mocks = angular.mock,
angular = require('angular'), LoginCtrl = require('../../src/js/controller/login'),
mocks = require('angularMocks'), EmailDAO = require('../../src/js/dao/email-dao'),
LoginCtrl = require('js/controller/login'), Auth = require('../../src/js/bo/auth'),
EmailDAO = require('js/dao/email-dao'), appController = require('../../src/js/app-controller'),
Auth = require('js/bo/auth'), KeychainDAO = require('../../src/js/dao/keychain-dao');
appController = require('js/app-controller'),
KeychainDAO = require('js/dao/keychain-dao');
describe('Login Controller unit test', function() { describe('Login Controller unit test', function() {
var scope, location, ctrl, var scope, location, ctrl,
@ -235,4 +232,3 @@ define(function(require) {
}); });
}); });
}); });
});

View File

@ -1,14 +1,11 @@
define(function(require) {
'use strict'; 'use strict';
var expect = chai.expect, var Auth = require('../../src/js/bo/auth'),
angular = require('angular'), mocks = angular.mock,
Auth = require('js/bo/auth'), LoginExistingCtrl = require('../../src/js/controller/login-existing'),
mocks = require('angularMocks'), EmailDAO = require('../../src/js/dao/email-dao'),
LoginExistingCtrl = require('js/controller/login-existing'), KeychainDAO = require('../../src/js/dao/keychain-dao'),
EmailDAO = require('js/dao/email-dao'), appController = require('../../src/js/app-controller');
KeychainDAO = require('js/dao/keychain-dao'),
appController = require('js/app-controller');
describe('Login (existing user) Controller unit test', function() { describe('Login (existing user) Controller unit test', function() {
var scope, location, ctrl, origEmailDao, emailDaoMock, var scope, location, ctrl, origEmailDao, emailDaoMock,
@ -114,4 +111,3 @@ define(function(require) {
}); });
}); });
}); });
});

View File

@ -1,14 +1,11 @@
define(function(require) {
'use strict'; 'use strict';
var expect = chai.expect, var Auth = require('../../src/js/bo/auth'),
angular = require('angular'), mocks = angular.mock,
Auth = require('js/bo/auth'), LoginInitialCtrl = require('../../src/js/controller/login-initial'),
mocks = require('angularMocks'), PGP = require('../../src/js/crypto/pgp'),
LoginInitialCtrl = require('js/controller/login-initial'), EmailDAO = require('../../src/js/dao/email-dao'),
PGP = require('js/crypto/pgp'), appController = require('../../src/js/app-controller');
EmailDAO = require('js/dao/email-dao'),
appController = require('js/app-controller');
describe('Login (initial user) Controller unit test', function() { describe('Login (initial user) Controller unit test', function() {
var scope, ctrl, location, origEmailDao, emailDaoMock, var scope, ctrl, location, origEmailDao, emailDaoMock,
@ -197,6 +194,4 @@ define(function(require) {
scope.generateKey(); scope.generateKey();
}); });
}); });
});
}); });

View File

@ -1,14 +1,11 @@
define(function(require) {
'use strict'; 'use strict';
var expect = chai.expect, var mocks = angular.mock,
angular = require('angular'), PGP = require('../../src/js/crypto/pgp'),
mocks = require('angularMocks'), LoginNewDeviceCtrl = require('../../src/js/controller/login-new-device'),
PGP = require('js/crypto/pgp'), KeychainDAO = require('../../src/js/dao/keychain-dao'),
LoginNewDeviceCtrl = require('js/controller/login-new-device'), EmailDAO = require('../../src/js/dao/email-dao'),
KeychainDAO = require('js/dao/keychain-dao'), appController = require('../../src/js/app-controller');
EmailDAO = require('js/dao/email-dao'),
appController = require('js/app-controller');
describe('Login (new device) Controller unit test', function() { describe('Login (new device) Controller unit test', function() {
var scope, ctrl, origEmailDao, emailDaoMock, pgpMock, var scope, ctrl, origEmailDao, emailDaoMock, pgpMock,
@ -187,4 +184,3 @@ define(function(require) {
}); });
}); });
}); });
});

View File

@ -1,14 +1,11 @@
define(function(require) {
'use strict'; 'use strict';
var expect = chai.expect, var mocks = angular.mock,
angular = require('angular'), Auth = require('../../src/js/bo/auth'),
mocks = require('angularMocks'), LoginPrivateKeyDownloadCtrl = require('../../src/js/controller/login-privatekey-download'),
Auth = require('js/bo/auth'), EmailDAO = require('../../src/js/dao/email-dao'),
LoginPrivateKeyDownloadCtrl = require('js/controller/login-privatekey-download'), appController = require('../../src/js/app-controller'),
EmailDAO = require('js/dao/email-dao'), KeychainDAO = require('../../src/js/dao/keychain-dao');
appController = require('js/app-controller'),
KeychainDAO = require('js/dao/keychain-dao');
describe('Login Private Key Download Controller unit test', function() { describe('Login Private Key Download Controller unit test', function() {
var scope, location, ctrl, var scope, location, ctrl,
@ -261,4 +258,3 @@ define(function(require) {
}); });
}); });
}); });
});

View File

@ -1,13 +1,10 @@
define(function(require) {
'use strict'; 'use strict';
var expect = chai.expect, var mocks = angular.mock,
angular = require('angular'), Auth = require('../../src/js/bo/auth'),
mocks = require('angularMocks'), ConnectionDoctor = require('../../src/js/util/connection-doctor'),
Auth = require('js/bo/auth'), SetCredentialsCtrl = require('../../src/js/controller/login-set-credentials'),
ConnectionDoctor = require('js/util/connection-doctor'), appController = require('../../src/js/app-controller');
SetCredentialsCtrl = require('js/controller/login-set-credentials'),
appController = require('js/app-controller');
describe('Login (Set Credentials) Controller unit test', function() { describe('Login (Set Credentials) Controller unit test', function() {
// Angular parameters // Angular parameters
@ -98,4 +95,3 @@ define(function(require) {
}); });
}); });
}); });
});

View File

@ -1,15 +1,12 @@
define(function(require) {
'use strict'; 'use strict';
var expect = chai.expect, var mocks = angular.mock,
angular = require('angular'), MailListCtrl = require('../../src/js/controller/mail-list'),
mocks = require('angularMocks'), EmailDAO = require('../../src/js/dao/email-dao'),
MailListCtrl = require('js/controller/mail-list'), DeviceStorageDAO = require('../../src/js/dao/devicestorage-dao'),
EmailDAO = require('js/dao/email-dao'), KeychainDAO = require('../../src/js/dao/keychain-dao'),
DeviceStorageDAO = require('js/dao/devicestorage-dao'), appController = require('../../src/js/app-controller'),
KeychainDAO = require('js/dao/keychain-dao'), notification = require('../../src/js/util/notification');
appController = require('js/app-controller'),
notification = require('js/util/notification');
chai.Assertion.includeStack = true; chai.Assertion.includeStack = true;
@ -448,4 +445,3 @@ define(function(require) {
}); });
}); });
}); });
});

View File

@ -1,113 +0,0 @@
'use strict';
// Mozilla bind polyfill because phantomjs is stupid
if (!Function.prototype.bind) {
Function.prototype.bind = function(oThis) {
if (typeof this !== "function") {
// closest thing possible to the ECMAScript 5 internal IsCallable function
throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
}
var aArgs = Array.prototype.slice.call(arguments, 1),
fToBind = this,
FNOP = function() {},
fBound = function() {
return fToBind.apply(this instanceof FNOP && oThis ? this : oThis, aArgs.concat(Array.prototype.slice.call(arguments)));
};
FNOP.prototype = this.prototype;
fBound.prototype = new FNOP();
return fBound;
};
}
// a warm round of applause for phantomjs for missing events
(function() {
function CustomEvent(event, params) {
params = params || {
bubbles: false,
cancelable: false,
detail: undefined
};
var evt = document.createEvent('CustomEvent');
evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);
return evt;
}
CustomEvent.prototype = window.Event.prototype;
window.CustomEvent = CustomEvent;
})();
require(['../../src/require-config'], function() {
require.config({
baseUrl: '../../src/lib',
paths: {
angularMocks: '../../test/lib/angular-mocks'
},
shim: {
angularMocks: {
exports: 'angular.mock',
deps: ['angular']
}
}
});
// Start the main app logic.
require(['js/app-config', 'axe'], function(app, axe) {
app.config.workerPath = '../../src/js';
// turn off logging in the test
axe.removeAppender(axe.defaultAppender);
startTests();
});
});
function startTests() {
mocha.setup('bdd');
require(
[
'test/unit/oauth-test',
'test/unit/auth-test',
'test/unit/email-dao-test',
'test/unit/app-controller-test',
'test/unit/pgp-test',
'test/unit/crypto-test',
'test/unit/backbutton-handler-test',
'test/unit/rest-dao-test',
'test/unit/admin-dao-test',
'test/unit/publickey-dao-test',
'test/unit/privatekey-dao-test',
'test/unit/lawnchair-dao-test',
'test/unit/keychain-dao-test',
'test/unit/devicestorage-dao-test',
'test/unit/dialog-ctrl-test',
'test/unit/add-account-ctrl-test',
'test/unit/account-ctrl-test',
'test/unit/set-passphrase-ctrl-test',
'test/unit/contacts-ctrl-test',
'test/unit/login-existing-ctrl-test',
'test/unit/login-initial-ctrl-test',
'test/unit/login-new-device-ctrl-test',
'test/unit/login-privatekey-download-ctrl-test',
'test/unit/login-set-credentials-ctrl-test',
'test/unit/privatekey-upload-ctrl-test',
'test/unit/login-ctrl-test',
'test/unit/read-ctrl-test',
'test/unit/navigation-ctrl-test',
'test/unit/mail-list-ctrl-test',
'test/unit/write-ctrl-test',
'test/unit/outbox-bo-test',
'test/unit/invitation-dao-test',
'test/unit/update-handler-test',
'test/unit/connection-doctor-test'
], function() {
//Tests loaded, run tests
mocha.run();
}
);
}

View File

@ -1,13 +1,10 @@
define(function(require) {
'use strict'; 'use strict';
var expect = chai.expect, var mocks = angular.mock,
angular = require('angular'), NavigationCtrl = require('../../src/js/controller/navigation'),
mocks = require('angularMocks'), EmailDAO = require('../../src/js/dao/email-dao'),
NavigationCtrl = require('js/controller/navigation'), OutboxBO = require('../../src/js/bo/outbox'),
EmailDAO = require('js/dao/email-dao'), appController = require('../../src/js/app-controller');
OutboxBO = require('js/bo/outbox'),
appController = require('js/app-controller');
describe('Navigation Controller unit test', function() { describe('Navigation Controller unit test', function() {
var scope, ctrl, origEmailDao, emailDaoMock, outboxBoMock, outboxFolder, onConnectStub; var scope, ctrl, origEmailDao, emailDaoMock, outboxBoMock, outboxFolder, onConnectStub;
@ -98,4 +95,3 @@ define(function(require) {
}); });
}); });
}); });
});

View File

@ -1,9 +1,7 @@
define(function(require) {
'use strict'; 'use strict';
var OAuth = require('js/util/oauth'), var OAuth = require('../../src/js/util/oauth'),
RestDAO = require('js/dao/rest-dao'), RestDAO = require('../../src/js/dao/rest-dao');
expect = chai.expect;
describe('OAuth unit tests', function() { describe('OAuth unit tests', function() {
var oauth, googleApiStub, identityStub, getPlatformInfoStub, removeCachedStub, var oauth, googleApiStub, identityStub, getPlatformInfoStub, removeCachedStub,
@ -198,4 +196,3 @@ define(function(require) {
}); });
}); });
});

View File

@ -1,11 +1,9 @@
define(function(require) {
'use strict'; 'use strict';
var expect = chai.expect, var OutboxBO = require('../../src/js/bo/outbox'),
OutboxBO = require('js/bo/outbox'), KeychainDAO = require('../../src/js/dao/keychain-dao'),
KeychainDAO = require('js/dao/keychain-dao'), EmailDAO = require('../../src/js/dao/email-dao'),
EmailDAO = require('js/dao/email-dao'), DeviceStorageDAO = require('../../src/js/dao/devicestorage-dao');
DeviceStorageDAO = require('js/dao/devicestorage-dao');
chai.Assertion.includeStack = true; chai.Assertion.includeStack = true;
@ -277,4 +275,3 @@ define(function(require) {
}); });
}); });
}); });
});

View File

@ -1,9 +1,6 @@
define(function(require) {
'use strict'; 'use strict';
var PGP = require('js/crypto/pgp'), var PGP = require('../../src/js/crypto/pgp');
openpgp = require('openpgp'),
expect = chai.expect;
describe('PGP Crypto Api unit tests', function() { describe('PGP Crypto Api unit tests', function() {
this.timeout(20000); this.timeout(20000);
@ -461,4 +458,3 @@ define(function(require) {
}); });
}); });
}); });
});

View File

@ -1,9 +1,7 @@
define(function(require) {
'use strict'; 'use strict';
var RestDAO = require('js/dao/rest-dao'), var RestDAO = require('../../src/js/dao/rest-dao'),
PrivateKeyDAO = require('js/dao/privatekey-dao'), PrivateKeyDAO = require('../../src/js/dao/privatekey-dao');
expect = chai.expect;
describe('Private Key DAO unit tests', function() { describe('Private Key DAO unit tests', function() {
@ -222,5 +220,3 @@ define(function(require) {
}); });
}); });
});

View File

@ -1,13 +1,10 @@
define(function(require) {
'use strict'; 'use strict';
var expect = chai.expect, var mocks = angular.mock,
angular = require('angular'), PrivateKeyUploadCtrl = require('../../src/js/controller/privatekey-upload'),
mocks = require('angularMocks'), appController = require('../../src/js/app-controller'),
PrivateKeyUploadCtrl = require('js/controller/privatekey-upload'), KeychainDAO = require('../../src/js/dao/keychain-dao'),
appController = require('js/app-controller'), PGP = require('../../src/js/crypto/pgp');
KeychainDAO = require('js/dao/keychain-dao'),
PGP = require('js/crypto/pgp');
describe('Private Key Upload Controller unit test', function() { describe('Private Key Upload Controller unit test', function() {
var scope, location, ctrl, var scope, location, ctrl,
@ -281,6 +278,4 @@ define(function(require) {
scope.goForward(); scope.goForward();
}); });
}); });
});
}); });

View File

@ -1,9 +1,7 @@
define(function(require) {
'use strict'; 'use strict';
var RestDAO = require('js/dao/rest-dao'), var RestDAO = require('../../src/js/dao/rest-dao'),
PublicKeyDAO = require('js/dao/publickey-dao'), PublicKeyDAO = require('../../src/js/dao/publickey-dao');
expect = chai.expect;
describe('Public Key DAO unit tests', function() { describe('Public Key DAO unit tests', function() {
@ -161,5 +159,3 @@ define(function(require) {
}); });
}); });
});

View File

@ -1,15 +1,12 @@
define(function(require) {
'use strict'; 'use strict';
var expect = chai.expect, var mocks = angular.mock,
angular = require('angular'), KeychainDAO = require('../../src/js/dao/keychain-dao'),
mocks = require('angularMocks'), InvitationDAO = require('../../src/js/dao/invitation-dao'),
KeychainDAO = require('js/dao/keychain-dao'), PGP = require('../../src/js/crypto/pgp'),
InvitationDAO = require('js/dao/invitation-dao'), ReadCtrl = require('../../src/js/controller/read'),
PGP = require('js/crypto/pgp'), OutboxBO = require('../../src/js/bo/outbox'),
ReadCtrl = require('js/controller/read'), appController = require('../../src/js/app-controller');
OutboxBO = require('js/bo/outbox'),
appController = require('js/app-controller');
describe('Read Controller unit test', function() { describe('Read Controller unit test', function() {
var scope, ctrl, var scope, ctrl,
@ -194,4 +191,3 @@ define(function(require) {
}); });
}); });
});

View File

@ -1,8 +1,6 @@
define(function(require) {
'use strict'; 'use strict';
var RestDAO = require('js/dao/rest-dao'), var RestDAO = require('../../src/js/dao/rest-dao');
expect = chai.expect;
describe('Rest DAO unit tests', function() { describe('Rest DAO unit tests', function() {
@ -221,5 +219,3 @@ define(function(require) {
}); });
}); });
});

View File

@ -1,13 +1,10 @@
define(function(require) {
'use strict'; 'use strict';
var expect = chai.expect, var mocks = angular.mock,
angular = require('angular'), SetPassphraseCtrl = require('../../src/js/controller/set-passphrase'),
mocks = require('angularMocks'), PGP = require('../../src/js/crypto/pgp'),
SetPassphraseCtrl = require('js/controller/set-passphrase'), appController = require('../../src/js/app-controller'),
PGP = require('js/crypto/pgp'), KeychainDAO = require('../../src/js/dao/keychain-dao');
appController = require('js/app-controller'),
KeychainDAO = require('js/dao/keychain-dao');
describe('Set Passphrase Controller unit test', function() { describe('Set Passphrase Controller unit test', function() {
var scope, setPassphraseCtrl, var scope, setPassphraseCtrl,
@ -123,4 +120,3 @@ define(function(require) {
}); });
}); });
});

View File

@ -1,12 +1,10 @@
define(function(require) {
'use strict'; 'use strict';
var DeviceStorageDAO = require('js/dao/devicestorage-dao'), var DeviceStorageDAO = require('../../src/js/dao/devicestorage-dao'),
Auth = require('js/bo/auth'), Auth = require('../../src/js/bo/auth'),
cfg = require('js/app-config').config, cfg = require('../../src/js/app-config').config,
UpdateHandler = require('js/util/update/update-handler'), UpdateHandler = require('../../src/js/util/update/update-handler'),
config = require('js/app-config').config, config = require('../../src/js/app-config').config;
expect = chai.expect;
describe('UpdateHandler', function() { describe('UpdateHandler', function() {
var updateHandler, appConfigStorageStub, authStub, userStorageStub, origDbVersion; var updateHandler, appConfigStorageStub, authStub, userStorageStub, origDbVersion;
@ -471,4 +469,3 @@ define(function(require) {
}); });
}); });
}); });
});

View File

@ -1,14 +1,11 @@
define(function(require) {
'use strict'; 'use strict';
var expect = chai.expect, var mocks = angular.mock,
angular = require('angular'), WriteCtrl = require('../../src/js/controller/write'),
mocks = require('angularMocks'), EmailDAO = require('../../src/js/dao/email-dao'),
WriteCtrl = require('js/controller/write'), OutboxBO = require('../../src/js/bo/outbox'),
EmailDAO = require('js/dao/email-dao'), KeychainDAO = require('../../src/js/dao/keychain-dao'),
OutboxBO = require('js/bo/outbox'), appController = require('../../src/js/app-controller');
KeychainDAO = require('js/dao/keychain-dao'),
appController = require('js/app-controller');
describe('Write controller unit test', function() { describe('Write controller unit test', function() {
var ctrl, scope, var ctrl, scope,
@ -398,4 +395,3 @@ define(function(require) {
}); });
}); });
});