diff --git a/README.md b/README.md index 34e6dcef..ac01d549 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ ## What it does -A P2P file sharing experiment which allows you to send encrypted files to other users. +A file sharing experiment which allows you to send encrypted files to other users. ## Requirements @@ -48,20 +48,3 @@ Pull requests are always welcome! Feel free to check out the list of ["good firs ## License [Mozilla Public License Version 2.0](LICENSE) - - **Entypo** - - Copyright (C) 2012 by Daniel Bruce - - Author: Daniel Bruce - License: SIL (http://scripts.sil.org/OFL) - Homepage: http://www.entypo.com - - - **Font Awesome** - - Copyright (C) 2016 by Dave Gandy - - Author: Dave Gandy - License: SIL () - Homepage: http://fortawesome.github.com/Font-Awesome/ diff --git a/docs/faq.md b/docs/faq.md new file mode 100644 index 00000000..ed15323f --- /dev/null +++ b/docs/faq.md @@ -0,0 +1,32 @@ +## How big of a file can I transfer with Firefox Send? + +There is a 2GB file size limit built in to Send, however, in practice you may +be unable to send files that large. Send encrypts and decrypts the files in +the browser which is great for security but will tax your system resources. In +particular you can expect to see your memory usage go up by at least the size +of the file when the transfer is processing. You can see [the results of some +testing](https://github.com/mozilla/send/issues/170#issuecomment-314107793). +For the most reliable operation on common computers, it’s probably best to stay +under a few hundred megabytes. + +## Why is my browser not supported? + +We’re using the [Web Cryptography JavaScript API with the AES-GCM +algorithm](https://www.w3.org/TR/WebCryptoAPI/#aes-gcm) for our encryption. +Many browsers support this standard and should work fine, but some have not +implemented it yet (mobile browsers lag behind on this, in +particular). + +## How long are files available for? + +Files are available to be downloaded for 24 hours, after which they are removed +from the server. They are also removed immediately after a download completes. + +## Can a file be downloaded more than once? + +Not currently, but we're considering multiple download support in a future +release. + + +*Disclaimer: Send is an experiment and under active development. The answers +here may change as we get feedback from you and the project matures.* diff --git a/frontend/src/download.js b/frontend/src/download.js index 1fe6f7d5..8e211fc8 100644 --- a/frontend/src/download.js +++ b/frontend/src/download.js @@ -6,9 +6,9 @@ require('jquery-circle-progress'); const Raven = window.Raven; $(document).ready(function() { $('#download-progress').hide(); - $('.send-new').click(() => { - window.location.replace(`${window.location.origin}`); - }); + //link back to homepage + $('.send-new').attr('href', window.location.origin); + const filename = $('#dl-filename').html(); //initiate progress bar @@ -21,7 +21,6 @@ $(document).ready(function() { $('#download-btn').click(download); function download() { const fileReceiver = new FileReceiver(); - const name = document.createElement('p'); fileReceiver.on('progress', progress => { $('#download-page-one').hide(); @@ -86,7 +85,6 @@ $(document).ready(function() { return; }) .then(([decrypted, fname]) => { - name.innerText = fname; const dataView = new DataView(decrypted); const blob = new Blob([dataView]); const downloadUrl = URL.createObjectURL(blob); diff --git a/frontend/src/fileSender.js b/frontend/src/fileSender.js index 44240625..a16b1849 100644 --- a/frontend/src/fileSender.js +++ b/frontend/src/fileSender.js @@ -8,6 +8,7 @@ class FileSender extends EventEmitter { super(); this.file = file; this.iv = window.crypto.getRandomValues(new Uint8Array(12)); + this.uploadXHR = new XMLHttpRequest(); } static delete(fileId, token) { @@ -35,6 +36,10 @@ class FileSender extends EventEmitter { }); } + cancel() { + this.uploadXHR.abort(); + } + upload() { const self = this; self.emit('loading', true); @@ -103,7 +108,7 @@ class FileSender extends EventEmitter { const fd = new FormData(); fd.append('data', blob, file.name); - const xhr = new XMLHttpRequest(); + const xhr = self.uploadXHR; xhr.upload.addEventListener('progress', e => { if (e.lengthComputable) { diff --git a/frontend/src/upload.js b/frontend/src/upload.js index beea5f62..ea29668e 100644 --- a/frontend/src/upload.js +++ b/frontend/src/upload.js @@ -47,7 +47,7 @@ $(document).ready(function() { //disable button for 3s $copyBtn.attr('disabled', true); $('#link').attr('disabled', true); - $copyBtn.html(''); + $copyBtn.html(''); window.setTimeout(() => { $copyBtn.attr('disabled', false); $('#link').attr('disabled', false); @@ -68,19 +68,10 @@ $(document).ready(function() { fill: '#3B9DFF', size: 158 }); - // link back to home page - $('.send-new').click(() => { - $('#upload-progress').hide(); - $('#share-link').hide(); - $('#upload-error').hide(); - $copyBtn.attr('disabled', false); - $('#link').attr('disabled', false); - $copyBtn.attr('data-l10n-id', 'copyUrlFormButton'); - $('.upload-window').removeClass('ondrag'); - $('#page-one').show(); - }); - //cancel the upload - $('#cancel-upload').click(() => {}); + + //link back to homepage + $('.send-new').attr('href', window.location); + // on file upload by browse or drag & drop function onUpload(event) { event.preventDefault(); @@ -93,6 +84,12 @@ $(document).ready(function() { const expiration = 24 * 60 * 60 * 1000; //will eventually come from a field const fileSender = new FileSender(file); + $('#cancel-upload').click(() => { + fileSender.cancel(); + location.reload(); + notify('Your upload was cancelled.'); + }); + fileSender.on('progress', progress => { $('#page-one').hide(); $('#upload-error').hide(); @@ -104,19 +101,19 @@ $(document).ready(function() { $('.percent-number').html(`${Math.floor(percent * 100)}`); }); if (progress[1] < 1000000) { - $('.progress-text').html( + $('.progress-text').text( `${file.name} (${(progress[0] / 1000).toFixed( 1 )}KB of ${(progress[1] / 1000).toFixed(1)}KB)` ); } else if (progress[1] < 1000000000) { - $('.progress-text').html( + $('.progress-text').text( `${file.name} (${(progress[0] / 1000000).toFixed( 1 )}MB of ${(progress[1] / 1000000).toFixed(1)}MB)` ); } else { - $('.progress-text').html( + $('.progress-text').text( `${file.name} (${(progress[0] / 1000000).toFixed( 1 )}MB of ${(progress[1] / 1000000000).toFixed(1)}GB)` @@ -219,13 +216,16 @@ $(document).ready(function() { const row = document.createElement('tr'); const name = document.createElement('td'); const link = document.createElement('td'); + const $copyIcon = $('', { src: '/resources/copy-16.svg', class: 'icon-copy', title: 'Copy URL' }); const expiry = document.createElement('td'); const del = document.createElement('td'); + const $delIcon = $('', { src: '/resources/close-16.svg', class: 'icon-delete', title: 'Delete' }); const popupDiv = document.createElement('div'); const $popupText = $('
', { class: 'popuptext' }); const cellText = document.createTextNode(file.name); const url = file.url.trim() + `#${file.secretKey}`.trim(); + $('#link').attr('value', url); $('#copy-text').attr( 'data-l10n-args', @@ -252,8 +252,9 @@ $(document).ready(function() { link.appendChild(linkSpan); link.style.color = '#0A8DFF'; + //copy link to clipboard when icon clicked - $(link).click(function() { + $copyIcon.click(function() { const aux = document.createElement('input'); aux.setAttribute('value', url); document.body.appendChild(aux); @@ -265,10 +266,11 @@ $(document).ready(function() { link.innerHTML = translated; }) window.setTimeout(() => { - const linkSpan = document.createElement('span'); - $(linkSpan).addClass('icon-docs'); - $(linkSpan).attr('data-l10n-id', 'copyUrlHover'); - $(link).html(linkSpan); + const linkImg = document.createElement('img'); + $(linkImg).addClass('icon-copy'); + $(linkImg).attr('data-l10n-id', 'copyUrlHover'); + $(linkImg).attr('src', '/resources/copy-16.svg'); + $(link).html(linkImg); }, 500); }); @@ -325,9 +327,22 @@ $(document).ready(function() { $popupText.html([ popupDelSpan, ' ', + ' ', popupNvmSpan ]); + + // add data cells to table row + row.appendChild(name); + $(link).append($copyIcon); + row.appendChild(link); + row.appendChild(expiry); + $(popupDiv).append($popupText); + $(del).append($delIcon); + del.appendChild(popupDiv); + row.appendChild(del); + $('tbody').append(row); //add row to table + // delete file $popupText.find('.del-file').click(e => { FileSender.delete(file.fileId, file.deleteToken).then(() => { @@ -342,17 +357,8 @@ $(document).ready(function() { location.reload(); }); }; - - // add data cells to table row - row.appendChild(name); - row.appendChild(link); - row.appendChild(expiry); - $(popupDiv).append($popupText); - del.appendChild(popupDiv); - row.appendChild(del); - // show popup - del.addEventListener('click', function() { + $delIcon.click(function() { $popupText.addClass('show'); $popupText.focus(); }); @@ -368,7 +374,7 @@ $(document).ready(function() { $popupText.blur(() => { $popupText.removeClass('show'); }); - $('tbody').append(row); //add row to table + toggleHeader(); } diff --git a/public/contribute.json b/public/contribute.json index b7b1ab26..db85d7a2 100644 --- a/public/contribute.json +++ b/public/contribute.json @@ -22,7 +22,6 @@ "JavaScript", "jQuery", "Node", - "P2P", "Redis" ] } diff --git a/public/main.css b/public/main.css index 02a1f69a..129342d9 100644 --- a/public/main.css +++ b/public/main.css @@ -24,7 +24,7 @@ body { .all { padding-top: 10%; - overflow-y: scroll; + padding-bottom: 51px; } input, select, textarea, button { @@ -35,10 +35,6 @@ a { text-decoration: none; } -span { - cursor: pointer; -} - /** page-one **/ .title { font-size: 33px; @@ -72,8 +68,9 @@ span { .upload-window.ondrag { border: 3px dashed rgba(0, 148, 251, 0.5); margin: 0 auto; - width: 672px; - height: 267px; + width: 636px; + height: 251px; + transform: scale(1.05); border-radius: 4.2px; display: flex; justify-content: center; @@ -146,6 +143,10 @@ tbody { table-layout: fixed; } +.icon-delete, .icon-copy, .icon-check { + cursor: pointer; +} + /* Popup container */ .popup { position: relative; @@ -166,7 +167,7 @@ tbody { z-index: 1; bottom: 20px; left: 50%; - margin-left: -96px; + margin-left: -88px; transition: opacity 0.5s; opacity: 0; outline: 0; diff --git a/public/resources/check-16.svg b/public/resources/check-16.svg new file mode 100644 index 00000000..4243e0dc --- /dev/null +++ b/public/resources/check-16.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/resources/close-16.svg b/public/resources/close-16.svg new file mode 100644 index 00000000..8f143c5b --- /dev/null +++ b/public/resources/close-16.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/resources/copy-16.svg b/public/resources/copy-16.svg new file mode 100644 index 00000000..c5cee826 --- /dev/null +++ b/public/resources/copy-16.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/resources/firefox_logo-only.svg b/public/resources/firefox_logo-only.svg index 6c9d5ce3..4f3cbbb5 100644 --- a/public/resources/firefox_logo-only.svg +++ b/public/resources/firefox_logo-only.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/public/resources/fontello-24c5e6ad/config.json b/public/resources/fontello-24c5e6ad/config.json deleted file mode 100755 index 3a91a711..00000000 --- a/public/resources/fontello-24c5e6ad/config.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "name": "", - "css_prefix_text": "icon-", - "css_use_suffix": false, - "hinting": true, - "units_per_em": 1000, - "ascent": 850, - "glyphs": [ - { - "uid": "c8585e1e5b0467f28b70bce765d5840c", - "css": "docs", - "code": 61637, - "src": "fontawesome" - }, - { - "uid": "c709da589c923ba3c2ad48d9fc563e93", - "css": "cancel-1", - "code": 59393, - "src": "entypo" - }, - { - "uid": "14017aae737730faeda4a6fd8fb3a5f0", - "css": "check", - "code": 59394, - "src": "entypo" - } - ] -} \ No newline at end of file diff --git a/public/resources/fontello-24c5e6ad/css/fontello.css b/public/resources/fontello-24c5e6ad/css/fontello.css deleted file mode 100755 index ea18ff91..00000000 --- a/public/resources/fontello-24c5e6ad/css/fontello.css +++ /dev/null @@ -1,60 +0,0 @@ -@font-face { - font-family: 'fontello'; - src: url('../font/fontello.eot?60405031'); - src: url('../font/fontello.eot?60405031#iefix') format('embedded-opentype'), - url('../font/fontello.woff2?60405031') format('woff2'), - url('../font/fontello.woff?60405031') format('woff'), - url('../font/fontello.ttf?60405031') format('truetype'), - url('../font/fontello.svg?60405031#fontello') format('svg'); - font-weight: normal; - font-style: normal; -} -/* Chrome hack: SVG is rendered more smooth in Windozze. 100% magic, uncomment if you need it. */ -/* Note, that will break hinting! In other OS-es font will be not as sharp as it could be */ -/* -@media screen and (-webkit-min-device-pixel-ratio:0) { - @font-face { - font-family: 'fontello'; - src: url('../font/fontello.svg?60405031#fontello') format('svg'); - } -} -*/ - - [class^="icon-"]:before, [class*=" icon-"]:before { - font-family: "fontello"; - font-style: normal; - font-weight: normal; - speak: none; - - display: inline-block; - text-decoration: inherit; - width: 1em; - margin-right: .2em; - text-align: center; - /* opacity: .8; */ - - /* For safety - reset parent styles, that can break glyph codes*/ - font-variant: normal; - text-transform: none; - - /* fix buttons height, for twitter bootstrap */ - line-height: 1em; - - /* Animation center compensation - margins should be symmetric */ - /* remove if not needed */ - margin-left: .2em; - - /* you can be more comfortable with increased icons size */ - /* font-size: 120%; */ - - /* Font smoothing. That was taken from TWBS */ - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - - /* Uncomment for 3D effect */ - /* text-shadow: 1px 1px 1px rgba(127, 127, 127, 0.3); */ -} - -.icon-cancel-1:before { content: '\e801'; font-size: 1.5em; font-weight: lighter;} /* '' */ -.icon-check:before { content: '\e802'; font-size: 1.5em;} /* '' */ -.icon-docs:before { content: '\f0c5'; font-weight: bolder;} /* '' */ diff --git a/public/resources/fontello-24c5e6ad/font/fontello.eot b/public/resources/fontello-24c5e6ad/font/fontello.eot deleted file mode 100755 index 30b0ddc1..00000000 Binary files a/public/resources/fontello-24c5e6ad/font/fontello.eot and /dev/null differ diff --git a/public/resources/fontello-24c5e6ad/font/fontello.svg b/public/resources/fontello-24c5e6ad/font/fontello.svg deleted file mode 100755 index 431b9d7c..00000000 --- a/public/resources/fontello-24c5e6ad/font/fontello.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - -Copyright (C) 2017 by original authors @ fontello.com - - - - - - - - - - - - \ No newline at end of file diff --git a/public/resources/fontello-24c5e6ad/font/fontello.ttf b/public/resources/fontello-24c5e6ad/font/fontello.ttf deleted file mode 100755 index 86b99e44..00000000 Binary files a/public/resources/fontello-24c5e6ad/font/fontello.ttf and /dev/null differ diff --git a/public/resources/fontello-24c5e6ad/font/fontello.woff b/public/resources/fontello-24c5e6ad/font/fontello.woff deleted file mode 100755 index 25766584..00000000 Binary files a/public/resources/fontello-24c5e6ad/font/fontello.woff and /dev/null differ diff --git a/public/resources/fontello-24c5e6ad/font/fontello.woff2 b/public/resources/fontello-24c5e6ad/font/fontello.woff2 deleted file mode 100755 index ca749888..00000000 Binary files a/public/resources/fontello-24c5e6ad/font/fontello.woff2 and /dev/null differ diff --git a/public/resources/github-icon.svg b/public/resources/github-icon.svg index 977cf9d7..44e074c8 100644 --- a/public/resources/github-icon.svg +++ b/public/resources/github-icon.svg @@ -1,59 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/public/resources/illustration_download.svg b/public/resources/illustration_download.svg index 85e8c5b9..9425fc28 100644 --- a/public/resources/illustration_download.svg +++ b/public/resources/illustration_download.svg @@ -1,126 +1 @@ - - - - -illustration_01 -Created with Sketch. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Untitled \ No newline at end of file diff --git a/public/resources/illustration_error.svg b/public/resources/illustration_error.svg index ca44824d..cba8d2e0 100644 --- a/public/resources/illustration_error.svg +++ b/public/resources/illustration_error.svg @@ -1,93 +1 @@ - - - - illustration - Created with Sketch. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file +illustration \ No newline at end of file diff --git a/public/resources/illustration_expired.svg b/public/resources/illustration_expired.svg index 9c551a28..1d569f08 100644 --- a/public/resources/illustration_expired.svg +++ b/public/resources/illustration_expired.svg @@ -1,64 +1 @@ - - - - Group - Created with Sketch. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file +Group \ No newline at end of file diff --git a/public/resources/mozilla-logo.svg b/public/resources/mozilla-logo.svg index 13e0a1c3..3ea2e868 100644 --- a/public/resources/mozilla-logo.svg +++ b/public/resources/mozilla-logo.svg @@ -1,5 +1 @@ - - - - - + \ No newline at end of file diff --git a/public/resources/send_bg.svg b/public/resources/send_bg.svg index f92ac6d5..8a2a63bb 100644 --- a/public/resources/send_bg.svg +++ b/public/resources/send_bg.svg @@ -1,107 +1 @@ - - - - Untitled - Created with Sketch. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - { } - - - - - - - - - - \ No newline at end of file +Untitled{ } \ No newline at end of file diff --git a/public/resources/send_logo.svg b/public/resources/send_logo.svg index af6c16f5..e370560d 100644 --- a/public/resources/send_logo.svg +++ b/public/resources/send_logo.svg @@ -1,21 +1 @@ - - - - send logo - Created with Sketch. - - - +send logo \ No newline at end of file diff --git a/public/resources/send_logo_type.svg b/public/resources/send_logo_type.svg index fc8f9ada..07091885 100644 --- a/public/resources/send_logo_type.svg +++ b/public/resources/send_logo_type.svg @@ -1,14 +1 @@ - - - - Send - Created with Sketch. - - - +logo design_01 copy \ No newline at end of file diff --git a/public/resources/twitter-icon.svg b/public/resources/twitter-icon.svg index 0b61e76e..8816009a 100644 --- a/public/resources/twitter-icon.svg +++ b/public/resources/twitter-icon.svg @@ -1,46 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/public/resources/upload.svg b/public/resources/upload.svg index e9bb7fc2..f98e6b2e 100644 --- a/public/resources/upload.svg +++ b/public/resources/upload.svg @@ -1,24 +1 @@ - - - - upload - Created with Sketch. - - - - - - - - - - - - - - - - - - - \ No newline at end of file +upload \ No newline at end of file diff --git a/server/server.js b/server/server.js index b26cde12..e599e681 100644 --- a/server/server.js +++ b/server/server.js @@ -224,6 +224,19 @@ app.post('/upload', (req, res, next) => { }); }); }); + + req.on('close', err => { + storage + .forceDelete(newId) + .then(err => { + if (!err) { + log.info('Deleted:', newId); + } + }) + .catch(err => { + log.info('DeleteError:', newId); + }); + }) }); app.get('/__lbheartbeat__', (req, res) => { diff --git a/server/storage.js b/server/storage.js index 5d48b490..68375e47 100644 --- a/server/storage.js +++ b/server/storage.js @@ -234,13 +234,13 @@ function awsDelete(id, delete_token) { if (!reply || delete_token !== reply) { reject(); } else { - redis_client.del(id); const params = { Bucket: conf.s3_bucket, Key: id }; s3.deleteObject(params, function(err, _data) { + redis_client.del(id); err ? reject(err) : resolve(err); }); } @@ -250,13 +250,13 @@ function awsDelete(id, delete_token) { function awsForceDelete(id) { return new Promise((resolve, reject) => { - redis_client.del(id); const params = { Bucket: conf.s3_bucket, Key: id }; s3.deleteObject(params, function(err, _data) { + redis_client.del(id); err ? reject(err) : resolve(err); }); }); diff --git a/views/download.handlebars b/views/download.handlebars index 15bd5f2d..f6eb8cf1 100644 --- a/views/download.handlebars +++ b/views/download.handlebars @@ -1,52 +1,46 @@ - -
-
- {{#if filename}} -
-
- - -
-
- -
- -
+
+ {{#if filename}} +
+
+ +
- -
-
-
-
- -
-
- - % -
-
-
-
{{filename}}
-
+
+ +
+
- -
- {{else}} -
- - -
-
- {{/if}}
+ +
+
+
+
+ +
+
+ + % +
+
+
+
{{filename}}
+
+
+ + + {{else}} +
+ + +
+ + {{/if}}
diff --git a/views/index.handlebars b/views/index.handlebars index 66e2fc91..3c18e9d9 100644 --- a/views/index.handlebars +++ b/views/index.handlebars @@ -1,93 +1,84 @@ - -
-
-
-
-
- -
-
-
-
+
+
+
+
+ +
+
+
+
-
- - -
-
- -
- - - - - - - - - - - - - - -
-
+
+ + +
-
-
-
- -
- -
-
- 0 - % -
-
-
-
-
-
-
- - - -
-
-
- -
-
- -
-
-
- - -
Firefox
- -
-
-
+
+ + + + + + + + + + + + + +
+ +
+
+
+ +
+
+ 0 + % +
+
+
+
+
+
+ +
+ + + +
+
+
+ + +
+ + diff --git a/views/layouts/main.handlebars b/views/layouts/main.handlebars index e410de68..c3826ccb 100644 --- a/views/layouts/main.handlebars +++ b/views/layouts/main.handlebars @@ -7,7 +7,6 @@ {{/if}} - {{#if trackerId}} {{> analytics trackerId=trackerId}} @@ -19,7 +18,13 @@ - {{{body}}} + +
+ {{{body}}} +