refactored folder structure

This commit is contained in:
Tankred Hase 2013-04-01 23:23:25 +02:00
parent 13ee758c8d
commit 5ee864fe01
27 changed files with 444 additions and 394 deletions

View File

@ -2,3 +2,11 @@ html5-mail
==========
HTML5 Mail App with Client-side Encryption
## Getting started
Required packages: nodejs, npm
npm install express
node server.js 8080 --dev
browse to http://localhost:8080

View File

@ -1,32 +0,0 @@
/**
* A simple development server for serving static files using node.js
* Required packages: nodejs, npm
* 1. npm install express
* 2. node dev_server.js 8080
* 3. browse to http://localhost:8080
*/
var express = require('express'),
port, app;
// set port
if (process.argv[2]) {
port = process.argv[2];
} else {
port = 8080;
}
// Server setup
app = express();
app.configure(function(){
app.use(express['static'](__dirname));
app.use(function(req, res, next) {
res.set('Content-Security-Policy', "script-src 'self' 'unsafe-eval'; object-src 'none'; style-src 'self' 'unsafe-inline'");
return next();
});
app.use(express['static'](__dirname + '/src'));
});
// start server
app.listen(port);
console.log(' > listening on http://localhost:' + port);

View File

@ -1,15 +0,0 @@
{
"name": "Whiteout",
"description": "HTML5 Mail with an encrypted message store both locally and in the cloud",
"launch_path": "/html5-mail/src/",
"icons": {
"128": "/html5-mail/src/css/images/key-128.png"
},
"developer": {
"name": "Whiteout Networks GmbH",
"url": "http://whiteout.io"
},
"appcache_path": "/html5-mail/src/manifest.appcache",
"csp": "script-src 'self' 'unsafe-eval'; object-src 'none'; style-src 'self' 'unsafe-inline'",
"default_locale": "en"
}

49
server.js Normal file
View File

@ -0,0 +1,49 @@
/**
* A simple server for serving static files using node.js
*/
var express = require('express'),
fs = require('fs'),
port, app, prot, dev;
// set port
if (process.argv[2]) {
port = process.argv[2];
} else {
port = 8080;
}
if (process.argv[3] === '--dev') {
// development server
dev = true;
prot = 'http';
app = express();
} else {
// production server
dev = false;
prot = 'https';
app = express({
ca: fs.readFileSync('./ssl/sub.class1.server.ca.pem'),
key: fs.readFileSync('./ssl/ssl.key'),
cert: fs.readFileSync('./ssl/ssl.crt')
});
}
// Server setup
app.configure(function() {
// active content security policy for production
if (!dev) {
app.use(function(req, res, next) {
var csp = "script-src 'self' 'unsafe-eval'; object-src 'none'; style-src 'self' 'unsafe-inline'";
res.set('Content-Security-Policy', csp);
res.set('X-Content-Security-Policy', csp);
res.set('X-WebKit-CSP', csp);
return next();
});
}
app.use(express['static'](__dirname + '/src'));
});
// start server
app.listen(port);
console.log(' > listening on ' + prot + '://localhost:' + port);

View File

@ -1,23 +1,28 @@
'use strict';
var app;
/**
(function() {
'use strict';
/**
* Create the application namespace
*/
var app = {
app = {
model: {},
view: {},
dao: {},
crypto:{},
crypto: {},
util: {}
};
};
/**
/**
* Global app configurations
*/
app.config = {
app.config = {
cloudUrl: 'https://whiteout-io.appspot.com',
symKeySize: 128,
symIvSize: 104,
asymKeySize: 2048,
workerPath: 'js'
};
};
}());

View File

@ -1,8 +1,9 @@
'use strict';
(function() {
'use strict';
var AppRouter = Backbone.Router.extend({
app.Router = Backbone.Router.extend({
routes:{
routes: {
'': 'login',
'compose': 'compose',
'accounts/:userId/folders': 'folders',
@ -10,8 +11,7 @@ var AppRouter = Backbone.Router.extend({
'accounts/:userId/folders/:folder/read/:messageId': 'read'
},
initialize: function () {
},
initialize: function() {},
login: function() {
// init email dao and dependencies
@ -22,7 +22,9 @@ var AppRouter = Backbone.Router.extend({
var devicestorage = new app.dao.DeviceStorage(util, crypto, jsonDao, null);
this.emailDao = new app.dao.EmailDAO(_, crypto, devicestorage, cloudstorage);
var loginView = new app.view.LoginView({dao: this.emailDao});
var loginView = new app.view.LoginView({
dao: this.emailDao
});
this.changePage(loginView);
},
@ -32,13 +34,19 @@ var AppRouter = Backbone.Router.extend({
},
folders: function(userId) {
var folderListView = new app.view.FolderListView({account: userId});
var folderListView = new app.view.FolderListView({
account: userId
});
this.changePage(folderListView);
},
messagelist: function(userId, folder) {
var self = this;
var messageListView = new app.view.MessageListView({account: userId, folder: folder, dao: this.emailDao});
var messageListView = new app.view.MessageListView({
account: userId,
folder: folder,
dao: this.emailDao
});
self.changePage(messageListView);
messageListView.loadItems();
},
@ -53,7 +61,7 @@ var AppRouter = Backbone.Router.extend({
readView.renderBody();
},
changePage: function (page) {
changePage: function(page) {
// render the page and append it to the DOM
var pageEl = $(page.el);
pageEl.attr('data-role', 'page');
@ -73,7 +81,12 @@ var AppRouter = Backbone.Router.extend({
window.location = href;
});
$.mobile.changePage(pageEl, {changeHash:false, reverse:false});
$.mobile.changePage(pageEl, {
changeHash: false,
reverse: false
});
}
});
});
}());

View File

@ -1,6 +1,7 @@
'use strict';
(function() {
'use strict';
$(document).on('mobileinit', function () {
$(document).on('mobileinit', function() {
console.log('mobileinit');
$.mobile.ajaxEnabled = false;
$.mobile.linkBindingEnabled = false;
@ -9,7 +10,9 @@ $(document).on('mobileinit', function () {
$.mobile.defaultPageTransition = 'none';
// Remove page from DOM when it's being replaced
$(document).on('pagehide', 'div[data-role="page"]', function (event, ui) {
$(document).on('pagehide', 'div[data-role="page"]', function(event, ui) {
$(event.currentTarget).remove();
});
});
});
}());

View File

@ -1,21 +1,22 @@
'use strict';
(function() {
'use strict';
/**
/**
* The Template Loader. Used to asynchronously load templates located in separate .html files
*/
app.util.tpl = {
app.util.tpl = {
// Hash of preloaded templates for the app
templates:{},
templates: {},
// Recursively pre-load all the templates for the app.
loadTemplates:function (names, callback) {
loadTemplates: function(names, callback) {
var that = this;
var loadTemplate = function (index) {
var loadTemplate = function(index) {
var name = names[index];
console.log('Loading template: ' + name);
$.get('tpl/' + name + '.html', function (data) {
$.get('tpl/' + name + '.html', function(data) {
that.templates[name] = data;
index++;
if (index < names.length) {
@ -30,23 +31,23 @@ app.util.tpl = {
},
// Get template by name from hash of preloaded templates
get:function (name) {
get: function(name) {
return this.templates[name];
}
};
};
/**
/**
* Load templates and start the application
*/
$(document).ready(function() {
$(document).ready(function() {
// are we running in native app or in browser?
var isBrowser = false;
if(document.URL.indexOf("http://") !== -1) {
if (document.URL.indexOf("http://") !== -1) {
isBrowser = true;
}
if(!isBrowser) {
if (!isBrowser) {
document.addEventListener("deviceready", onDeviceReady, false);
} else {
onDeviceReady();
@ -60,10 +61,11 @@ $(document).ready(function() {
'folderlist',
'messagelist',
'messagelistitem',
'read'
], function () {
var router = new AppRouter();
'read'], function() {
var router = new app.Router();
Backbone.history.start();
});
};
});
}
});
}());

15
src/manifest.webapp Normal file
View File

@ -0,0 +1,15 @@
{
"name": "Whiteout",
"description": "HTML5 Mail with an encrypted message store both locally and in the cloud",
"launch_path": "/html5-mail/src/",
"icons": {
"128": "/html5-mail/src/css/images/key-128.png"
},
"developer": {
"name": "Whiteout Networks GmbH",
"url": "http://whiteout.io"
},
"appcache_path": "/html5-mail/src/manifest.appcache",
"csp": "script-src 'self' 'unsafe-eval'; object-src 'none'; style-src 'self' 'unsafe-inline'",
"default_locale": "en"
}

View File

@ -12,7 +12,7 @@ asyncTest("Init", 1, function() {
var util = new app.crypto.Util(window, uuid);
var jsonDao = new app.dao.LawnchairDAO(window);
cloudstoragedao_test.crypto = new app.crypto.Crypto(window, util);
cloudstoragedao_test.storage = new app.dao.DeviceStorage(cloudstoragedao_test.crypto, jsonDao, null);
cloudstoragedao_test.storage = new app.dao.DeviceStorage(util, cloudstoragedao_test.crypto, jsonDao, null);
cloudstoragedao_test.cloudstorage = new app.dao.CloudStorage(window, $);
cloudstoragedao_test.emailDao = new app.dao.EmailDAO(_, cloudstoragedao_test.crypto, cloudstoragedao_test.storage, cloudstoragedao_test.cloudstorage);

View File

@ -0,0 +1,74 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JavaScript Integration Tests</title>
<link rel="stylesheet" href="../qunit-1.11.0.css">
</head>
<body>
<div id="qunit"></div>
<div id="qunit-fixture"></div>
<script>
// clear session storage of failed tests, so async order is correct after fail & refresh
window.sessionStorage.clear();
</script>
<!-- dependencies -->
<script src="../../lib/cordova-2.5.0.js"></script>
<script src="../qunit-1.11.0.js"></script>
<script src="../../lib/jquery-1.8.2.min.js"></script>
<script src="../../lib/underscore-1.4.4.min.js"></script>
<script src="../../lib/backbone-0.9.10.min.js"></script>
<script src="../../lib/lawnchair/lawnchair-git.min.js"></script>
<script src="../../lib/lawnchair/lawnchair-adapter-indexed-db-git.js"></script>
<script src="../../lib/lawnchair/lawnchair-adapter-webkit-sqlite-git.js"></script>
<script src="../../lib/crypto-js/core.js"></script>
<script src="../../lib/crypto-js/enc-base64.js"></script>
<script src="../../lib/crypto-js/cipher-core.js"></script>
<script src="../../lib/crypto-js/aes.js"></script>
<script src="../../lib/crypto-js/sha1.js"></script>
<script src="../../lib/crypto-js/hmac.js"></script>
<script src="../../lib/crypto-js/pbkdf2.js"></script>
<script src="../../lib/sjcl/sjcl.js"></script>
<script src="../../lib/sjcl/sha256.js"></script>
<script src="../../lib/sjcl/random.js"></script>
<script src="../../lib/sjcl/bitArray.js"></script>
<script src="../../lib/sjcl/codecBase64.js"></script>
<script src="../../lib/sjcl/codecString.js"></script>
<script src="../../lib/sjcl/aes.js"></script>
<script src="../../lib/sjcl/ccm.js"></script>
<script src="../../lib/uuid.js"></script>
<script src="../../lib/openpgp.min.js"></script>
<script src="../../js/app-config.js"></script>
<script>
app.config.workerPath = '../../js';
app.config.cloudUrl = 'http://localhost:8888';
</script>
<script src="../../js/model/email-model.js"></script>
<script src="../../js/model/folder-model.js"></script>
<script src="../../js/model/account-model.js"></script>
<script src="../../js/crypto/util.js"></script>
<script src="../../js/crypto/pbkdf2.js"></script>
<script src="../../js/crypto/aes-cbc.js"></script>
<script src="../../js/crypto/aes-ccm.js"></script>
<script src="../../js/crypto/aes-gcm.js"></script>
<script src="../../js/crypto/crypto.js"></script>
<script src="../../js/dao/localstorage-dao.js"></script>
<script src="../../js/dao/lawnchair-dao.js"></script>
<script src="../../js/dao/devicestorage.js"></script>
<script src="../../js/dao/cloudstorage-dao.js"></script>
<script src="../../js/dao/email-dao.js"></script>
<!-- tests -->
<script src="cloudstorage-dao-test.js"></script>
</body>
</html>

View File

@ -15,7 +15,9 @@ asyncTest("Init", 2, function() {
emaildao_test.storage = new app.dao.DeviceStorage(util, emaildao_test.crypto, jsonDao, null);
// cloud storage stub
var cloudstorageStub = {
getUserSecretKey: function(emailAdress, callback) { callback(); }
getUserSecretKey: function(emailAdress, callback) {
callback();
}
};
emaildao_test.emailDao = new app.dao.EmailDAO(_, emaildao_test.crypto, emaildao_test.storage, cloudstorageStub);

81
src/test/unit/index.html Normal file
View File

@ -0,0 +1,81 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JavaScript Unit Tests</title>
<link rel="stylesheet" href="../qunit-1.11.0.css">
</head>
<body>
<div id="qunit"></div>
<div id="qunit-fixture"></div>
<script>
// clear session storage of failed tests, so async order is correct after fail & refresh
window.sessionStorage.clear();
</script>
<!-- dependencies -->
<script src="../../lib/cordova-2.5.0.js"></script>
<script src="../qunit-1.11.0.js"></script>
<script src="../../lib/jquery-1.8.2.min.js"></script>
<script src="../../lib/underscore-1.4.4.min.js"></script>
<script src="../../lib/backbone-0.9.10.min.js"></script>
<script src="../../lib/lawnchair/lawnchair-git.min.js"></script>
<script src="../../lib/lawnchair/lawnchair-adapter-indexed-db-git.js"></script>
<script src="../../lib/lawnchair/lawnchair-adapter-webkit-sqlite-git.js"></script>
<script src="../../lib/crypto-js/core.js"></script>
<script src="../../lib/crypto-js/enc-base64.js"></script>
<script src="../../lib/crypto-js/cipher-core.js"></script>
<script src="../../lib/crypto-js/aes.js"></script>
<script src="../../lib/crypto-js/sha1.js"></script>
<script src="../../lib/crypto-js/hmac.js"></script>
<script src="../../lib/crypto-js/pbkdf2.js"></script>
<script src="../../lib/sjcl/sjcl.js"></script>
<script src="../../lib/sjcl/sha256.js"></script>
<script src="../../lib/sjcl/random.js"></script>
<script src="../../lib/sjcl/bitArray.js"></script>
<script src="../../lib/sjcl/codecBase64.js"></script>
<script src="../../lib/sjcl/codecString.js"></script>
<script src="../../lib/sjcl/aes.js"></script>
<script src="../../lib/sjcl/ccm.js"></script>
<script src="../../lib/uuid.js"></script>
<script src="../../lib/openpgp.min.js"></script>
<script src="../../js/app-config.js"></script>
<script>
app.config.workerPath = '../../js';
app.config.cloudUrl = 'http://localhost:8888';
</script>
<script src="../../js/model/email-model.js"></script>
<script src="../../js/model/folder-model.js"></script>
<script src="../../js/model/account-model.js"></script>
<script src="../../js/crypto/util.js"></script>
<script src="../../js/crypto/pbkdf2.js"></script>
<script src="../../js/crypto/aes-cbc.js"></script>
<script src="../../js/crypto/aes-ccm.js"></script>
<script src="../../js/crypto/aes-gcm.js"></script>
<script src="../../js/crypto/crypto.js"></script>
<script src="../../js/dao/localstorage-dao.js"></script>
<script src="../../js/dao/lawnchair-dao.js"></script>
<script src="../../js/dao/devicestorage.js"></script>
<script src="../../js/dao/cloudstorage-dao.js"></script>
<script src="../../js/dao/email-dao.js"></script>
<!-- tests -->
<script src="../test-data.js"></script>
<script src="util-test.js"></script>
<script src="aes-test.js"></script>
<script src="crypto-test.js"></script>
<script src="localstorage-dao-test.js"></script>
<script src="lawnchair-dao-test.js"></script>
<script src="devicestorage-test.js"></script>
<script src="email-dao-test.js"></script>
</body>
</html>

View File

@ -1,74 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JavaScript Integration Tests</title>
<link rel="stylesheet" href="../qunit-1.11.0.css">
</head>
<body>
<div id="qunit"></div>
<div id="qunit-fixture"></div>
<script>
// clear session storage of failed tests, so async order is correct after fail & refresh
window.sessionStorage.clear();
</script>
<!-- dependencies -->
<script src="../../src/lib/cordova-2.5.0.js"></script>
<script src="../qunit-1.11.0.js"></script>
<script src="../../src/lib/jquery-1.8.2.min.js"></script>
<script src="../../src/lib/underscore-1.4.4.min.js"></script>
<script src="../../src/lib/backbone-0.9.10.min.js"></script>
<script src="../../src/lib/lawnchair/lawnchair-git.min.js"></script>
<script src="../../src/lib/lawnchair/lawnchair-adapter-indexed-db-git.js"></script>
<script src="../../src/lib/lawnchair/lawnchair-adapter-webkit-sqlite-git.js"></script>
<script src="../../src/lib/crypto-js/core.js"></script>
<script src="../../src/lib/crypto-js/enc-base64.js"></script>
<script src="../../src/lib/crypto-js/cipher-core.js"></script>
<script src="../../src/lib/crypto-js/aes.js"></script>
<script src="../../src/lib/crypto-js/sha1.js"></script>
<script src="../../src/lib/crypto-js/hmac.js"></script>
<script src="../../src/lib/crypto-js/pbkdf2.js"></script>
<script src="../../src/lib/sjcl/sjcl.js"></script>
<script src="../../src/lib/sjcl/sha256.js"></script>
<script src="../../src/lib/sjcl/random.js"></script>
<script src="../../src/lib/sjcl/bitArray.js"></script>
<script src="../../src/lib/sjcl/codecBase64.js"></script>
<script src="../../src/lib/sjcl/codecString.js"></script>
<script src="../../src/lib/sjcl/aes.js"></script>
<script src="../../src/lib/sjcl/ccm.js"></script>
<script src="../../src/lib/uuid.js"></script>
<script src="../../src/lib/openpgp.min.js"></script>
<script src="../../src/js/app-config.js"></script>
<script>
app.config.workerPath = '../../src/js';
app.config.cloudUrl = 'http://localhost:8888';
</script>
<script src="../../src/js/model/email-model.js"></script>
<script src="../../src/js/model/folder-model.js"></script>
<script src="../../src/js/model/account-model.js"></script>
<script src="../../src/js/crypto/util.js"></script>
<script src="../../src/js/crypto/pbkdf2.js"></script>
<script src="../../src/js/crypto/aes-cbc.js"></script>
<script src="../../src/js/crypto/aes-ccm.js"></script>
<script src="../../src/js/crypto/aes-gcm.js"></script>
<script src="../../src/js/crypto/crypto.js"></script>
<script src="../../src/js/dao/localstorage-dao.js"></script>
<script src="../../src/js/dao/lawnchair-dao.js"></script>
<script src="../../src/js/dao/devicestorage.js"></script>
<script src="../../src/js/dao/cloudstorage-dao.js"></script>
<script src="../../src/js/dao/email-dao.js"></script>
<!-- tests -->
<script src="cloudstorage-dao-test.js"></script>
</body>
</html>

View File

@ -1,81 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JavaScript Unit Tests</title>
<link rel="stylesheet" href="../qunit-1.11.0.css">
</head>
<body>
<div id="qunit"></div>
<div id="qunit-fixture"></div>
<script>
// clear session storage of failed tests, so async order is correct after fail & refresh
window.sessionStorage.clear();
</script>
<!-- dependencies -->
<script src="../../src/lib/cordova-2.5.0.js"></script>
<script src="../qunit-1.11.0.js"></script>
<script src="../../src/lib/jquery-1.8.2.min.js"></script>
<script src="../../src/lib/underscore-1.4.4.min.js"></script>
<script src="../../src/lib/backbone-0.9.10.min.js"></script>
<script src="../../src/lib/lawnchair/lawnchair-git.min.js"></script>
<script src="../../src/lib/lawnchair/lawnchair-adapter-indexed-db-git.js"></script>
<script src="../../src/lib/lawnchair/lawnchair-adapter-webkit-sqlite-git.js"></script>
<script src="../../src/lib/crypto-js/core.js"></script>
<script src="../../src/lib/crypto-js/enc-base64.js"></script>
<script src="../../src/lib/crypto-js/cipher-core.js"></script>
<script src="../../src/lib/crypto-js/aes.js"></script>
<script src="../../src/lib/crypto-js/sha1.js"></script>
<script src="../../src/lib/crypto-js/hmac.js"></script>
<script src="../../src/lib/crypto-js/pbkdf2.js"></script>
<script src="../../src/lib/sjcl/sjcl.js"></script>
<script src="../../src/lib/sjcl/sha256.js"></script>
<script src="../../src/lib/sjcl/random.js"></script>
<script src="../../src/lib/sjcl/bitArray.js"></script>
<script src="../../src/lib/sjcl/codecBase64.js"></script>
<script src="../../src/lib/sjcl/codecString.js"></script>
<script src="../../src/lib/sjcl/aes.js"></script>
<script src="../../src/lib/sjcl/ccm.js"></script>
<script src="../../src/lib/uuid.js"></script>
<script src="../../src/lib/openpgp.min.js"></script>
<script src="../../src/js/app-config.js"></script>
<script>
app.config.workerPath = '../../src/js';
app.config.cloudUrl = 'http://localhost:8888';
</script>
<script src="../../src/js/model/email-model.js"></script>
<script src="../../src/js/model/folder-model.js"></script>
<script src="../../src/js/model/account-model.js"></script>
<script src="../../src/js/crypto/util.js"></script>
<script src="../../src/js/crypto/pbkdf2.js"></script>
<script src="../../src/js/crypto/aes-cbc.js"></script>
<script src="../../src/js/crypto/aes-ccm.js"></script>
<script src="../../src/js/crypto/aes-gcm.js"></script>
<script src="../../src/js/crypto/crypto.js"></script>
<script src="../../src/js/dao/localstorage-dao.js"></script>
<script src="../../src/js/dao/lawnchair-dao.js"></script>
<script src="../../src/js/dao/devicestorage.js"></script>
<script src="../../src/js/dao/cloudstorage-dao.js"></script>
<script src="../../src/js/dao/email-dao.js"></script>
<!-- tests -->
<script src="../test-data.js"></script>
<script src="util-test.js"></script>
<script src="aes-test.js"></script>
<script src="crypto-test.js"></script>
<script src="localstorage-dao-test.js"></script>
<script src="lawnchair-dao-test.js"></script>
<script src="devicestorage-test.js"></script>
<script src="email-dao-test.js"></script>
</body>
</html>