Compare commits
1023 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
43729833a5 | ||
|
b05aeea342 | ||
|
137c8c7c24 | ||
|
853be194d9 | ||
|
8b36a719c3 | ||
|
8165416c5d | ||
|
b375d81635 | ||
|
e56f8c2c28 | ||
|
ad3691fae9 | ||
|
e0663ab8d8 | ||
|
263b5c13b0 | ||
|
8636ba201b | ||
|
aa24881efc | ||
|
b7b5c1bdf5 | ||
|
59d38f9b14 | ||
|
c44984b2f3 | ||
|
c31c320e83 | ||
|
7f49e691db | ||
|
a346f1612e | ||
|
6b0b71d4ff | ||
|
4683583a0a | ||
|
b038ac2c16 | ||
|
f32863dc54 | ||
|
39d19df187 | ||
|
9bf8c758ec | ||
|
76f770a12b | ||
|
3af376b419 | ||
|
e9a8702b39 | ||
|
25b9141a5f | ||
|
1d0efc02a2 | ||
|
c3362c193d | ||
|
7f0235c9b2 | ||
|
8e0dfacd51 | ||
|
467d001483 | ||
|
e7fb3bcf6d | ||
|
ce740b2109 | ||
|
0bfaba3bd9 | ||
|
e7cbf9ed86 | ||
|
c76a392abf | ||
|
ca8c2d9a4f | ||
|
f287c4cddf | ||
|
59006a98d7 | ||
|
73fcfba2a9 | ||
|
b473d2b7fe | ||
|
4519ab65c6 | ||
|
19bdf0aa49 | ||
|
b8f21ac7eb | ||
|
ff2a7c3e4a | ||
|
7834f79045 | ||
|
b35d993ff1 | ||
|
4e0388b349 | ||
|
add1cd3919 | ||
|
d87449c57f | ||
|
4cf1ef3107 | ||
|
e5e1c118be | ||
|
8e03b6a2ff | ||
|
6963ea33e9 | ||
|
0074e0ca90 | ||
|
9f5daa12b1 | ||
|
44591cc099 | ||
|
ecf16b028b | ||
|
bcaef5c330 | ||
|
9454739818 | ||
|
991f61d271 | ||
|
f62257a595 | ||
|
4f1ead0394 | ||
|
bd910df187 | ||
|
504e8ffd50 | ||
|
7c1d68ec6e | ||
|
4293031f1f | ||
|
44dac729aa | ||
|
55add6a6d3 | ||
|
d36ddcef7f | ||
|
94188be7b3 | ||
|
215a53e2a9 | ||
|
168eaf0086 | ||
|
9f39b67812 | ||
|
7540ffcab5 | ||
|
15ff8c85db | ||
|
4efab0daf0 | ||
|
701eb36b19 | ||
|
b687986980 | ||
|
281e53a887 | ||
|
6216fe2f1a | ||
|
2aa166ac19 | ||
|
4a681a73d2 | ||
|
56bd5222d2 | ||
|
1032a1eb06 | ||
|
e6d109d42d | ||
|
0dc04e659f | ||
|
c8779caef2 | ||
|
898e19e3ea | ||
|
246d19b76e | ||
|
55406cf7e8 | ||
|
b5c917f95a | ||
|
a0378cc0b9 | ||
|
8b42f83b35 | ||
|
9f94467ad1 | ||
|
321b6a9710 | ||
|
cf85fbd2ee | ||
|
9518cb69fa | ||
|
ec7e8cbd68 | ||
|
d0f002bfd1 | ||
|
9841a59a9e | ||
|
1ffcaf5487 | ||
|
150a3c7888 | ||
|
1af3eac566 | ||
|
e437a95baa | ||
|
2828771c2b | ||
|
2148d06d49 | ||
|
dca2f4ead9 | ||
|
8807830122 | ||
|
69ed386765 | ||
|
e6147e1fdc | ||
|
1d64c2dfb0 | ||
|
e5f281c124 | ||
|
06d772159b | ||
|
ff72822e36 | ||
|
09ff51f329 | ||
|
a2442554ad | ||
|
153d0626d2 | ||
|
222b7d35e3 | ||
|
07e0f39b55 | ||
|
73febe287e | ||
|
abbd893438 | ||
|
d67e0531d5 | ||
|
210ab61ba1 | ||
|
b752269c68 | ||
|
d8fb06cb08 | ||
|
88e83b6511 | ||
|
1b8c6b6b8d | ||
|
8295806b1f | ||
|
c30fbe8b6b | ||
|
5a8d7d8324 | ||
|
c9981239c8 | ||
|
c8f13511c1 | ||
|
f41e6e12b9 | ||
|
809de91354 | ||
|
220b8af509 | ||
|
1d57b004d1 | ||
|
518ceec0ef | ||
|
1d4a9414bb | ||
|
0304bbf8fe | ||
|
6ceb877472 | ||
|
1806f78ef3 | ||
|
881b05df91 | ||
|
369ad58134 | ||
|
5f19bbeff0 | ||
|
1c361e9c85 | ||
|
888204e1b9 | ||
|
427dee8214 | ||
|
e089139474 | ||
|
6873fd7f3d | ||
|
9bc2bc7912 | ||
|
9aebecd45f | ||
|
9d68b6475c | ||
|
2c1e1f669e | ||
|
91693c62ad | ||
|
93dc53f7b7 | ||
|
59dc2008a4 | ||
|
10cd2795f3 | ||
|
9c6d618ddc | ||
|
163ad5db79 | ||
|
54d495d8d9 | ||
|
0faa5b3743 | ||
|
2e3e07aa1d | ||
|
3da5a55251 | ||
|
f28c7854c3 | ||
|
57918bbd67 | ||
|
c26a51f83d | ||
|
6938750803 | ||
|
c94c419b38 | ||
|
5e246ee921 | ||
|
443cc3b59b | ||
|
da639b5a69 | ||
|
0d17701ebd | ||
|
5bf0890c02 | ||
|
f8e5ea6d89 | ||
|
7ffb7ca148 | ||
|
5121347640 | ||
|
2c092b0240 | ||
|
2875228359 | ||
|
274c23ea4c | ||
|
4fe3ceaea2 | ||
|
ff587672d9 | ||
|
fef264248d | ||
|
9a9b0d4cea | ||
|
c93eaf17f3 | ||
|
038437595e | ||
|
0446f8219b | ||
|
86653e8700 | ||
|
900294a13d | ||
|
990950bc48 | ||
|
978822ae55 | ||
|
75a382190a | ||
|
6ad3b7402e | ||
|
6a525ae643 | ||
|
55ab661582 | ||
|
7c9e8e6a4e | ||
|
295c781b62 | ||
|
b7072648b7 | ||
|
753cd1a4d7 | ||
|
281f4a94cd | ||
|
c271dc91dc | ||
|
fc6b21e63a | ||
|
2be7beb3a1 | ||
|
d3b54187cb | ||
|
c165ced523 | ||
|
d7a4058644 | ||
|
7d266e6a79 | ||
|
a07ee38fdb | ||
|
c660883a24 | ||
|
8ce33f9573 | ||
|
9d420f3cdc | ||
|
802f9619cf | ||
|
242d067141 | ||
|
b3942d9dce | ||
|
b68bebaf12 | ||
|
fb0454142c | ||
|
d41ed34837 | ||
|
66cf02bcb3 | ||
|
f1ba11abc3 | ||
|
b3afa745c3 | ||
|
c7195db4ca | ||
|
873f4ea1c9 | ||
|
e3643717fe | ||
|
ab18cdd5f8 | ||
|
087d4e66d5 | ||
|
e01b1ac965 | ||
|
00914cb3be | ||
|
8412973c38 | ||
|
b62c551b8b | ||
|
b0476989fb | ||
|
dc02cb1da4 | ||
|
bb206bc700 | ||
|
1378c7b069 | ||
|
137c6fe971 | ||
|
6dc6442b9d | ||
|
8dbdb030db | ||
|
95ce49279d | ||
|
36b0096973 | ||
|
bd327db4e8 | ||
|
6dffba9ff3 | ||
|
37fb3f5f8d | ||
|
b44d0a222a | ||
|
3cc0a372e1 | ||
|
6a9603cb69 | ||
|
cddc0988b7 | ||
|
b01aa6716c | ||
|
6a8c24d813 | ||
|
383761e6cb | ||
|
6beddf4760 | ||
|
eab07041f0 | ||
|
085b104521 | ||
|
ea74f3443c | ||
|
bfe827e084 | ||
|
c5a8e1c119 | ||
|
e5c602cee0 | ||
|
2af599c0ad | ||
|
993ca8eac7 | ||
|
bc41486693 | ||
|
e32456c3db | ||
|
a80169ebe2 | ||
|
26553e49d7 | ||
|
15b902acf6 | ||
|
cc886ad402 | ||
|
7bb69c76b6 | ||
|
88a48ec540 | ||
|
f4fe1a36a6 | ||
|
dab09f1068 | ||
|
cb1c4fd0ed | ||
|
a58448483a | ||
|
3944b1741e | ||
|
fb89ffd35a | ||
|
67adf4a1b8 | ||
|
7aa0d2cf4a | ||
|
502c6b7467 | ||
|
01e0529854 | ||
|
f9f086d622 | ||
|
99c2f24d7d | ||
|
ce07f30252 | ||
|
7b698e52b0 | ||
|
3ec4ad46e5 | ||
|
b5380bbef3 | ||
|
10c3748249 | ||
|
1979903943 | ||
|
a5c6400601 | ||
|
67384695f1 | ||
|
ad9990a0ce | ||
|
67a9c07f7a | ||
|
276a82e5ef | ||
|
c3efeb1132 | ||
|
8c88f25875 | ||
|
738d2671f7 | ||
|
3cd0bcc513 | ||
|
6eeba1ad2f | ||
|
fdb94e4e20 | ||
|
0b53886889 | ||
|
8340584de9 | ||
|
30c2c19652 | ||
|
420bcbcaa8 | ||
|
17c082e21b | ||
|
e00f2ecb3d | ||
|
6f794ff26d | ||
|
2272f3d58f | ||
|
dcfcd74373 | ||
|
f735430c68 | ||
|
68d464483e | ||
|
43eb385a14 | ||
|
df9ba7fd66 | ||
|
33b30221f7 | ||
|
eb4bc13e3f | ||
|
175b97f7a2 | ||
|
4622ebd8d9 | ||
|
95cbe0ea11 | ||
|
987ddbd796 | ||
|
7752675ec3 | ||
|
170b01d5f1 | ||
|
ee313d3765 | ||
|
c012f54c89 | ||
|
e06fff4385 | ||
|
fee1151952 | ||
|
5e29c707e0 | ||
|
5ac7955721 | ||
|
b5e305534e | ||
|
f0f215ad5b | ||
|
7d3e6b0f2f | ||
|
9d8fc023ca | ||
|
6a17c5a77f | ||
|
46acefd3bc | ||
|
dafe584d48 | ||
|
2a6d4e0d9b | ||
|
97f1132023 | ||
|
c3b3efa696 | ||
|
e8e69ad32d | ||
|
32cc2806e9 | ||
|
4edf79d8c4 | ||
|
51715822f8 | ||
|
251264835f | ||
|
47270b659c | ||
|
189c82159f | ||
|
13c6061589 | ||
|
876a0b0302 | ||
|
d15d45a16c | ||
|
a999d26c29 | ||
|
a177503bdd | ||
|
4ca25fc86f | ||
|
15a222a6ae | ||
|
9bee0f3def | ||
|
da3a128cf1 | ||
|
81a2d64835 | ||
|
5b4d7bcd4a | ||
|
6668174852 | ||
|
ac7af7168b | ||
|
c7463cd185 | ||
|
d985054fcd | ||
|
92a8348ea7 | ||
|
7443dcad99 | ||
|
b4884e4956 | ||
|
26bc7c91fc | ||
|
9f981f8168 | ||
|
e66d450b81 | ||
|
2a6cce858c | ||
|
3b1df177b9 | ||
|
45c4bbc525 | ||
|
e2e15f9a3d | ||
|
620fd51aa3 | ||
|
d0460bf4f3 | ||
|
e70b874dc3 | ||
|
520268e357 | ||
|
ad794454ab | ||
|
941283bfb6 | ||
|
04da07813a | ||
|
324d252628 | ||
|
28b0558129 | ||
|
cb4d27e58f | ||
|
c0ee4a7db7 | ||
|
aff71d506b | ||
|
b57be79b00 | ||
|
fb21de8035 | ||
|
bd13a993a2 | ||
|
0d90af5ec1 | ||
|
12e65e0011 | ||
|
f8f7588c93 | ||
|
f740b27659 | ||
|
2f25557747 | ||
|
32d3ea1801 | ||
|
b3b947f6e5 | ||
|
2b6da522c6 | ||
|
03b2e10bc3 | ||
|
1c1a5a4d54 | ||
|
156cff1854 | ||
|
eb099d9bfe | ||
|
c8665bc786 | ||
|
2764c6e230 | ||
|
2a2058c167 | ||
|
34e3a3fe46 | ||
|
7f6410e1f8 | ||
|
c8980f6f51 | ||
|
f2fee61d3b | ||
|
881afbff40 | ||
|
3342b91d3f | ||
|
cb5431dc16 | ||
|
198118571f | ||
|
7eeff8ec75 | ||
|
5109ccd899 | ||
|
da5a9e2c17 | ||
|
1e752885d4 | ||
|
9b10346cb9 | ||
|
4c04ba4e74 | ||
|
e6b22bd0a0 | ||
|
1f5fa4ca41 | ||
|
da416f4329 | ||
|
c221372ed4 | ||
|
95ad15b0dd | ||
|
41879bf5b3 | ||
|
a5da52c8a6 | ||
|
38d908995a | ||
|
ac09c7d91f | ||
|
c8d56b4bd1 | ||
|
f7b7e174b0 | ||
|
628beb02e8 | ||
|
f11d4e8df3 | ||
|
eabdeaf888 | ||
|
906909fd7d | ||
|
585ccf84a2 | ||
|
b12c99fbfe | ||
|
aed9d174a5 | ||
|
c85b6344fc | ||
|
3156fd9601 | ||
|
21356ae9ac | ||
|
57f11f1108 | ||
|
eb775525f5 | ||
|
3e54f66cb9 | ||
|
c2df2abbb0 | ||
|
99fbd475f4 | ||
|
2440817cfa | ||
|
97ec23c973 | ||
|
5e82b2382c | ||
|
18dc3dbf37 | ||
|
5d982fdcac | ||
|
ea1e5c6380 | ||
|
d4984aafa7 | ||
|
9c5bb31d66 | ||
|
e1c594ce0f | ||
|
a2cce31a1f | ||
|
996730f160 | ||
|
dfff273bf3 | ||
|
88370adbf3 | ||
|
aaf3743665 | ||
|
82f02312ea | ||
|
5eafb448c8 | ||
|
77fc111ee8 | ||
|
42c259dea6 | ||
|
5113583707 | ||
|
f8038ea735 | ||
|
4d2cabc8c1 | ||
|
f82c7c7480 | ||
|
fb3ca46017 | ||
|
68bcf9ebc7 | ||
|
7229923d70 | ||
|
6e284dfd7e | ||
|
70402d77a8 | ||
|
38fce60e6c | ||
|
f0b1d7934d | ||
|
aff3854cb9 | ||
|
64abd6ad63 | ||
|
2bc96a5fb1 | ||
|
42c1bbc638 | ||
|
8c84369e92 | ||
|
31a6091b25 | ||
|
4f12f2d0a7 | ||
|
16308232ce | ||
|
cf1f60fbf9 | ||
|
082cbf192b | ||
|
1d22231e8a | ||
|
510f147b97 | ||
|
11d7a26c31 | ||
|
1bfdafd6b1 | ||
|
4bfeb99b7b | ||
|
4468c91242 | ||
|
93bd548b46 | ||
|
074914044d | ||
|
069628c62b | ||
|
5884b1231f | ||
|
4b73492aa5 | ||
|
e06f602890 | ||
|
915db579c4 | ||
|
e34da3bdbf | ||
|
900dbc8cb9 | ||
|
eb3a266725 | ||
|
da872daa7d | ||
|
a6bd06f853 | ||
|
b3f1f4b3fe | ||
|
e8964cde39 | ||
|
acea305a5a | ||
|
26e819c8e3 | ||
|
fc66df8894 | ||
|
2b15eabcd0 | ||
|
24a181cf8d | ||
|
8cc84ef8c6 | ||
|
f62ad4b868 | ||
|
402bd80b34 | ||
|
7959be55a7 | ||
|
40a4b33748 | ||
|
fe62759613 | ||
|
d67f2a5d53 | ||
|
4722af1457 | ||
|
69a3c9555d | ||
|
14dc80ec3c | ||
|
8f1fd2de5f | ||
|
7d223dc851 | ||
|
0c33f9070b | ||
|
5253680f86 | ||
|
b10c0896e9 | ||
|
541b35818b | ||
|
571d9dbf34 | ||
|
325e36b2e0 | ||
|
8b081c759a | ||
|
650aa83958 | ||
|
a65435a771 | ||
|
0bf68a0385 | ||
|
8e737474f5 | ||
|
8910376134 | ||
|
4861ee23c3 | ||
|
4a43765f70 | ||
|
568ccebcc1 | ||
|
4760ddf314 | ||
|
168a794708 | ||
|
31fba2fed2 | ||
|
10e6bd32e8 | ||
|
5efa410d7d | ||
|
edcaf7e3c0 | ||
|
dc8ee2c498 | ||
|
29f82754d4 | ||
|
bd19135472 | ||
|
2594ff515b | ||
|
06498017df | ||
|
8c2aebf3fd | ||
|
c3021a7244 | ||
|
c9c05302d2 | ||
|
b53fdd3162 | ||
|
4ef2b834b6 | ||
|
b96ae1dd89 | ||
|
52a2f4f43a | ||
|
f938b3b83c | ||
|
cce81337c3 | ||
|
a728e34e32 | ||
|
eb81028123 | ||
|
c6b50d04f6 | ||
|
f380db4e1d | ||
|
f9b1c66932 | ||
|
dada15c2b4 | ||
|
5f9132ab5f | ||
|
d6b842b0f4 | ||
|
0f800f7875 | ||
|
20ad94fc6b | ||
|
a610440b5a | ||
|
d7c1718a1c | ||
|
ce78e71cd7 | ||
|
486a48679f | ||
|
b556334407 | ||
|
7a986fc60a | ||
|
a93d817962 | ||
|
84ba1e5c44 | ||
|
1fbb6b0c91 | ||
|
65036a5087 | ||
|
dd9680f626 | ||
|
1995836736 | ||
|
35b2da32ff | ||
|
5b8ad29e0a | ||
|
59853ecbca | ||
|
eaff850d27 | ||
|
5d09e32320 | ||
|
d971969b5f | ||
|
9723d6f0cd | ||
|
3a6e0463fb | ||
|
7be6c63060 | ||
|
c6c058c2dc | ||
|
5ea660e5d4 | ||
|
046241e20d | ||
|
2cb008c8c3 | ||
|
c120818792 | ||
|
6e1ad91f6a | ||
|
033df2dea8 | ||
|
0519b73cdc | ||
|
c6fb31fd49 | ||
|
84d5bd8124 | ||
|
85afb0be01 | ||
|
7e09add0f4 | ||
|
b5b95d1c5c | ||
|
b0a186884a | ||
|
98dfcfcb22 | ||
|
b2b39abd66 | ||
|
5d608cad67 | ||
|
fc613ce501 | ||
|
0bfef4a710 | ||
|
7a20049bbc | ||
|
d9a2c77aa4 | ||
|
9bfda73969 | ||
|
c36cd069e0 | ||
|
73ed053c66 | ||
|
66ddac2c71 | ||
|
315a471f10 | ||
|
7b84f9dcb2 | ||
|
5e17d68740 | ||
|
cf20672735 | ||
|
b02989e766 | ||
|
771b03e13a | ||
|
9521d6b990 | ||
|
38d760364d | ||
|
658daf21b1 | ||
|
297f7c493f | ||
|
5c9f8dac23 | ||
|
bedb69973c | ||
|
f66fbf592c | ||
|
a92a5c5a3f | ||
|
fe73f3db52 | ||
|
0266f330c0 | ||
|
f42f9f640f | ||
|
b11a9220fe | ||
|
53a695b7dc | ||
|
0613016581 | ||
|
53341f02a2 | ||
|
3bfc3ad66b | ||
|
6be8b71247 | ||
|
675e1b13dd | ||
|
77e0377fd1 | ||
|
91528f993b | ||
|
b6608a1c4d | ||
|
d93ee3be5d | ||
|
3156a20664 | ||
|
320686f590 | ||
|
7b99682299 | ||
|
ba55dfc90b | ||
|
3ec9597371 | ||
|
74f6b3312e | ||
|
f3ad08b066 | ||
|
8199ee741d | ||
|
1cc224dcf2 | ||
|
513d29ad79 | ||
|
1311cd1c5e | ||
|
909bca2da5 | ||
|
017ea707ad | ||
|
d1308aa14c | ||
|
a304f13cd2 | ||
|
4ea983dcfb | ||
|
5a7dc6c95e | ||
|
7c7d650cf2 | ||
|
98bc50a285 | ||
|
a29e072165 | ||
|
fcbe84841e | ||
|
bf54d6281f | ||
|
3a13a3056e | ||
|
b05a98b951 | ||
|
d31c8a69e6 | ||
|
d66890211a | ||
|
7497268c7a | ||
|
9c85fb2ebe | ||
|
51434d82e0 | ||
|
42867880e7 | ||
|
ba9770b495 | ||
|
d365de4e5b | ||
|
6ee9853506 | ||
|
0aff411c3f | ||
|
059349807b | ||
|
14294a5579 | ||
|
86a87e26b8 | ||
|
b69e0951c9 | ||
|
487bb31d45 | ||
|
e29f083c60 | ||
|
37d7f76f75 | ||
|
43858b1927 | ||
|
efdc78fc75 | ||
|
a06d9b4d92 | ||
|
34b3bee520 | ||
|
d9a23e3a7d | ||
|
a600aaea87 | ||
|
221bbea17c | ||
|
400a90f88e | ||
|
7e8d88e5a8 | ||
|
165eef0ee1 | ||
|
196fa974bc | ||
|
8eae30b9da | ||
|
4b108921f3 | ||
|
f55c2c796f | ||
|
50f0bf951e | ||
|
ad5617dc7d | ||
|
da246d4a03 | ||
|
c0e8480b87 | ||
|
15710f4602 | ||
|
2caeaeea3f | ||
|
3cfbad1498 | ||
|
ad2b6d1237 | ||
|
ec238a5325 | ||
|
d5d74df9bf | ||
|
a2bc734ba6 | ||
|
292bd3cb77 | ||
|
72092b3943 | ||
|
04b6c8b033 | ||
|
54e733b24d | ||
|
a3d87c7da8 | ||
|
4d62c07ed2 | ||
|
30f0029907 | ||
|
54c9ca3a73 | ||
|
ec5edff626 | ||
|
c75e365c65 | ||
|
30632205ce | ||
|
1ff9f44b2d | ||
|
8a737788e7 | ||
|
7bc9b90045 | ||
|
facc9f13da | ||
|
e229e106dd | ||
|
1ee280c74e | ||
|
0e21616911 | ||
|
275a602274 | ||
|
6bc2ee54f3 | ||
|
fc4bd0054f | ||
|
f417a09b8d | ||
|
f824f1737f | ||
|
14624c877e | ||
|
53fae2cd52 | ||
|
ec2186080a | ||
|
22246677f5 | ||
|
e8ba6e8572 | ||
|
0e482e475d | ||
|
7da5d58886 | ||
|
57c7027832 | ||
|
ceb1d2a69c | ||
|
04ed3dab68 | ||
|
1534ceeb6c | ||
|
7adc095277 | ||
|
bb9a641b4e | ||
|
995af4ca3c | ||
|
c4337fba30 | ||
|
ed43dfc55a | ||
|
eb0002c8d5 | ||
|
77a80f5899 | ||
|
aa22878033 | ||
|
fca6a386d1 | ||
|
d088eec89c | ||
|
d278afb253 | ||
|
b887aaaa28 | ||
|
4a38820501 | ||
|
9e1a402b94 | ||
|
3a713180f1 | ||
|
64daec7536 | ||
|
6ce1f2361a | ||
|
e8c45cc83f | ||
|
061fe0dd9c | ||
|
26f52981eb | ||
|
e19d8a4e5b | ||
|
9b618cc20f | ||
|
2b139578f0 | ||
|
e072f118ca | ||
|
1e7255f8ce | ||
|
746c06e24a | ||
|
45d40d5d37 | ||
|
2798c1812a | ||
|
bdbed0d6dd | ||
|
cefa47edc7 | ||
|
a5d25ea43c | ||
|
a28528c23b | ||
|
81eee6e67d | ||
|
18f658cbb8 | ||
|
129e95aef2 | ||
|
ed8ed07028 | ||
|
7b11b43dc4 | ||
|
8fa2641e78 | ||
|
679d7987c4 | ||
|
ad22d42720 | ||
|
845af9b127 | ||
|
f8f4ee7945 | ||
|
aed2a5ec14 | ||
|
8617a4d0ed | ||
|
a137bf5bfd | ||
|
22d42358e4 | ||
|
3e80138a10 | ||
|
2c3347bf84 | ||
|
1120ef78af | ||
|
a9db71a8b9 | ||
|
10d19b5816 | ||
|
26f62668c6 | ||
|
a9c61a1fd1 | ||
|
17ff272d02 | ||
|
2019f7f657 | ||
|
23298e8f12 | ||
|
1c2f00cddd | ||
|
3bfbf77ac1 | ||
|
7e4f8f1c80 | ||
|
b4507b1bbc | ||
|
6f9d43a02d | ||
|
c803caf1d3 | ||
|
bfda677b1b | ||
|
5ed6408eb9 | ||
|
6a0ae4d55d | ||
|
fbfc2618eb | ||
|
1d0526a6a0 | ||
|
1d0a1f9a79 | ||
|
6d2896a70c | ||
|
95e90ab3e7 | ||
|
66bd88c07f | ||
|
4e897d01ff | ||
|
021510d936 | ||
|
e460a75f4c | ||
|
63980eb7ac | ||
|
264e220b7c | ||
|
1ead2d146d | ||
|
022ae347ae | ||
|
9e46f96a28 | ||
|
6403b041e8 | ||
|
1b8e662769 | ||
|
2b1ff2347c | ||
|
30efac0792 | ||
|
b11161655a | ||
|
ec16dc91ad | ||
|
6d044bb1a6 | ||
|
c987862343 | ||
|
c335fee0d5 | ||
|
0e46cdc624 | ||
|
1283bb4a1c | ||
|
8ebb24123a | ||
|
bf063b5dac | ||
|
22fc2b29fe | ||
|
5aec80da47 | ||
|
b20c6977ca | ||
|
f20dbede2c | ||
|
de1e843b2c | ||
|
049ac96954 | ||
|
0cd4430103 | ||
|
a9cf763bed | ||
|
f117c78d36 | ||
|
c1d9feb391 | ||
|
05553cbff4 | ||
|
9373bee556 | ||
|
a479d5850e | ||
|
7c65b48f34 | ||
|
7b87551404 | ||
|
493c13eac6 | ||
|
636e6ffad9 | ||
|
2500b46f3a | ||
|
48c478961d | ||
|
37b1862e9f | ||
|
ded1e5f7ef | ||
|
99bccefdba | ||
|
ca0f91af27 | ||
|
b5fda88b8a | ||
|
c890cbe71d | ||
|
5244c5c2d7 | ||
|
0d0b767b36 | ||
|
7a896a66d1 | ||
|
3626b4d556 | ||
|
f31bded060 | ||
|
fb1a20d2b0 | ||
|
e720753779 | ||
|
4880c162f8 | ||
|
1e8894abe6 | ||
|
a810fb06d1 | ||
|
18d1c39b0a | ||
|
a7a562bef6 | ||
|
7720097778 | ||
|
27035c926c | ||
|
df8b74bfb6 | ||
|
fa1fbda11f | ||
|
9465ce57ed | ||
|
af0ae907c9 | ||
|
b7a4c13766 | ||
|
77ad3613cf | ||
|
31d6d1e949 | ||
|
e28c9a62ff | ||
|
cdbdad0ba3 | ||
|
cb60995ce1 | ||
|
c4e2f66172 | ||
|
5dfaca7d6e | ||
|
2b18c905f6 | ||
|
d1ff3f8624 | ||
|
00abb96dc2 | ||
|
3017c9fb93 | ||
|
504062abe1 | ||
|
29dfb9fe7e | ||
|
8eaf6c98a1 | ||
|
237c03fa8d | ||
|
5a1b9c1af9 | ||
|
583c06d622 | ||
|
64fe6e9aa6 | ||
|
6124bd1a04 | ||
|
20f12f042b | ||
|
ec9a87d23a | ||
|
b9da151a54 | ||
|
3a59f79223 | ||
|
d23521312f | ||
|
b9a7e3b43c | ||
|
b5973cc370 | ||
|
d6373e6249 | ||
|
d2d4cfa5df | ||
|
f65e0f35b8 | ||
|
159d1e04dd | ||
|
54f35cd370 | ||
|
2a1cb893d0 | ||
|
234c0ca485 | ||
|
181902d3a7 | ||
|
4a78d228c3 | ||
|
07222d24f4 | ||
|
746c4f3b2d | ||
|
3dc2222050 | ||
|
2592b35e4c | ||
|
c89ae65bb7 | ||
|
f33febaa88 | ||
|
a29ece8c82 | ||
|
a730cad49d | ||
|
c71e1482c9 | ||
|
088519f4f8 | ||
|
3a0d71b645 | ||
|
7b5ed03716 | ||
|
77e5e2a97e | ||
|
726396d3f4 | ||
|
5602bd2dc9 | ||
|
fa45fcdb76 | ||
|
b9fc1c8244 | ||
|
380a9da1fd | ||
|
e25617134b | ||
|
811f35c048 | ||
|
1e3c5c1760 | ||
|
65a1b1ac83 | ||
|
79b24ee952 | ||
|
eb685cf7f6 | ||
|
48b394f3bd | ||
|
bb84da4324 | ||
|
b02df18347 | ||
|
e54daf1fd7 | ||
|
533c3b20c9 | ||
|
e6de5366c9 | ||
|
c0a6514a13 | ||
|
8767ccda3b | ||
|
1795f2af45 | ||
|
ea7a0ceb2a | ||
|
644e61cfc2 | ||
|
6c329b3772 | ||
|
79f71d5185 | ||
|
c4d0029f34 | ||
|
17c7fa70e0 | ||
|
c6a82b3442 | ||
|
99edcee93b | ||
|
2a1a92f907 | ||
|
a97c3a35e7 | ||
|
453422cf11 | ||
|
747d9fce39 | ||
|
a7efdf1125 | ||
|
f44db9d1bd | ||
|
36c08cdbb1 | ||
|
2d5b9afb88 | ||
|
39fe8f08db | ||
|
c272b4f937 | ||
|
4fc4b02c26 | ||
|
f903fb2291 | ||
|
4da56b6fe7 | ||
|
171a3ec9dc | ||
|
5cb79330d0 | ||
|
a83e9d0c72 | ||
|
5a4889d57d | ||
|
5d5d84cdc9 | ||
|
dc02106492 | ||
|
4cf83fd6f1 | ||
|
2ec4982889 | ||
|
404acf9fb0 | ||
|
1a6cfad83d | ||
|
637980cc7b | ||
|
49cadecd2d | ||
|
f5f8781a8c | ||
|
604e44267f | ||
|
f60d3b7af8 | ||
|
38b9f4d565 | ||
|
cae6197e4d | ||
|
77876f5432 | ||
|
f7fbec4823 | ||
|
2d54ee16eb | ||
|
5fef73ab99 | ||
|
4abcec6e33 | ||
|
c6be8bdb18 | ||
|
35a7f30459 | ||
|
16fd3e8978 | ||
|
433cc58d0b | ||
|
2eff335680 | ||
|
bb386299b9 | ||
|
ba22ee4674 | ||
|
23be9c823d | ||
|
6bb1bd2239 | ||
|
af6f44177b | ||
|
edbac5a379 | ||
|
c08ff4f287 | ||
|
6adc9da8c1 | ||
|
716febfe70 | ||
|
9ae46b2257 | ||
|
44cbb803f3 | ||
|
fdd9c22144 | ||
|
c2ce4e73ef | ||
|
0b3f19a8ce | ||
|
138a462862 | ||
|
d0c59fc58f | ||
|
c6c53a67dc | ||
|
0031d27abd | ||
|
548abcfc01 | ||
|
a10dd34794 | ||
|
8c004d2418 | ||
|
834e0434d5 | ||
|
7e8c0d75b8 | ||
|
80d6f31c8e | ||
|
7a160d36df | ||
|
f9d38f246d | ||
|
089292b3b9 | ||
|
becff37b4b | ||
|
680ed6e0c3 | ||
|
804e693c4d | ||
|
f2dcb572ad | ||
|
580baa34d2 | ||
|
aee532da44 | ||
|
bfc354146a | ||
|
770a4f0ae9 | ||
|
b08703f71f | ||
|
67939a04d9 | ||
|
fb12488c5f | ||
|
a39749a359 | ||
|
2ab1e7d6c6 |
12
.elasticbeanstalk/config.yml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
branch-defaults:
|
||||||
|
release/prod:
|
||||||
|
environment: mail-prod
|
||||||
|
release/test:
|
||||||
|
environment: mail-test
|
||||||
|
global:
|
||||||
|
application_name: mail
|
||||||
|
default_ec2_keyname: null
|
||||||
|
default_platform: Node.js
|
||||||
|
default_region: eu-central-1
|
||||||
|
profile: eb-cli
|
||||||
|
sc: git
|
10
.gitignore
vendored
@ -5,10 +5,10 @@ test/lib/
|
|||||||
.sass-cache
|
.sass-cache
|
||||||
src/css/
|
src/css/
|
||||||
dist/
|
dist/
|
||||||
|
compile/
|
||||||
release/
|
release/
|
||||||
test/integration/src/
|
test/integration/src/
|
||||||
src/lib/*.js
|
src/img/icons/all.svg
|
||||||
src/js/crypto/aes-cbc.js
|
test/*/index.js
|
||||||
src/js/crypto/crypto-batch.js
|
**/*.browserified.js
|
||||||
src/js/crypto/rsa.js
|
**/*.js.map
|
||||||
src/js/crypto/util.js
|
|
||||||
|
44
.jshintrc
@ -18,31 +18,37 @@
|
|||||||
"unused": true,
|
"unused": true,
|
||||||
|
|
||||||
"predef": [
|
"predef": [
|
||||||
"console",
|
"$",
|
||||||
"importScripts",
|
"inject",
|
||||||
"process",
|
"Promise",
|
||||||
"QUnit",
|
"resolves",
|
||||||
"test",
|
"rejects",
|
||||||
"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",
|
||||||
|
"PhoneNumber",
|
||||||
|
"DOMPurify"
|
||||||
],
|
],
|
||||||
|
|
||||||
"globals": {
|
"globals": {}
|
||||||
}
|
|
||||||
}
|
}
|
@ -1,9 +1,7 @@
|
|||||||
|
sudo: false
|
||||||
language: node_js
|
language: node_js
|
||||||
node_js:
|
node_js:
|
||||||
- "0.10"
|
- "0.12"
|
||||||
before_install:
|
before_install:
|
||||||
- gem install sass
|
- gem install sass
|
||||||
- npm install -g grunt-cli
|
- npm install -g grunt-cli
|
||||||
notifications:
|
|
||||||
email:
|
|
||||||
- build@whiteout.io
|
|
||||||
|
891
Gruntfile.js
@ -1,175 +1,66 @@
|
|||||||
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: {
|
|
||||||
dev: {
|
|
||||||
options: {
|
|
||||||
port: 8580,
|
|
||||||
base: '.',
|
|
||||||
keepalive: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
test: {
|
|
||||||
options: {
|
|
||||||
port: 8581,
|
|
||||||
base: '.'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
prod: {
|
|
||||||
options: {
|
|
||||||
port: process.env.PORT || 8585,
|
|
||||||
base: './dist/',
|
|
||||||
keepalive: true,
|
|
||||||
middleware: function(connect, options) {
|
|
||||||
// Return array of whatever middlewares you want
|
|
||||||
return [
|
|
||||||
function(req, res, next) {
|
|
||||||
res.setHeader('Content-Security-Policy', "default-src 'self'; object-src 'none'; connect-src 'self' https://keys.whiteout.io; img-src 'self' data:;");
|
|
||||||
|
|
||||||
return next();
|
// General
|
||||||
},
|
|
||||||
|
|
||||||
// Serve static files.
|
shell: {
|
||||||
connect.static(options.base)
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
jshint: {
|
|
||||||
all: ['Gruntfile.js', 'src/*.js', 'src/js/**/*.js', 'test/new-unit/*.js', 'test/unit/*.js', 'test/integration/*.js'],
|
|
||||||
options: {
|
options: {
|
||||||
jshintrc: '.jshintrc'
|
stderr: false
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
target: {
|
||||||
qunit: {
|
command: 'dir=$(pwd) && cd node_modules/mailreader/ && npm install --production && cd $dir'
|
||||||
all: {
|
|
||||||
options: {
|
|
||||||
timeout: 20000,
|
|
||||||
urls: ['http://localhost:<%= connect.test.options.port %>/test/unit/index.html'
|
|
||||||
/*,
|
|
||||||
'http://localhost:<%= connect.test.options.port %>/test/integration/index.html'*/
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
mocha: {
|
|
||||||
all: {
|
|
||||||
options: {
|
|
||||||
urls: ['http://localhost:<%= connect.test.options.port %>/test/new-unit/index.html'],
|
|
||||||
run: false,
|
|
||||||
reporter: 'Spec'
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
clean: {
|
clean: {
|
||||||
dist: ['dist', 'src/lib/*.js', 'test/lib', 'test/integration/src']
|
dist: ['dist', 'compile', 'test/lib', 'test/integration/src'],
|
||||||
},
|
release: ['dist/**/*.browserified.js', 'dist/**/*.js.map', 'dist/js/app.templates.js']
|
||||||
sass: {
|
|
||||||
dist: {
|
|
||||||
files: {
|
|
||||||
'src/css/all.css': 'src/sass/all.scss'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
autoprefixer: {
|
|
||||||
options: {
|
|
||||||
browsers: ['last 2 versions']
|
|
||||||
},
|
|
||||||
dist: {
|
|
||||||
files: {
|
|
||||||
'src/css/all.css': 'src/css/all.css'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
csso: {
|
|
||||||
options: {
|
|
||||||
banner: '/*! Copyright © 2013, Whiteout Networks GmbH. All rights reserved.*/\n'
|
|
||||||
},
|
|
||||||
dist: {
|
|
||||||
files: {
|
|
||||||
'dist/css/all.min.css': 'src/css/all.css'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
css: {
|
|
||||||
files: ['src/sass/**/*.scss'],
|
|
||||||
tasks: ['dist-css']
|
|
||||||
},
|
|
||||||
js: {
|
|
||||||
files: ['src/js/**/*.js'],
|
|
||||||
tasks: ['copy:js']
|
|
||||||
},
|
|
||||||
lib: {
|
|
||||||
files: ['src/lib/**/*.js'],
|
|
||||||
tasks: ['copy:lib']
|
|
||||||
},
|
|
||||||
app: {
|
|
||||||
files: ['src/*.js', 'src/**/*.html', 'src/**/*.json', 'src/img/**/*', 'src/font/**/*'],
|
|
||||||
tasks: ['copy:app', 'copy:ca', 'copy:tpl', 'copy:img', 'copy:font', 'manifest-dev']
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
copy: {
|
copy: {
|
||||||
npm: {
|
libTest: {
|
||||||
expand: true,
|
expand: true,
|
||||||
flatten: true,
|
flatten: true,
|
||||||
cwd: 'node_modules/',
|
cwd: './',
|
||||||
src: [
|
src: [
|
||||||
'requirejs/require.js',
|
'node_modules/mocha/mocha.css',
|
||||||
'crypto-lib/node_modules/node-forge/js/*.js',
|
'node_modules/mocha/mocha.js',
|
||||||
'imap-client/src/*.js',
|
'node_modules/chai/chai.js',
|
||||||
'imap-client/node_modules/inbox/src/*.js',
|
'node_modules/sinon/pkg/sinon.js',
|
||||||
'imap-client/node_modules/setimmediate/setImmediate.js',
|
'node_modules/browsercrow/src/*.js',
|
||||||
'imap-client/node_modules/inbox/node_modules/node-shims/src/*.js',
|
'node_modules/browsersmtp/src/*.js',
|
||||||
'imap-client/node_modules/inbox/node_modules/utf7/src/utf7.js',
|
'node_modules/openpgp/dist/openpgp.min.js',
|
||||||
'imap-client/node_modules/inbox/node_modules/xoauth2/src/xoauth2.js',
|
'node_modules/openpgp/dist/openpgp.worker.min.js',
|
||||||
'mailreader/src/*.js',
|
'src/lib/forge/forge.min.js',
|
||||||
'mailreader/node_modules/mailparser/src/*.js',
|
'dist/js/pbkdf2-worker.min.js'
|
||||||
'mailreader/node_modules/mailparser/node_modules/encoding/src/encoding.js',
|
|
||||||
'mailreader/node_modules/mailparser/node_modules/mimelib/src/mimelib.js',
|
|
||||||
'mailreader/node_modules/mailparser/node_modules/mimelib/node_modules/addressparser/src/addressparser.js',
|
|
||||||
'mailreader/node_modules/mailparser/node_modules/encoding/node_modules/iconv-lite/src/*.js',
|
|
||||||
'mailreader/node_modules/mailparser/node_modules/mime/src/mime.js',
|
|
||||||
'pgpmailer/src/*.js',
|
|
||||||
'pgpmailer/node_modules/simplesmtp/src/*',
|
|
||||||
'pgpbuilder/src/*.js',
|
|
||||||
'pgpbuilder/node_modules/mailbuilder/src/*.js'
|
|
||||||
],
|
],
|
||||||
dest: 'src/lib/'
|
|
||||||
},
|
|
||||||
npmDev: {
|
|
||||||
expand: true,
|
|
||||||
flatten: true,
|
|
||||||
cwd: 'node_modules/',
|
|
||||||
src: ['requirejs/require.js', 'mocha/mocha.css', 'mocha/mocha.js', 'chai/chai.js', 'sinon/pkg/sinon.js', 'angularjs/src/ngMock/angular-mocks.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,
|
||||||
cwd: 'src/lib/',
|
flatten: true,
|
||||||
src: ['**'],
|
cwd: './',
|
||||||
dest: 'dist/lib/'
|
src: [
|
||||||
},
|
'node_modules/openpgp/dist/openpgp.min.js',
|
||||||
js: {
|
'node_modules/openpgp/dist/openpgp.worker.min.js',
|
||||||
expand: true,
|
'src/lib/forge/forge.min.js'
|
||||||
cwd: 'src/js/',
|
],
|
||||||
src: ['**'],
|
|
||||||
dest: 'dist/js/'
|
dest: 'dist/js/'
|
||||||
},
|
},
|
||||||
font: {
|
font: {
|
||||||
@ -187,29 +78,496 @@ module.exports = function(grunt) {
|
|||||||
tpl: {
|
tpl: {
|
||||||
expand: true,
|
expand: true,
|
||||||
cwd: 'src/tpl/',
|
cwd: 'src/tpl/',
|
||||||
src: ['*'],
|
src: ['read-sandbox.html'],
|
||||||
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'],
|
src: ['*.js', '*.json', 'manifest.*'],
|
||||||
dest: 'dist/'
|
dest: 'dist/'
|
||||||
},
|
|
||||||
integration: {
|
|
||||||
expand: true,
|
|
||||||
cwd: 'src/',
|
|
||||||
src: ['**'],
|
|
||||||
dest: 'test/integration/src/'
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Stylesheets
|
||||||
|
|
||||||
|
sass: {
|
||||||
|
dist: {
|
||||||
|
files: {
|
||||||
|
'src/css/read-sandbox.css': 'src/sass/read-sandbox.scss',
|
||||||
|
'src/css/all.css': 'src/sass/all.scss'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
styleguide: {
|
||||||
|
files: {
|
||||||
|
'src/css/styleguide.css': 'src/sass/styleguide.scss'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
autoprefixer: {
|
||||||
|
options: {
|
||||||
|
browsers: ['last 2 versions']
|
||||||
|
},
|
||||||
|
dist: {
|
||||||
|
files: {
|
||||||
|
'src/css/read-sandbox.css': 'src/css/read-sandbox.css',
|
||||||
|
'src/css/all.css': 'src/css/all.css'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
styleguide: {
|
||||||
|
files: {
|
||||||
|
'src/css/styleguide.css': 'src/css/styleguide.css'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
csso: {
|
||||||
|
options: {
|
||||||
|
banner: '/*! Copyright © 2013, Whiteout Networks GmbH. All rights reserved.*/\n'
|
||||||
|
},
|
||||||
|
dist: {
|
||||||
|
files: {
|
||||||
|
'dist/css/read-sandbox.min.css': 'src/css/read-sandbox.css',
|
||||||
|
'dist/css/all.min.css': 'src/css/all.css'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
styleguide: {
|
||||||
|
files: {
|
||||||
|
'dist/styleguide/css/styleguide.min.css': 'src/css/styleguide.css'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// JavaScript
|
||||||
|
|
||||||
|
jshint: {
|
||||||
|
all: ['Gruntfile.js', 'src/*.js', 'src/js/**/*.js', 'test/unit/*-test.js', 'test/integration/*-test.js'],
|
||||||
|
options: {
|
||||||
|
jshintrc: '.jshintrc'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
browserify: {
|
||||||
|
app: {
|
||||||
|
files: {
|
||||||
|
'dist/js/app.browserified.js': ['src/js/app.js']
|
||||||
|
},
|
||||||
|
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
|
||||||
|
},
|
||||||
|
compressionWorker: {
|
||||||
|
files: {
|
||||||
|
'dist/js/browserbox-compression-worker.browserified.js': ['node_modules/imap-client/node_modules/browserbox/src/browserbox-compression-worker.js']
|
||||||
|
},
|
||||||
|
options: browserifyOpt
|
||||||
|
},
|
||||||
|
unitTest: {
|
||||||
|
files: {
|
||||||
|
'test/unit/index.browserified.js': [
|
||||||
|
'test/main.js',
|
||||||
|
'test/unit/util/dialog-test.js',
|
||||||
|
'test/unit/util/connection-doctor-test.js',
|
||||||
|
'test/unit/util/update-handler-test.js',
|
||||||
|
'test/unit/util/status-display-test.js',
|
||||||
|
'test/unit/crypto/pgp-test.js',
|
||||||
|
'test/unit/crypto/crypto-test.js',
|
||||||
|
'test/unit/service/rest-dao-test.js',
|
||||||
|
'test/unit/service/admin-dao-test.js',
|
||||||
|
'test/unit/service/auth-test.js',
|
||||||
|
'test/unit/service/oauth-test.js',
|
||||||
|
'test/unit/service/publickey-dao-test.js',
|
||||||
|
'test/unit/service/privatekey-dao-test.js',
|
||||||
|
'test/unit/service/lawnchair-dao-test.js',
|
||||||
|
'test/unit/service/keychain-dao-test.js',
|
||||||
|
'test/unit/service/devicestorage-dao-test.js',
|
||||||
|
'test/unit/service/newsletter-service-test.js',
|
||||||
|
'test/unit/service/mail-config-service-test.js',
|
||||||
|
'test/unit/service/invitation-dao-test.js',
|
||||||
|
'test/unit/service/publickey-verifier-test.js',
|
||||||
|
'test/unit/email/outbox-bo-test.js',
|
||||||
|
'test/unit/email/email-dao-test.js',
|
||||||
|
'test/unit/email/account-test.js',
|
||||||
|
'test/unit/email/search-test.js',
|
||||||
|
'test/unit/controller/login/add-account-ctrl-test.js',
|
||||||
|
'test/unit/controller/login/create-account-ctrl-test.js',
|
||||||
|
'test/unit/controller/login/validate-phone-ctrl-test.js',
|
||||||
|
'test/unit/controller/login/login-existing-ctrl-test.js',
|
||||||
|
'test/unit/controller/login/login-initial-ctrl-test.js',
|
||||||
|
'test/unit/controller/login/login-new-device-ctrl-test.js',
|
||||||
|
'test/unit/controller/login/login-privatekey-download-ctrl-test.js',
|
||||||
|
'test/unit/controller/login/login-privatekey-upload-ctrl-test.js',
|
||||||
|
'test/unit/controller/login/login-verify-public-key-ctrl-test.js',
|
||||||
|
'test/unit/controller/login/login-set-credentials-ctrl-test.js',
|
||||||
|
'test/unit/controller/login/login-ctrl-test.js',
|
||||||
|
'test/unit/controller/app/dialog-ctrl-test.js',
|
||||||
|
'test/unit/controller/app/publickey-import-ctrl-test.js',
|
||||||
|
'test/unit/controller/app/account-ctrl-test.js',
|
||||||
|
'test/unit/controller/app/set-passphrase-ctrl-test.js',
|
||||||
|
'test/unit/controller/app/contacts-ctrl-test.js',
|
||||||
|
'test/unit/controller/app/read-ctrl-test.js',
|
||||||
|
'test/unit/controller/app/navigation-ctrl-test.js',
|
||||||
|
'test/unit/controller/app/mail-list-ctrl-test.js',
|
||||||
|
'test/unit/controller/app/write-ctrl-test.js',
|
||||||
|
'test/unit/controller/app/action-bar-ctrl-test.js',
|
||||||
|
]
|
||||||
|
},
|
||||||
|
options: browserifyOpt
|
||||||
|
},
|
||||||
|
integrationTest: {
|
||||||
|
files: {
|
||||||
|
'test/integration/index.browserified.js': [
|
||||||
|
'test/main.js',
|
||||||
|
'test/integration/email-dao-test.js',
|
||||||
|
'test/integration/publickey-verifier-test.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'],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
ngtemplates: {
|
||||||
|
mail: {
|
||||||
|
src: [
|
||||||
|
'tpl/**/*.html'
|
||||||
|
],
|
||||||
|
dest: 'dist/js/app.templates.js',
|
||||||
|
cwd: 'src/',
|
||||||
|
options: {
|
||||||
|
htmlmin: {
|
||||||
|
collapseWhitespace: true,
|
||||||
|
removeComments: true // we do not use comment directives
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
concat: {
|
||||||
|
options: {
|
||||||
|
separator: ';\n',
|
||||||
|
sourceMap: true
|
||||||
|
},
|
||||||
|
app: {
|
||||||
|
src: [
|
||||||
|
'src/lib/underscore/underscore.js',
|
||||||
|
'node_modules/jquery/dist/jquery.min.js',
|
||||||
|
'src/lib/angular/angular.js',
|
||||||
|
'src/lib/angular/angular-route.js',
|
||||||
|
'src/lib/angular/angular-animate.js',
|
||||||
|
'src/lib/ngtagsinput/ng-tags-input.min.js',
|
||||||
|
'node_modules/ng-infinite-scroll/build/ng-infinite-scroll.min.js',
|
||||||
|
'node_modules/iframe-resizer/js/iframeResizer.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',
|
||||||
|
'src/lib/phonenumber/PhoneNumberMetadata.js',
|
||||||
|
'src/lib/phonenumber/PhoneNumberNormalizer.js',
|
||||||
|
'src/lib/phonenumber/PhoneNumber.js',
|
||||||
|
'dist/js/app.browserified.js',
|
||||||
|
'<%= ngtemplates.mail.dest %>'
|
||||||
|
],
|
||||||
|
dest: 'dist/js/app.min.js',
|
||||||
|
options: {
|
||||||
|
sourceMapName: 'dist/js/app.js.map'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
readSandbox: {
|
||||||
|
src: [
|
||||||
|
'node_modules/dompurify/src/purify.js',
|
||||||
|
'node_modules/iframe-resizer/js/iframeResizer.contentWindow.min.js',
|
||||||
|
'src/js/controller/app/read-sandbox.js'
|
||||||
|
],
|
||||||
|
dest: 'dist/js/read-sandbox.min.js'
|
||||||
|
},
|
||||||
|
pbkdf2Worker: {
|
||||||
|
src: ['dist/js/pbkdf2-worker.browserified.js'],
|
||||||
|
dest: 'dist/js/pbkdf2-worker.min.js'
|
||||||
|
},
|
||||||
|
mailreaderWorker: {
|
||||||
|
src: ['dist/js/mailreader-parser-worker.browserified.js'],
|
||||||
|
dest: 'dist/js/mailreader-parser-worker.min.js'
|
||||||
|
},
|
||||||
|
tlsWorker: {
|
||||||
|
src: ['dist/js/tcp-socket-tls-worker.browserified.js'],
|
||||||
|
dest: 'dist/js/tcp-socket-tls-worker.min.js'
|
||||||
|
},
|
||||||
|
compressionWorker: {
|
||||||
|
src: ['dist/js/browserbox-compression-worker.browserified.js'],
|
||||||
|
dest: 'dist/js/browserbox-compression-worker.min.js'
|
||||||
|
},
|
||||||
|
unitTest: {
|
||||||
|
src: [
|
||||||
|
'src/lib/underscore/underscore.js',
|
||||||
|
'node_modules/jquery/dist/jquery.min.js',
|
||||||
|
'src/lib/angular/angular.js',
|
||||||
|
'src/lib/angular/angular-route.js',
|
||||||
|
'src/lib/angular/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',
|
||||||
|
'src/lib/phonenumber/PhoneNumberMetadata.js',
|
||||||
|
'src/lib/phonenumber/PhoneNumberNormalizer.js',
|
||||||
|
'src/lib/phonenumber/PhoneNumber.js',
|
||||||
|
'test/unit/index.browserified.js'
|
||||||
|
],
|
||||||
|
dest: 'test/unit/index.js',
|
||||||
|
options: {
|
||||||
|
sourceMapName: 'test/unit/index.js.map'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
integrationTest: {
|
||||||
|
src: [
|
||||||
|
'src/lib/underscore/underscore.js',
|
||||||
|
'node_modules/jquery/dist/jquery.min.js',
|
||||||
|
'src/lib/angular/angular.js',
|
||||||
|
'src/lib/angular/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/integration/index.browserified.js'
|
||||||
|
],
|
||||||
|
dest: 'test/integration/index.js',
|
||||||
|
options: {
|
||||||
|
sourceMapName: 'test/integration/index.js.map'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
uglify: {
|
||||||
|
app: {
|
||||||
|
files: {
|
||||||
|
'dist/js/app.min.js': ['dist/js/app.min.js']
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
mangle: false,
|
||||||
|
sourceMap: true,
|
||||||
|
sourceMapIn: 'dist/js/app.js.map',
|
||||||
|
sourceMapIncludeSources: true,
|
||||||
|
sourceMapName: 'dist/js/app.min.js.map'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
readSandbox: {
|
||||||
|
files: {
|
||||||
|
'dist/js/read-sandbox.min.js': ['dist/js/read-sandbox.min.js']
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
sourceMap: true,
|
||||||
|
sourceMapName: 'dist/js/read-sandbox.min.js.map'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
pbkdf2Worker: {
|
||||||
|
files: {
|
||||||
|
'dist/js/pbkdf2-worker.min.js': ['dist/js/pbkdf2-worker.min.js']
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mailreaderWorker: {
|
||||||
|
files: {
|
||||||
|
'dist/js/mailreader-parser-worker.min.js': ['dist/js/mailreader-parser-worker.min.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.min.js']
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
sourceMap: true,
|
||||||
|
sourceMapName: 'dist/js/tcp-socket-tls-worker.min.js.map'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
compressionWorker: {
|
||||||
|
files: {
|
||||||
|
'dist/js/browserbox-compression-worker.min.js': ['dist/js/browserbox-compression-worker.min.js']
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
sourceMap: true,
|
||||||
|
sourceMapName: 'dist/js/browserbox-compression-worker.min.js.map'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
banner: '/*! Copyright © <%= grunt.template.today("yyyy") %>, Whiteout Networks GmbH.*/\n'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
mocha_phantomjs: {
|
||||||
|
all: {
|
||||||
|
options: {
|
||||||
|
urls: [
|
||||||
|
'http://localhost:<%= connect.test.options.port %>/test/unit/index.html',
|
||||||
|
'http://localhost:<%= connect.test.options.port %>/test/integration/index.html'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// Assets
|
||||||
|
|
||||||
|
svgmin: {
|
||||||
|
options: {
|
||||||
|
plugins: [{
|
||||||
|
removeViewBox: false
|
||||||
|
}, {
|
||||||
|
removeUselessStrokeAndFill: false
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
icons: {
|
||||||
|
files: [{
|
||||||
|
expand: true,
|
||||||
|
src: ['img/icons/*.svg', '!img/icons/all.svg'],
|
||||||
|
cwd: 'src/',
|
||||||
|
dest: 'compile/'
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
svgstore: {
|
||||||
|
options: {
|
||||||
|
prefix: 'icon-',
|
||||||
|
svg: {
|
||||||
|
viewBox: '0 0 100 100',
|
||||||
|
xmlns: 'http://www.w3.org/2000/svg'
|
||||||
|
},
|
||||||
|
cleanup: ['fill', 'stroke']
|
||||||
|
},
|
||||||
|
icons: {
|
||||||
|
files: {
|
||||||
|
'src/img/icons/all.svg': ['compile/img/icons/*.svg'],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'string-replace': {
|
||||||
|
index: {
|
||||||
|
files: {
|
||||||
|
'dist/index.html': 'src/index.html'
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
replacements: [{
|
||||||
|
pattern: /<!-- @import (.*?) -->/ig,
|
||||||
|
replacement: function(match, p1) {
|
||||||
|
return grunt.file.read('src/' + p1);
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// Styleguide
|
||||||
|
|
||||||
|
assemble: {
|
||||||
|
options: {
|
||||||
|
assets: 'dist',
|
||||||
|
layoutdir: 'src/styleguide/layouts',
|
||||||
|
layout: 'default.hbs',
|
||||||
|
partials: ['src/styleguide/blocks/**/*.hbs'],
|
||||||
|
helpers: [
|
||||||
|
'handlebars-helper-compose',
|
||||||
|
'src/styleguide/helpers/**/*.js'
|
||||||
|
],
|
||||||
|
data: [
|
||||||
|
'dist/manifest.json'
|
||||||
|
],
|
||||||
|
flatten: true
|
||||||
|
},
|
||||||
|
styleguide: {
|
||||||
|
files: [{
|
||||||
|
'dist/styleguide/': ['src/styleguide/*.hbs']
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// Development
|
||||||
|
|
||||||
|
connect: {
|
||||||
|
dev: {
|
||||||
|
options: {
|
||||||
|
port: 8580,
|
||||||
|
base: '.',
|
||||||
|
keepalive: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
test: {
|
||||||
|
options: {
|
||||||
|
port: 8581,
|
||||||
|
base: '.'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// Utilities
|
||||||
|
|
||||||
|
watch: {
|
||||||
|
css: {
|
||||||
|
files: ['src/sass/**/*.scss'],
|
||||||
|
tasks: ['dist-css', 'offline-cache', 'dist-styleguide']
|
||||||
|
},
|
||||||
|
styleguide: {
|
||||||
|
files: ['src/styleguide/**/*.hbs', 'src/styleguide/**/*.js'],
|
||||||
|
tasks: ['dist-styleguide']
|
||||||
|
},
|
||||||
|
jsApp: {
|
||||||
|
files: ['src/js/**/*.js', 'src/*.html', 'src/tpl/**/*.html'],
|
||||||
|
tasks: ['dist-js-app']
|
||||||
|
},
|
||||||
|
jsUnitTest: {
|
||||||
|
files: ['test/unit/**/*-test.js', 'test/*.js'],
|
||||||
|
tasks: ['dist-js-unitTest']
|
||||||
|
},
|
||||||
|
jsIntegrationTest: {
|
||||||
|
files: ['test/integration/*-test.js', 'test/*.js'],
|
||||||
|
tasks: ['dist-js-integrationTest']
|
||||||
|
},
|
||||||
|
icons: {
|
||||||
|
files: ['src/index.html', 'src/img/icons/*.svg', '!src/img/icons/all.svg'],
|
||||||
|
tasks: ['svgmin', 'svgstore', 'string-replace', 'dist-styleguide', 'offline-cache']
|
||||||
|
},
|
||||||
|
lib: {
|
||||||
|
files: ['src/lib/**/*.js'],
|
||||||
|
tasks: ['copy:lib', 'offline-cache']
|
||||||
|
},
|
||||||
|
app: {
|
||||||
|
files: ['src/*.js', 'src/*.html', 'src/tpl/**/*.html', 'src/**/*.json', 'src/manifest.*', 'src/img/**/*', 'src/font/**/*'],
|
||||||
|
tasks: ['copy:app', 'copy:tpl', 'copy:img', 'copy:font', 'manifest-dev', 'offline-cache']
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// Deployment
|
||||||
|
|
||||||
compress: {
|
compress: {
|
||||||
main: {
|
main: {
|
||||||
options: {
|
options: {
|
||||||
@ -220,37 +578,152 @@ 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: '/'
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
nodewebkit: {
|
// Offline caching
|
||||||
|
|
||||||
|
swPrecache: {
|
||||||
|
prod: {
|
||||||
|
handleFetch: true,
|
||||||
|
rootDir: 'dist'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
manifest: {
|
||||||
|
generate: {
|
||||||
options: {
|
options: {
|
||||||
version: '0.9.2', // node-webkit version
|
basePath: 'dist/',
|
||||||
build_dir: './release/node-webkit/', // Where the build version of my node-webkit app is saved
|
timestamp: true,
|
||||||
mac: true, // We want to build it for mac
|
hash: true,
|
||||||
win: false, // We want to build it for win
|
cache: ['socket.io/socket.io.js'],
|
||||||
linux32: false, // We don't need linux32
|
exclude: [
|
||||||
linux64: false, // We don't need linux64
|
'appcache.manifest',
|
||||||
|
'manifest.webapp',
|
||||||
|
'manifest.mobile.json',
|
||||||
|
'background.js',
|
||||||
|
'service-worker.js',
|
||||||
|
'styleguide/css/styleguide.min.css',
|
||||||
|
'styleguide/index.html',
|
||||||
|
'js/app.templates.js',
|
||||||
|
'js/app.js.map',
|
||||||
|
'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/pbkdf2-worker.min.js.map',
|
||||||
|
'js/read-sandbox.min.js.map',
|
||||||
|
'js/mailreader-parser-worker.browserified.js',
|
||||||
|
'js/mailreader-parser-worker.min.js.map',
|
||||||
|
'js/tcp-socket-tls-worker.browserified.js',
|
||||||
|
'js/tcp-socket-tls-worker.min.js.map',
|
||||||
|
'js/browserbox-compression-worker.browserified.js',
|
||||||
|
'js/browserbox-compression-worker.min.js.map',
|
||||||
|
'img/icon-100-ios.png',
|
||||||
|
'img/icon-114-ios.png',
|
||||||
|
'img/icon-120-ios.png',
|
||||||
|
'img/icon-128-chrome.png',
|
||||||
|
'img/icon-144-android.png',
|
||||||
|
'img/icon-144-ios.png',
|
||||||
|
'img/icon-152-ios.png',
|
||||||
|
'img/icon-180-ios.png',
|
||||||
|
'img/icon-192-android.png',
|
||||||
|
'img/icon-29-ios.png',
|
||||||
|
'img/icon-36-android.png',
|
||||||
|
'img/icon-40-ios.png',
|
||||||
|
'img/icon-48-android.png',
|
||||||
|
'img/icon-50-ios.png',
|
||||||
|
'img/icon-57-ios.png',
|
||||||
|
'img/icon-58-ios.png',
|
||||||
|
'img/icon-60-android.png',
|
||||||
|
'img/icon-60-ios.png',
|
||||||
|
'img/icon-72-android.png',
|
||||||
|
'img/icon-72-ios.png',
|
||||||
|
'img/icon-76-ios.png',
|
||||||
|
'img/icon-78-android.png',
|
||||||
|
'img/icon-80-ios.png',
|
||||||
|
'img/icon-87-ios.png',
|
||||||
|
'img/icon-96-android.png',
|
||||||
|
'img/Default-568h@2x~iphone.png',
|
||||||
|
'img/Default-667h.png',
|
||||||
|
'img/Default-736h.png',
|
||||||
|
'img/Default-Landscape-736h.png',
|
||||||
|
'img/Default-Landscape@2x~ipad.png',
|
||||||
|
'img/Default-Landscape~ipad.png',
|
||||||
|
'img/Default-Portrait@2x~ipad.png',
|
||||||
|
'img/Default-Portrait~ipad.png',
|
||||||
|
'img/Default@2x~iphone.png',
|
||||||
|
'img/Default~iphone.png'
|
||||||
|
],
|
||||||
|
master: ['index.html']
|
||||||
},
|
},
|
||||||
src: ['./dist/**/*'] // Your node-webkit app
|
src: ['**/*.*'],
|
||||||
|
dest: 'dist/appcache.manifest'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
// generate service-worker stasks
|
||||||
|
grunt.registerMultiTask('swPrecache', function() {
|
||||||
|
var fs = require('fs');
|
||||||
|
var path = require('path');
|
||||||
|
var swPrecache = require('sw-precache');
|
||||||
|
var packageJson = require('./package.json');
|
||||||
|
|
||||||
|
var done = this.async();
|
||||||
|
var rootDir = this.data.rootDir;
|
||||||
|
var handleFetch = this.data.handleFetch;
|
||||||
|
|
||||||
|
generateServiceWorkerFileContents(rootDir, handleFetch, function(error, serviceWorkerFileContents) {
|
||||||
|
if (error) {
|
||||||
|
grunt.fail.warn(error);
|
||||||
|
}
|
||||||
|
fs.writeFile(path.join(rootDir, 'service-worker.js'), serviceWorkerFileContents, function(error) {
|
||||||
|
if (error) {
|
||||||
|
grunt.fail.warn(error);
|
||||||
|
}
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function generateServiceWorkerFileContents(rootDir, handleFetch, callback) {
|
||||||
|
var config = {
|
||||||
|
cacheId: packageJson.name,
|
||||||
|
// If handleFetch is false (i.e. because this is called from swPrecache:dev), then
|
||||||
|
// the service worker will precache resources but won't actually serve them.
|
||||||
|
// This allows you to test precaching behavior without worry about the cache preventing your
|
||||||
|
// local changes from being picked up during the development cycle.
|
||||||
|
handleFetch: handleFetch,
|
||||||
|
logger: grunt.log.writeln,
|
||||||
|
dynamicUrlToDependencies: {
|
||||||
|
'socket.io/socket.io.js': ['node_modules/socket.io/node_modules/socket.io-client/socket.io.js'],
|
||||||
},
|
},
|
||||||
|
staticFileGlobs: [
|
||||||
|
rootDir + '/*.html',
|
||||||
|
rootDir + '/tpl/*.html',
|
||||||
|
rootDir + '/js/**/*.min.js',
|
||||||
|
rootDir + '/css/**/*.css',
|
||||||
|
rootDir + '/img/**/*.svg',
|
||||||
|
rootDir + '/img/*-universal.png',
|
||||||
|
rootDir + '/font/**.*',
|
||||||
|
rootDir + '/*.json'
|
||||||
|
],
|
||||||
|
maximumFileSizeToCacheInBytes: 100 * 1024 * 1024,
|
||||||
|
stripPrefix: path.join(rootDir, path.sep)
|
||||||
|
};
|
||||||
|
|
||||||
|
swPrecache(config, callback);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Load the plugin(s)
|
// Load the plugin(s)
|
||||||
|
grunt.loadNpmTasks('grunt-browserify');
|
||||||
|
grunt.loadNpmTasks('grunt-contrib-concat');
|
||||||
|
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-contrib-qunit');
|
|
||||||
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');
|
||||||
@ -258,17 +731,50 @@ 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-mocha-phantomjs');
|
||||||
|
grunt.loadNpmTasks('grunt-exorcise');
|
||||||
|
grunt.loadNpmTasks('grunt-string-replace');
|
||||||
|
grunt.loadNpmTasks('grunt-svgmin');
|
||||||
|
grunt.loadNpmTasks('grunt-svgstore');
|
||||||
|
grunt.loadNpmTasks('grunt-shell');
|
||||||
|
grunt.loadNpmTasks('grunt-angular-templates');
|
||||||
|
grunt.loadNpmTasks('assemble');
|
||||||
|
|
||||||
// Build tasks
|
// Build tasks
|
||||||
grunt.registerTask('dist-npm', ['copy:npm', 'copy:npmDev', 'copy:cryptoLib']);
|
grunt.registerTask('dist-css', ['sass:dist', 'autoprefixer:dist', 'csso:dist']);
|
||||||
grunt.registerTask('dist-css', ['sass', 'autoprefixer', 'csso']);
|
grunt.registerTask('dist-js', ['browserify', 'exorcise', 'ngtemplates', 'concat', 'uglify']);
|
||||||
|
grunt.registerTask('dist-js-app', [
|
||||||
|
'browserify:app',
|
||||||
|
'browserify:pbkdf2Worker',
|
||||||
|
'exorcise:app',
|
||||||
|
'ngtemplates',
|
||||||
|
'concat:app',
|
||||||
|
'concat:readSandbox',
|
||||||
|
'concat:pbkdf2Worker',
|
||||||
|
'offline-cache'
|
||||||
|
]);
|
||||||
|
grunt.registerTask('dist-js-unitTest', [
|
||||||
|
'browserify:unitTest',
|
||||||
|
'exorcise:unitTest',
|
||||||
|
'concat:unitTest'
|
||||||
|
]);
|
||||||
|
grunt.registerTask('dist-js-integrationTest', [
|
||||||
|
'browserify:integrationTest',
|
||||||
|
'exorcise:integrationTest',
|
||||||
|
'concat:integrationTest'
|
||||||
|
]);
|
||||||
grunt.registerTask('dist-copy', ['copy']);
|
grunt.registerTask('dist-copy', ['copy']);
|
||||||
grunt.registerTask('dist', ['clean', 'dist-npm', 'dist-css', 'dist-copy']);
|
grunt.registerTask('dist-assets', ['svgmin', 'svgstore', 'string-replace']);
|
||||||
|
grunt.registerTask('dist-styleguide', ['sass:styleguide', 'autoprefixer:styleguide', 'csso:styleguide', 'assemble:styleguide']);
|
||||||
|
// generate styleguide after manifest to forward version number to styleguide
|
||||||
|
grunt.registerTask('dist', ['clean:dist', 'shell', 'dist-css', 'dist-js', 'dist-assets', 'dist-copy', 'manifest', 'dist-styleguide']);
|
||||||
|
|
||||||
|
grunt.registerTask('offline-cache', ['manifest', 'swPrecache:prod']);
|
||||||
|
|
||||||
// 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']);
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -278,12 +784,12 @@ module.exports = function(grunt) {
|
|||||||
grunt.registerTask('manifest-dev', function() {
|
grunt.registerTask('manifest-dev', function() {
|
||||||
patchManifest({
|
patchManifest({
|
||||||
suffix: ' (DEV)',
|
suffix: ' (DEV)',
|
||||||
version: '9999.9999.9999.9999'
|
version: '9999.9999.9999'
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
grunt.registerTask('manifest-test', function() {
|
grunt.registerTask('manifest-test', function() {
|
||||||
if (!version) {
|
if (!version) {
|
||||||
throw new Error('You must specify the version: "--release=1.0"');
|
throw new Error('You must specify the version: "--release=1.0.0"');
|
||||||
}
|
}
|
||||||
|
|
||||||
patchManifest({
|
patchManifest({
|
||||||
@ -293,13 +799,12 @@ module.exports = function(grunt) {
|
|||||||
deleteKey: true
|
deleteKey: true
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
grunt.registerTask('manifest-stable', function() {
|
grunt.registerTask('manifest-prod', function() {
|
||||||
if (!version) {
|
if (!version) {
|
||||||
throw new Error('You must specify the version: "--release=1.0"');
|
throw new Error('You must specify the version: "--release=1.0.0"');
|
||||||
}
|
}
|
||||||
|
|
||||||
patchManifest({
|
patchManifest({
|
||||||
suffix: ' (Alpha)',
|
|
||||||
version: version,
|
version: version,
|
||||||
deleteKey: true,
|
deleteKey: true,
|
||||||
keyServer: 'https://keys.whiteout.io/'
|
keyServer: 'https://keys.whiteout.io/'
|
||||||
@ -331,9 +836,9 @@ module.exports = function(grunt) {
|
|||||||
fs.writeFileSync(path, JSON.stringify(manifest, null, 2));
|
fs.writeFileSync(path, JSON.stringify(manifest, null, 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
grunt.registerTask('release-dev', ['dist', 'manifest-dev', 'compress']);
|
grunt.registerTask('release-dev', ['dist', 'manifest-dev', 'swPrecache:prod', 'compress']);
|
||||||
grunt.registerTask('release-test', ['dist', 'manifest-test', 'compress']);
|
grunt.registerTask('release-test', ['dist', 'manifest-test', 'clean:release', 'swPrecache:prod', 'compress']);
|
||||||
grunt.registerTask('release-stable', ['dist', 'manifest-stable', 'compress']);
|
grunt.registerTask('release-prod', ['dist', 'manifest-prod', 'clean:release', 'swPrecache:prod', 'compress']);
|
||||||
grunt.registerTask('default', ['release-dev']);
|
grunt.registerTask('default', ['release-dev']);
|
||||||
|
|
||||||
};
|
};
|
25
LICENSE.txt
@ -1,6 +1,21 @@
|
|||||||
Copyright © 2013, Whiteout Networks GmbH. All rights reserved.
|
The MIT License (MIT)
|
||||||
|
|
||||||
The code is open for inspection and peer review by the security community.
|
Copyright (c) 2014 Whiteout Networks GmbH.
|
||||||
The code is currently not licensed under an open source license. If you're
|
|
||||||
interested in contributing or getting a license, please get in touch with
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
us (info@whiteout.io).
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
124
README.md
@ -1,66 +1,142 @@
|
|||||||
mail-html5 [![Build Status](https://travis-ci.org/whiteout-io/mail-html5.png)](https://travis-ci.org/whiteout-io/mail-html5)
|
Whiteout Mail [![Build Status](https://travis-ci.org/whiteout-io/mail.svg?branch=master)](https://travis-ci.org/whiteout-io/mail)
|
||||||
==========
|
==========
|
||||||
|
|
||||||
Whiteout Mail is an easy to use email client with integrated OpenPGP encryption written in pure JavaScript. Download the official version under [whiteout.io](http://whiteout.io).
|
Whiteout Mail is an easy to use email client with integrated OpenPGP encryption written in pure JavaScript. Download the official version under [whiteout.io](https://whiteout.io/#product).
|
||||||
|
|
||||||
|
![Screenshot](https://whiteout.io/img/screens.png)
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|
||||||
You can read about product features and our future roadmap in our [FAQ](https://github.com/whiteout-io/mail-html5/wiki/FAQ).
|
You can read about product features and our future roadmap in our [FAQ](https://github.com/whiteout-io/mail/wiki/FAQ).
|
||||||
|
|
||||||
### Privacy and Security
|
### Privacy and Security
|
||||||
|
|
||||||
We take the privacy of your data very seriously. Here are some of the technical details:
|
We take the privacy of your data very seriously. Here are some of the technical details:
|
||||||
|
|
||||||
* Messages are [encrypted end-to-end ](http://en.wikipedia.org/wiki/End-to-end_encryption) using the [OpenPGP](http://en.wikipedia.org/wiki/Pretty_Good_Privacy) standard. This means that only you and the recipient can read your mail. Your messages and private PGP key are stored encrypted on your computer and are never sent to our our servers.
|
* The code has undergone a [full security audit](https://blog.whiteout.io/2015/06/11/whiteout-mail-1-0-and-security-audit-by-cure53/) by [Cure53](https://cure53.de).
|
||||||
|
|
||||||
* Like most native email clients whiteout mail uses raw [TCP sockets](http://developer.chrome.com/apps/socket.html) to communicate directly with your mail server via IMAP/SMTP.
|
* Messages are [encrypted end-to-end ](http://en.wikipedia.org/wiki/End-to-end_encryption) using the [OpenPGP](http://en.wikipedia.org/wiki/Pretty_Good_Privacy) standard. This means that only you and the recipient can read your mail. Your messages and private PGP key are stored only on your computer (in IndexedDB).
|
||||||
|
|
||||||
* Mail server [SSL certificates are pinned](http://security.stackexchange.com/questions/29988/what-is-certificate-pinning) under [`src/ca/`](https://github.com/whiteout-io/mail-html5/tree/master/src/ca) in order to protect against SSL certificate forgery and other man in the middle attacks.
|
* Users have the option to use [encrypted private key sync](https://github.com/whiteout-io/mail/wiki/Secure-OpenPGP-Key-Pair-Synchronization-via-IMAP) if they want to use Whiteout on multiple devices.
|
||||||
|
|
||||||
* The app is deployed as a [Chrome Packaged App](https://developer.chrome.com/apps/about_apps.html) with [auditable static versions](https://github.com/whiteout-io/mail-html5/releases) in order to prevent [problems with host-based security](http://tonyarcieri.com/whats-wrong-with-webcrypto).
|
* [Content Security Policy (CSP)](http://www.html5rocks.com/en/tutorials/security/content-security-policy/) is enforced to prevent injection attacks.
|
||||||
|
|
||||||
* [Content Security Policy (CSP)](http://www.html5rocks.com/en/tutorials/security/content-security-policy/) is enforced to prevent against injection attacks.
|
* HTML mails are sanitized with [DOMPurify](https://github.com/cure53/DOMPurify) and are rendered in a sandboxed iframe.
|
||||||
|
|
||||||
* The code is still under heavy development and is not yet recommended for production use. That being said, we have done multiple code audits and penetration tests (which will be published regularly once all reported vulnerabilities are fixed).
|
* Displaying mail images is optional and opt-in by default.
|
||||||
|
|
||||||
|
* Like most native email clients, whiteout mail uses raw [TCP sockets](http://developer.chrome.com/apps/socket.html) to communicate directly with your mail server via IMAP/SMTP. TLS is used to protect your password and message data in transit.
|
||||||
|
|
||||||
|
* The app is deployed as a signed [Chrome Packaged App](https://developer.chrome.com/apps/about_apps.html) with [auditable static versions](https://github.com/whiteout-io/mail/releases) in order to prevent [problems with host-based security](https://blog.whiteout.io/2014/04/13/heartbleed-and-javascript-crypto/).
|
||||||
|
|
||||||
|
* The app can also be used from any modern web browser in environments where installing an app is not possible (e.g. a locked down corporate desktop). The IMAP/SMTP TLS sessions are still terminated in the user's browser using JS crypto ([Forge](https://github.com/digitalbazaar/forge)), but the encrypted TLS payload is proxied via [socket.io](http://socket.io/), due to the lack of raw sockets in the browser. **Please keep in mind that this mode of operation is not as secure as using the signed packaged app, since users must trust the webserver to deliver the correct code. This mode will still protect user against passive attacks like wiretapping (since PGP and TLS are still applied in the user's browser), but not against active attacks from the webserver. So it's best to decide which threat model applies to you.**
|
||||||
|
|
||||||
|
### Architecture
|
||||||
|
|
||||||
|
![client architecture](https://whiteout.io/img/app_layers.png)
|
||||||
|
|
||||||
### Reporting bugs and feature requests
|
### Reporting bugs and feature requests
|
||||||
|
|
||||||
* We will launch a bug bounty program later on for independant security researchers. If you find any security vulnerabilities, don't hesitate to contact us [security@whiteout.io](mailto:security@whiteout.io).
|
* We will launch a bug bounty program later on for independent security researchers. If you find any security vulnerabilities, don't hesitate to contact us [security@whiteout.io](mailto:security@whiteout.io).
|
||||||
|
|
||||||
* You can also just create an [issue](https://github.com/whiteout-io/mail-html5/issues) on GitHub if you're missing a feature or just want to give us feedback. It would be much appreciated!
|
* You can also just create an [issue](https://github.com/whiteout-io/mail/issues) on GitHub if you're missing a feature or just want to give us feedback. It would be much appreciated!
|
||||||
|
|
||||||
### Testing
|
### Testing
|
||||||
|
|
||||||
You can download a prebuilt bundle under [releases](https://github.com/whiteout-io/mail-html5/releases) or build your own from source (requires [node.js](http://nodejs.org/download/), [grunt](http://gruntjs.com/getting-started#installing-the-cli) and [sass](http://sass-lang.com/install)):
|
You can download a prebuilt bundle under [releases](https://github.com/whiteout-io/mail/releases) or build your own from source (requires [node.js](http://nodejs.org/download/), [grunt](http://gruntjs.com/getting-started#installing-the-cli) and [sass](http://sass-lang.com/install)):
|
||||||
|
|
||||||
npm install && npm test
|
npm install && npm test
|
||||||
|
|
||||||
This will download all dependencies, run the tests and build the Chrome Packaged App bundle **DEV.zip** which can be installed under [chrome://extensions](chrome://extensions) in developer mode.
|
This will download all dependencies, run the tests and build the Chrome Packaged App bundle **release/whiteout-mail_DEV.zip** which can be installed under [chrome://extensions](chrome://extensions) in developer mode.
|
||||||
|
|
||||||
### Development
|
### Development
|
||||||
For development you can start a connect dev server:
|
For development you can start a connect dev server:
|
||||||
|
|
||||||
grunt dev
|
grunt dev
|
||||||
|
|
||||||
Then visit [http://localhost:8580/dist/chrome.html#/desktop](http://localhost:8580/dist/chrome.html#/desktop) for front-end code or [http://localhost:8580/test/new-unit/](http://localhost:8580/test/new-unit/) to test JavaScript changes. You can also start a watch task so you don't have rebuild everytime you make a change:
|
Then visit [http://localhost:8580/dist/#/account?dev=true](http://localhost:8580/dist/#/account?dev=true) for front-end code or [http://localhost:8580/test/unit/](http://localhost:8580/test/unit/) to test JavaScript changes. You can also start a watch task so you don't have rebuild everytime you make a change:
|
||||||
|
|
||||||
grunt watch
|
grunt watch
|
||||||
|
|
||||||
|
## Releasing Chrome App
|
||||||
|
|
||||||
|
grunt release-test --release=0.0.0.x
|
||||||
|
grunt release-stable --release=0.x.0
|
||||||
|
|
||||||
|
## Deploying Web App & Selfhosting
|
||||||
|
|
||||||
|
The App can be used either as a Chrome Packaged App or just by hosting it on your own trusted web server. You can build the app from source.
|
||||||
|
|
||||||
|
### Build from source
|
||||||
|
|
||||||
|
Clone the git repository
|
||||||
|
|
||||||
|
git clone https://github.com/whiteout-io/mail.git
|
||||||
|
|
||||||
|
Build and generate the `dist/` directory:
|
||||||
|
|
||||||
|
npm install && grunt
|
||||||
|
|
||||||
|
### Running the server
|
||||||
|
|
||||||
|
To test the server, start it in development mode (without SSL):
|
||||||
|
|
||||||
|
node server.js --dev
|
||||||
|
|
||||||
|
Navigate to [http://localhost:8889](http://localhost:8889) (or whatever port is set using the `PORT` environment variable).
|
||||||
|
|
||||||
|
To start the server for production use (this automatically redirects to `https`)
|
||||||
|
|
||||||
|
npm start
|
||||||
|
|
||||||
|
**A note on security: The app should not be used without SSL so it's best to set up a reverse proxy or Loadbalancer with your SSL certificates. If you are not sure how to do this it might be easier to use our managed web hosting or packaged apps under [https://whiteout.io/#product](https://whiteout.io/#product).**
|
||||||
|
|
||||||
|
You can limit incoming and outgoing connections to the socket.io proxy by setting the following environment variables:
|
||||||
|
|
||||||
|
# the web socket proxy listens to this port
|
||||||
|
# if unset, defaults to 8889
|
||||||
|
PORT=12345
|
||||||
|
|
||||||
|
# the socket.io proxy accepts connections from these origins to tunnel them to tcp,
|
||||||
|
# separate with commas
|
||||||
|
# if unset, defaults to 'localhost:' + port
|
||||||
|
INBOUND_ORIGINS='foo:1234,bar:569'
|
||||||
|
|
||||||
|
# the socket.io proxy opens tcp connections with these ports to tunnel them to socket.io
|
||||||
|
# separate with commas
|
||||||
|
# if unset, defaults to '143,465,587,993' (25 is forbidden by default)
|
||||||
|
OUTBOUND_PORTS='123,456,789'
|
||||||
|
|
||||||
|
To start the server in development mode (no forced HTTPS, iframe loads http content), run `node server.js --dev`
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
Copyright © 2013, Whiteout Networks GmbH. All rights reserved.
|
The MIT License (MIT)
|
||||||
|
|
||||||
The code is open for inspection and peer review by the security community.
|
Copyright (c) 2014 Whiteout Networks GmbH.
|
||||||
The code is currently not licensed under an open source license. If you're
|
|
||||||
interested in contributing or getting a license, please get in touch with
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
us (info@whiteout.io).
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
|
||||||
### Third party libraries
|
### Third party libraries
|
||||||
|
|
||||||
We work together with existing open source projects wherever possible and contribute any changes we make back upstream. Many of theses libraries are licensed under an open source license. Here are some of them:
|
We work together with existing open source projects wherever possible and contribute any changes we make back upstream. Many of theses libraries are licensed under an open source license. Here are some of them:
|
||||||
|
|
||||||
* [OpenPGP.js](http://openpgpjs.org): An implementation of OpenPGP in Javascript
|
* [OpenPGP.js](http://openpgpjs.org) (LGPL license): An implementation of OpenPGP in Javascript
|
||||||
* [Inbox](https://github.com/andris9/inbox): Simple IMAP client for node.js
|
* [email.js](http://emailjs.org) (MIT license): IMAP, SMTP, MIME-building and MIME-parsing engine
|
||||||
* [Nodemailer](http://www.nodemailer.com): SMTP client for node.js
|
* [Forge](https://github.com/digitalbazaar/forge) (BSD license): An implementation of TLS in JavaScript
|
||||||
* [Forge](https://github.com/digitalbazaar/forge): An implementation of TLS in Javascript
|
|
||||||
* [node-shims](https://github.com/whiteout-io/node-shims): Shims for wrapping node's net/tls (TCP socket) APIs around chrome.socket
|
|
||||||
|
19
config/default.js
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var port = process.env.PORT || 8889;
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
server: {
|
||||||
|
port: port,
|
||||||
|
inboundOrigins: (process.env.INBOUND_ORIGINS || ('localhost:' + port)).split(',').map(function(host) {
|
||||||
|
return host.trim();
|
||||||
|
}),
|
||||||
|
outboundPorts: (process.env.OUTBOUND_PORTS || '143,465,587,993').split(',').map(function(i) {
|
||||||
|
return parseInt(i, 10);
|
||||||
|
})
|
||||||
|
},
|
||||||
|
log: {
|
||||||
|
level: "silly",
|
||||||
|
http: ':remote-addr [:date] ":method :url HTTP/:http-version" :status :res[content-length] ":referrer"'
|
||||||
|
}
|
||||||
|
};
|
10
config/integration.js
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
server: {
|
||||||
|
port: 8889
|
||||||
|
},
|
||||||
|
log: {
|
||||||
|
level: "error"
|
||||||
|
}
|
||||||
|
};
|
7
config/production.js
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
log: {
|
||||||
|
level: "error"
|
||||||
|
}
|
||||||
|
};
|
81
package.json
@ -1,39 +1,68 @@
|
|||||||
{
|
{
|
||||||
"name": "mail-html5",
|
"name": "whiteout-mail",
|
||||||
"version": "0.1.0-dev",
|
"description": "Mail App with integrated OpenPGP encryption.",
|
||||||
|
"author": "Whiteout Networks",
|
||||||
|
"homepage": "https://whiteout.io",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.8"
|
"node": ">=0.10"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"postinstall": "grunt dist-npm",
|
"test": "grunt && grunt test",
|
||||||
"test": "grunt test && grunt",
|
"start": "node server.js"
|
||||||
"start": "grunt && grunt dev"
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"crypto-lib": "https://github.com/whiteout-io/crypto-lib/tarball/v0.1.0",
|
"compression": "^1.0.11",
|
||||||
"imap-client": "https://github.com/whiteout-io/imap-client/tarball/v0.1.0",
|
"config": "^1.0.2",
|
||||||
"mailreader": "https://github.com/whiteout-io/mailreader/tarball/v0.1.0",
|
"express": "^4.8.3",
|
||||||
"pgpmailer": "https://github.com/whiteout-io/pgpmailer/tarball/v0.1.0",
|
"morgan": "^1.2.3",
|
||||||
"pgpbuilder": "https://github.com/whiteout-io/pgpbuilder/tarball/v0.1.0",
|
"npmlog": "^0.1.1",
|
||||||
"requirejs": "2.1.10"
|
"socket.io": "^1.0.6"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"angular": "https://github.com/angular/angular.js/tarball/v1.2.8",
|
"assemble": "~0.4.42",
|
||||||
|
"axe-logger": "~0.0.2",
|
||||||
|
"browsercrow": "https://github.com/whiteout-io/browsercrow/tarball/master",
|
||||||
|
"browsersmtp": "https://github.com/whiteout-io/browsersmtp/tarball/master",
|
||||||
|
"chai": "~1.9.2",
|
||||||
|
"crypto-lib": "~0.2.1",
|
||||||
|
"dompurify": "~0.7.3",
|
||||||
"grunt": "~0.4.1",
|
"grunt": "~0.4.1",
|
||||||
"mocha": "~1.13.0",
|
"grunt-angular-templates": "~0.5.7",
|
||||||
"chai": "~1.7.2",
|
"grunt-autoprefixer": "~0.7.2",
|
||||||
"sinon": "~1.7.3",
|
"grunt-browserify": "3.7.0",
|
||||||
"grunt-contrib-connect": "~0.5.0",
|
"insert-module-globals": "6.5.0",
|
||||||
"grunt-contrib-jshint": "~0.6.4",
|
|
||||||
"grunt-contrib-qunit": "~0.2.2",
|
|
||||||
"grunt-mocha": "~0.4.1",
|
|
||||||
"grunt-contrib-clean": "~0.5.0",
|
"grunt-contrib-clean": "~0.5.0",
|
||||||
"grunt-csso": "~0.5.0",
|
|
||||||
"grunt-contrib-sass": "~0.5.0",
|
|
||||||
"grunt-autoprefixer": "~0.3.0",
|
|
||||||
"grunt-contrib-watch": "~0.5.3",
|
|
||||||
"grunt-contrib-copy": "~0.4.1",
|
|
||||||
"grunt-contrib-compress": "~0.5.2",
|
"grunt-contrib-compress": "~0.5.2",
|
||||||
"grunt-node-webkit-builder": "~0.1.17"
|
"grunt-contrib-concat": "^0.5.0",
|
||||||
|
"grunt-contrib-connect": "~0.5.0",
|
||||||
|
"grunt-contrib-copy": "~0.4.1",
|
||||||
|
"grunt-contrib-jshint": "~0.6.4",
|
||||||
|
"grunt-contrib-sass": "~0.7.3",
|
||||||
|
"grunt-contrib-uglify": "^0.6.0",
|
||||||
|
"grunt-contrib-watch": "~0.5.3",
|
||||||
|
"grunt-csso": "~0.6.1",
|
||||||
|
"grunt-exorcise": "^0.2.0",
|
||||||
|
"grunt-manifest": "^0.4.0",
|
||||||
|
"grunt-mocha-phantomjs": "^0.7.0",
|
||||||
|
"grunt-shell": "~1.1.1",
|
||||||
|
"grunt-string-replace": "~1.0.0",
|
||||||
|
"grunt-svgmin": "~1.0.0",
|
||||||
|
"grunt-svgstore": "~0.3.4",
|
||||||
|
"handlebars-helper-compose": "~0.2.12",
|
||||||
|
"iframe-resizer": "^2.8.3",
|
||||||
|
"imap-client": "~0.14.2",
|
||||||
|
"jquery": "~2.1.1",
|
||||||
|
"mailbuild": "^0.3.7",
|
||||||
|
"mailreader": "~0.4.0",
|
||||||
|
"mocha": "^1.21.4",
|
||||||
|
"ng-infinite-scroll": "~1.1.2",
|
||||||
|
"openpgp": "^1.0.0",
|
||||||
|
"pgpbuilder": "~0.6.0",
|
||||||
|
"pgpmailer": "~0.9.1",
|
||||||
|
"sinon": "~1.7.3",
|
||||||
|
"sw-precache": "^1.3.0",
|
||||||
|
"tcp-socket": "~0.5.0",
|
||||||
|
"time-grunt": "^1.0.0",
|
||||||
|
"wo-smtpclient": "~0.6.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,21 +0,0 @@
|
|||||||
THANK YOU FOR USING GLYPHICONS!
|
|
||||||
|
|
||||||
If you would like to be among the first ones to hear about all the news, follow @glyphicons on Twitter.
|
|
||||||
|
|
||||||
LICENSE:
|
|
||||||
-------------------
|
|
||||||
GLYPHICONS FREE are released under the Creative Commons Attribution 3.0 Unported (CC BY 3.0). The Glyphicons FREE can be used both commercially and for personal use, but you must always add a link to www.glyphicons.com in a prominent place (e.g. the footer of a website), include the CC-BY license and the reference to www.glyphicons.com on every page using Glyphicons.
|
|
||||||
|
|
||||||
Glyphicons Halflings are also a part of Bootstrap by Twitter, and are released under the same Apache 2.0 license as Bootstrap. While you are not required to include attribution on your Bootstrap-based projects, I'd certainly appreciate a visibile link back to glyphicons.com in any place you find appropriate (footer, docs, etc).
|
|
||||||
|
|
||||||
All logos and trademarks in social icons are the property of the respective trademark owners.®
|
|
||||||
|
|
||||||
CONTACT:
|
|
||||||
-------------------
|
|
||||||
Web: http://glyphicons.com/
|
|
||||||
Email: glyphicons@gmail.com
|
|
||||||
Twitter: http://twitter.com/glyphicons
|
|
||||||
|
|
||||||
If you want to use the icons without restrictions, please buy any version on www.glyphicons.com, thank you.
|
|
||||||
|
|
||||||
Jan Kovařík
|
|
2
res/android-release-keys.properties
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
storeFile=/Users/tanx/.keystore
|
||||||
|
keyAlias=mykey
|
45
res/aws_release.sh
Executable file
@ -0,0 +1,45 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# go to root
|
||||||
|
cd `dirname $0`
|
||||||
|
cd ..
|
||||||
|
|
||||||
|
if [ "$#" -ne 3 ] || [ "$1" != "prod" ] && [ "$1" != "test" ] ; then
|
||||||
|
echo 'Usage: ./res/aws_release prod|test from-branch 1.0.0'
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# switch branch
|
||||||
|
git checkout $2
|
||||||
|
git branch -D release/$1
|
||||||
|
git checkout -b release/$1
|
||||||
|
git merge $2 --no-edit
|
||||||
|
|
||||||
|
# abort if tests fail
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# build and test
|
||||||
|
rm -rf node_modules/
|
||||||
|
npm cache clear
|
||||||
|
npm install
|
||||||
|
npm test
|
||||||
|
grunt release-$1 --release=$3
|
||||||
|
|
||||||
|
# install only production dependencies
|
||||||
|
rm -rf node_modules/
|
||||||
|
npm install --production
|
||||||
|
|
||||||
|
# delete .gitignore files before adding to git for aws deployment
|
||||||
|
find node_modules/ -name ".gitignore" -exec rm -rf {} \;
|
||||||
|
|
||||||
|
# Add runtime dependencies to git
|
||||||
|
sed -i "" '/dist/d' .gitignore
|
||||||
|
sed -i "" '/node_modules/d' .gitignore
|
||||||
|
git add .gitignore node_modules/ dist/
|
||||||
|
git commit -m "Update release"
|
||||||
|
|
||||||
|
# push to aws
|
||||||
|
eb deploy
|
||||||
|
|
||||||
|
# switch back to $2 branch
|
||||||
|
git checkout $2
|
73
res/cca_build.sh
Executable file
@ -0,0 +1,73 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# reads values from JSON
|
||||||
|
jsonValue() {
|
||||||
|
KEY=$1
|
||||||
|
num=$2
|
||||||
|
awk -F"[,:}]" '{for(i=1;i<=NF;i++){if($i~/'$KEY'\042/){print $(i+1)}}}' | tr -d '"' | sed -n ${num}p
|
||||||
|
}
|
||||||
|
|
||||||
|
# go to root
|
||||||
|
cd `dirname $0`
|
||||||
|
cd ..
|
||||||
|
|
||||||
|
DIR=release/cca
|
||||||
|
PROJNAME=`less dist/manifest.json | jsonValue name 1 | sed -e 's/^ *//' -e 's/ *$//'`
|
||||||
|
|
||||||
|
# create
|
||||||
|
rm -rf $DIR
|
||||||
|
mkdir -p $DIR
|
||||||
|
cca create $DIR/Whiteout --link-to=dist/manifest.json
|
||||||
|
|
||||||
|
#prepare
|
||||||
|
cd $DIR/Whiteout
|
||||||
|
cca prepare
|
||||||
|
|
||||||
|
#
|
||||||
|
# post-build tweaks
|
||||||
|
#
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "## Running post-build tweaks"
|
||||||
|
|
||||||
|
# cp signing config
|
||||||
|
echo "Copy Android signing config"
|
||||||
|
cp ../../../res/android-release-keys.properties .
|
||||||
|
|
||||||
|
# status bar should not overlay the web view
|
||||||
|
echo "Tweaking iOS status bar to not overlay the web view"
|
||||||
|
sed -i "" 's/StatusBarOverlaysWebView" value="true"/StatusBarOverlaysWebView" value="false"/' "platforms/ios/$PROJNAME/config.xml"
|
||||||
|
|
||||||
|
# status bar should use dark font on light background
|
||||||
|
echo "Tweaking iOS status bar to use dark font on light background"
|
||||||
|
sed -i "" 's/StatusBarStyle" value="lightcontent"/StatusBarStyle" value="darkcontent"/' "platforms/ios/$PROJNAME/config.xml"
|
||||||
|
|
||||||
|
# copy splash screens
|
||||||
|
echo "Copying splash screens"
|
||||||
|
cp ../../../src/img/Default* "platforms/ios/$PROJNAME/Resources/splash"
|
||||||
|
|
||||||
|
# fixing missing/wrong icons
|
||||||
|
echo "Fixing wrong/missing iOS icons"
|
||||||
|
cp ../../../src/img/icon-40-ios.png "platforms/ios/$PROJNAME/Resources/icons/icon-40.png"
|
||||||
|
cp ../../../src/img/icon-80-ios.png "platforms/ios/$PROJNAME/Resources/icons/icon-40@2x.png"
|
||||||
|
cp ../../../src/img/icon-120-ios.png "platforms/ios/$PROJNAME/Resources/icons/icon-40@3x.png"
|
||||||
|
cp ../../../src/img/icon-50-ios.png "platforms/ios/$PROJNAME/Resources/icons/icon-50.png"
|
||||||
|
cp ../../../src/img/icon-100-ios.png "platforms/ios/$PROJNAME/Resources/icons/icon-50@2x.png"
|
||||||
|
cp ../../../src/img/icon-60-ios.png "platforms/ios/$PROJNAME/Resources/icons/icon-60.png"
|
||||||
|
cp ../../../src/img/icon-120-ios.png "platforms/ios/$PROJNAME/Resources/icons/icon-60@2x.png"
|
||||||
|
cp ../../../src/img/icon-180-ios.png "platforms/ios/$PROJNAME/Resources/icons/icon-60@3x.png"
|
||||||
|
cp ../../../src/img/icon-72-ios.png "platforms/ios/$PROJNAME/Resources/icons/icon-72.png"
|
||||||
|
cp ../../../src/img/icon-144-ios.png "platforms/ios/$PROJNAME/Resources/icons/icon-72@2x.png"
|
||||||
|
cp ../../../src/img/icon-76-ios.png "platforms/ios/$PROJNAME/Resources/icons/icon-76.png"
|
||||||
|
cp ../../../src/img/icon-152-ios.png "platforms/ios/$PROJNAME/Resources/icons/icon-76@2x.png"
|
||||||
|
cp ../../../src/img/icon-29-ios.png "platforms/ios/$PROJNAME/Resources/icons/icon-small.png"
|
||||||
|
cp ../../../src/img/icon-58-ios.png "platforms/ios/$PROJNAME/Resources/icons/icon-small@2x.png"
|
||||||
|
cp ../../../src/img/icon-87-ios.png "platforms/ios/$PROJNAME/Resources/icons/icon-small@3x.png"
|
||||||
|
cp ../../../src/img/icon-57-ios.png "platforms/ios/$PROJNAME/Resources/icons/icon.png"
|
||||||
|
cp ../../../src/img/icon-114-ios.png "platforms/ios/$PROJNAME/Resources/icons/icon@2x.png"
|
||||||
|
|
||||||
|
# print reminder for manual work in xcode
|
||||||
|
echo ""
|
||||||
|
echo "### Reminder for manual steps required for iOS release"
|
||||||
|
echo "### Change deployment target to iOS 8.1"
|
||||||
|
echo "### Add retina icons to build, migrate to icon set, fix splash screens config"
|
11
res/cca_release_android.sh
Executable file
@ -0,0 +1,11 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# go to root
|
||||||
|
cd `dirname $0`
|
||||||
|
cd ..
|
||||||
|
|
||||||
|
DIR=release/cca
|
||||||
|
|
||||||
|
#prepare
|
||||||
|
cd $DIR/Whiteout
|
||||||
|
cca build android --release
|
8
res/cca_run_android.sh
Executable file
@ -0,0 +1,8 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# go to root
|
||||||
|
cd `dirname $0`
|
||||||
|
cd ..
|
||||||
|
|
||||||
|
cd release/cca/Whiteout
|
||||||
|
cca run android --device
|
8
res/cca_run_ios.sh
Executable file
@ -0,0 +1,8 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# go to root
|
||||||
|
cd `dirname $0`
|
||||||
|
cd ..
|
||||||
|
|
||||||
|
cd release/cca/Whiteout
|
||||||
|
cca run ios
|
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.4 KiB |