From 1dbda38995f7a5ddc925d0f9102e6082e9dd2248 Mon Sep 17 00:00:00 2001 From: Peter deHaan Date: Fri, 9 Jun 2017 10:44:12 -0700 Subject: [PATCH] Fix ESLint errors --- .eslintignore | 1 + .eslintrc.yml | 2 +- frontend/src/download.js | 20 ++++---- frontend/src/fileReceiver.js | 18 +++---- frontend/src/fileSender.js | 92 ++++++++++++++++++------------------ frontend/src/upload.js | 34 ++++++------- frontend/src/utils.js | 4 +- public/main.css | 64 ++++++++++++------------- server/config.js | 4 +- server/log.js | 8 ++-- server/portal_server.js | 26 +++++----- server/storage.js | 34 ++++++------- 12 files changed, 151 insertions(+), 156 deletions(-) diff --git a/.eslintignore b/.eslintignore index 7f3dd623..1365f08d 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1 +1,2 @@ public/bundle.js +public/webcrypto-shim.js diff --git a/.eslintrc.yml b/.eslintrc.yml index f0bf0bd3..16f7f635 100644 --- a/.eslintrc.yml +++ b/.eslintrc.yml @@ -31,7 +31,7 @@ rules: eqeqeq: error no-console: warn no-path-concat: error - no-unused-vars: [error, {argsIgnorePattern: "^_|next"}] + no-unused-vars: [error, {argsIgnorePattern: "^_|err|event|next|reject"}] no-var: error one-var: [error, never] prefer-const: error diff --git a/frontend/src/download.js b/frontend/src/download.js index 1048647c..5ad2fb3e 100644 --- a/frontend/src/download.js +++ b/frontend/src/download.js @@ -5,13 +5,11 @@ $(document).ready(function() { $('#send-file').click(() => { window.location.replace(`${window.location.origin}`); }); - let download = () => { + const download = () => { const fileReceiver = new FileReceiver(); - - let li = document.createElement('li'); - let name = document.createElement('p'); - let progress = document.createElement('p'); - let btn = $('#download-btn'); + const name = document.createElement('p'); + const progress = document.createElement('p'); + const btn = $('#download-btn'); fileReceiver.on('progress', percentComplete => { progress.innerText = `Progress: ${percentComplete}%`; @@ -25,7 +23,7 @@ $(document).ready(function() { fileReceiver .download() - .catch(err => { + .catch(() => { $('.title').text( 'This link has expired or never existed in the first place.' ); @@ -36,11 +34,11 @@ $(document).ready(function() { }) .then(([decrypted, fname]) => { name.innerText = fname; - let dataView = new DataView(decrypted); - let blob = new Blob([dataView]); - let downloadUrl = URL.createObjectURL(blob); + const dataView = new DataView(decrypted); + const blob = new Blob([dataView]); + const downloadUrl = URL.createObjectURL(blob); - let a = document.createElement('a'); + const a = document.createElement('a'); a.href = downloadUrl; if (window.navigator.msSaveBlob) { // if we are in microsoft edge or IE diff --git a/frontend/src/fileReceiver.js b/frontend/src/fileReceiver.js index a1a50457..79e25f67 100644 --- a/frontend/src/fileReceiver.js +++ b/frontend/src/fileReceiver.js @@ -10,16 +10,18 @@ class FileReceiver extends EventEmitter { download() { return Promise.all([ new Promise((resolve, reject) => { - let xhr = new XMLHttpRequest(); + const xhr = new XMLHttpRequest(); - xhr.onprogress = e => { - if (e.lengthComputable) { - let percentComplete = Math.floor(e.loaded / e.total * 100); + xhr.onprogress = event => { + if (event.lengthComputable) { + const percentComplete = Math.floor( + event.loaded / event.total * 100 + ); this.emit('progress', percentComplete); } }; - xhr.onload = function(e) { + xhr.onload = event => { if (xhr.status === 404) { reject( new Error('The file has expired, or has already been deleted.') @@ -27,8 +29,8 @@ class FileReceiver extends EventEmitter { return; } - let blob = new Blob([this.response]); - let fileReader = new FileReader(); + const blob = new Blob([this.response]); + const fileReader = new FileReader(); fileReader.onload = function() { resolve({ data: this.result, @@ -60,7 +62,7 @@ class FileReceiver extends EventEmitter { ['encrypt', 'decrypt'] ) ]).then(([fdata, key]) => { - let salt = this.salt; + const salt = this.salt; return Promise.all([ window.crypto.subtle.decrypt( { diff --git a/frontend/src/fileSender.js b/frontend/src/fileSender.js index 5b50b0da..8a70c2f9 100644 --- a/frontend/src/fileSender.js +++ b/frontend/src/fileSender.js @@ -13,7 +13,7 @@ class FileSender extends EventEmitter { if (!fileId || !token) { return reject(); } - let xhr = new XMLHttpRequest(); + const xhr = new XMLHttpRequest(); xhr.open('post', '/delete/' + fileId, true); xhr.setRequestHeader('Content-Type', 'application/json'); @@ -51,55 +51,55 @@ class FileSender extends EventEmitter { }; }) ]) - .then(([secretKey, plaintext]) => { - return Promise.all([ - window.crypto.subtle.encrypt( - { - name: 'AES-CBC', - iv: this.iv - }, - secretKey, - plaintext - ), - window.crypto.subtle.exportKey('jwk', secretKey) - ]); - }) - .then(([encrypted, keydata]) => { - return new Promise((resolve, reject) => { - let file = this.file; - let fileId = ivToStr(this.iv); - let dataView = new DataView(encrypted); - let blob = new Blob([dataView], { type: file.type }); - let fd = new FormData(); - fd.append('fname', file.name); - fd.append('data', blob, file.name); + .then(([secretKey, plaintext]) => { + return Promise.all([ + window.crypto.subtle.encrypt( + { + name: 'AES-CBC', + iv: this.iv + }, + secretKey, + plaintext + ), + window.crypto.subtle.exportKey('jwk', secretKey) + ]); + }) + .then(([encrypted, keydata]) => { + return new Promise((resolve, reject) => { + const file = this.file; + const fileId = ivToStr(this.iv); + const dataView = new DataView(encrypted); + const blob = new Blob([dataView], { type: file.type }); + const fd = new FormData(); + fd.append('fname', file.name); + fd.append('data', blob, file.name); - let xhr = new XMLHttpRequest(); + const xhr = new XMLHttpRequest(); - xhr.upload.addEventListener('progress', e => { - if (e.lengthComputable) { - let percentComplete = Math.floor(e.loaded / e.total * 100); - this.emit('progress', percentComplete); - } + xhr.upload.addEventListener('progress', e => { + if (e.lengthComputable) { + const percentComplete = Math.floor(e.loaded / e.total * 100); + this.emit('progress', percentComplete); + } + }); + + xhr.onreadystatechange = () => { + if (xhr.readyState === XMLHttpRequest.DONE) { + // uuid field and url field + const responseObj = JSON.parse(xhr.responseText); + resolve({ + url: responseObj.url, + fileId: fileId, + secretKey: keydata.k, + deleteToken: responseObj.uuid + }); + } + }; + + xhr.open('post', '/upload/' + fileId, true); + xhr.send(fd); }); - - xhr.onreadystatechange = () => { - if (xhr.readyState == XMLHttpRequest.DONE) { - // uuid field and url field - let responseObj = JSON.parse(xhr.responseText); - resolve({ - url: responseObj.url, - fileId: fileId, - secretKey: keydata.k, - deleteToken: responseObj.uuid - }); - } - }; - - xhr.open('post', '/upload/' + fileId, true); - xhr.send(fd); }); - }); } } diff --git a/frontend/src/upload.js b/frontend/src/upload.js index 72c02f36..17d4a3b8 100644 --- a/frontend/src/upload.js +++ b/frontend/src/upload.js @@ -3,7 +3,7 @@ const $ = require('jquery'); $(document).ready(function() { // reset copy button - let copyBtn = $('#copy-btn'); + const copyBtn = $('#copy-btn'); copyBtn.attr('disabled', false); copyBtn.html('Copy'); @@ -14,7 +14,7 @@ $(document).ready(function() { // copy link to clipboard copyBtn.click(() => { - var aux = document.createElement('input'); + const aux = document.createElement('input'); aux.setAttribute('value', $('#link').attr('value')); document.body.appendChild(aux); aux.select(); @@ -38,22 +38,22 @@ $(document).ready(function() { window.onUpload = event => { event.preventDefault(); let file = ''; - if (event.type == 'drop') { + if (event.type === 'drop') { file = event.dataTransfer.files[0]; } else { file = event.target.files[0]; } - let $fileList = $('#uploaded-files'); - let row = document.createElement('tr'); - let name = document.createElement('td'); - let link = document.createElement('td'); - let expiry = document.createElement('td'); - let del = document.createElement('td'); - let btn = document.createElement('button'); - let popupDiv = document.createElement('div'); - let $popupText = $('', { 'class': 'popuptext' }); - let cellText = document.createTextNode(file.name); - let progress = document.createElement('p'); + const $fileList = $('#uploaded-files'); + const row = document.createElement('tr'); + const name = document.createElement('td'); + const link = document.createElement('td'); + const expiry = document.createElement('td'); + const del = document.createElement('td'); + const btn = document.createElement('button'); + const popupDiv = document.createElement('div'); + const $popupText = $('', { class: 'popuptext' }); + const cellText = document.createTextNode(file.name); + const progress = document.createElement('p'); name.appendChild(cellText); @@ -64,7 +64,7 @@ $(document).ready(function() { // create popup popupDiv.classList.add('popup'); $popupText.html( - "Delete Nevermind" + 'Delete Nevermind' ); // add data cells to table row @@ -96,7 +96,7 @@ $(document).ready(function() { FileSender.delete( info.fileId, localStorage.getItem(info.fileId) - ).then(() => { + ).then(() => { // $(e.target).parents('tr').remove(); localStorage.removeItem(info.fileId); @@ -111,7 +111,7 @@ $(document).ready(function() { $('#share-link').show(); }); - function toggleShow(){ + function toggleShow() { $popupText.toggleClass('show'); } }; diff --git a/frontend/src/utils.js b/frontend/src/utils.js index 547211fe..a95026f8 100644 --- a/frontend/src/utils.js +++ b/frontend/src/utils.js @@ -1,6 +1,6 @@ function ivToStr(iv) { let hexStr = ''; - for (let i in iv) { + for (const i in iv) { if (iv[i] < 16) { hexStr += '0' + iv[i].toString(16); } else { @@ -12,7 +12,7 @@ function ivToStr(iv) { } function strToIv(str) { - let iv = new Uint8Array(16); + const iv = new Uint8Array(16); for (let i = 0; i < str.length; i += 2) { iv[i / 2] = parseInt(str.charAt(i) + str.charAt(i + 1), 16); } diff --git a/public/main.css b/public/main.css index 38fd83e3..96afd97e 100644 --- a/public/main.css +++ b/public/main.css @@ -13,7 +13,7 @@ html { flex-direction: column; } input, select, textarea, button { - font-family:inherit; + font-family: inherit; } /** page-one **/ @@ -59,7 +59,7 @@ input, select, textarea, button { padding-right: 20px; } -.upload-window>div:nth-child(2) { +.upload-window > div:nth-child(2) { font-size: 26px; } @@ -97,7 +97,7 @@ td { #uploaded-files { width: 472px; - margin: 10px auto ; + margin: 10px auto; table-layout: fixed; } @@ -110,50 +110,48 @@ td { /* Popup container */ .popup { - position: relative; - display: inline-block; - cursor: pointer; - + position: relative; + display: inline-block; + cursor: pointer; } /* The actual popup (appears on top) */ .popup .popuptext { - visibility: hidden; - width: 160px; - background-color: #555; - color: #fff; - text-align: center; - border-radius: 6px; - padding: 8px 0; - position: absolute; - z-index: 1; - bottom: 125%; - left: 50%; - margin-left: -80px; - transition: opacity 0.5s; - opacity: 0; + visibility: hidden; + width: 160px; + background-color: #555; + color: #fff; + text-align: center; + border-radius: 6px; + padding: 8px 0; + position: absolute; + z-index: 1; + bottom: 125%; + left: 50%; + margin-left: -80px; + transition: opacity 0.5s; + opacity: 0; } /* Popup arrow */ .popup .popuptext::after { - content: ""; - position: absolute; - top: 100%; - left: 50%; - margin-left: -5px; - border-width: 5px; - border-style: solid; - border-color: #555 transparent transparent transparent; + content: ""; + position: absolute; + top: 100%; + left: 50%; + margin-left: -5px; + border-width: 5px; + border-style: solid; + border-color: #555 transparent transparent transparent; } .popup .show { - visibility: visible; - opacity: 1; + visibility: visible; + opacity: 1; } /** upload-progress **/ - /** share-link **/ .share-window { width: 50%; @@ -174,7 +172,7 @@ td { flex-direction: column; } -#share-window-r>div { +#share-window-r > div { font-size: 12px; padding-bottom: 10px; } diff --git a/server/config.js b/server/config.js index be87cd85..74450e59 100644 --- a/server/config.js +++ b/server/config.js @@ -1,6 +1,6 @@ const convict = require('convict'); -let conf = convict({ +const conf = convict({ bitly_key: { format: String, default: 'localhost', @@ -32,7 +32,7 @@ let conf = convict({ // Perform validation conf.validate({ allowed: 'strict' }); -let props = conf.getProperties(); +const props = conf.getProperties(); module.exports = props; module.exports.notLocalHost = diff --git a/server/log.js b/server/log.js index e851239d..baebf52a 100644 --- a/server/log.js +++ b/server/log.js @@ -1,12 +1,12 @@ const conf = require('./config.js'); -let notLocalHost = conf.notLocalHost; +const notLocalHost = conf.notLocalHost; -const mozlog = require('mozlog') ({ +const mozlog = require('mozlog')({ app: 'FirefoxFileshare', level: notLocalHost ? 'INFO' : 'verbose', fmt: notLocalHost ? 'heka' : 'pretty', debug: !notLocalHost -}) +}); -module.exports = mozlog; \ No newline at end of file +module.exports = mozlog; diff --git a/server/portal_server.js b/server/portal_server.js index 5f8810ba..8173a6eb 100644 --- a/server/portal_server.js +++ b/server/portal_server.js @@ -2,20 +2,16 @@ const express = require('express'); const exphbs = require('express-handlebars'); const busboy = require('connect-busboy'); const path = require('path'); -const fs = require('fs-extra'); const bodyParser = require('body-parser'); -const crypto = require('crypto'); -const stream = require('stream'); -const fetch = require('node-fetch'); const bytes = require('bytes'); const conf = require('./config.js'); const storage = require('./storage.js'); -let notLocalHost = conf.notLocalHost; +const notLocalHost = conf.notLocalHost; const mozlog = require('./log.js'); -let log = mozlog('portal.server'); +const log = mozlog('portal.server'); const app = express(); @@ -32,14 +28,14 @@ app.get('/', (req, res) => { }); app.get('/exists/:id', (req, res) => { - let id = req.params.id; + const id = req.params.id; storage.exists(id).then(doesExist => { res.sendStatus(doesExist ? 200 : 404); }); }); app.get('/download/:id', (req, res) => { - let id = req.params.id; + const id = req.params.id; storage.filename(id).then(filename => { storage .length(id) @@ -56,7 +52,7 @@ app.get('/download/:id', (req, res) => { }); app.get('/assets/download/:id', (req, res) => { - let id = req.params.id; + const id = req.params.id; if (!validateID(id)) { res.sendStatus(404); return; @@ -71,7 +67,7 @@ app.get('/assets/download/:id', (req, res) => { 'Content-Type': 'application/octet-stream', 'Content-Length': contentLength }); - let file_stream = storage.get(id); + const file_stream = storage.get(id); file_stream.on(notLocalHost ? 'finish' : 'close', () => { storage.forceDelete(id).then(err => { @@ -90,14 +86,14 @@ app.get('/assets/download/:id', (req, res) => { }); app.post('/delete/:id', (req, res) => { - let id = req.params.id; + const id = req.params.id; if (!validateID(id)) { res.send(404); return; } - let delete_token = req.body.delete_token; + const delete_token = req.body.delete_token; if (!delete_token) { res.sendStatus(404); @@ -125,7 +121,7 @@ app.post('/upload/:id', (req, res, next) => { log.info('Uploading:', req.params.id); const protocol = notLocalHost ? 'https' : req.protocol; - let url = `${protocol}://${req.get('host')}/download/${req.params.id}/`; + const url = `${protocol}://${req.get('host')}/download/${req.params.id}/`; storage.set(req.params.id, file, filename, url).then(linkAndID => { res.json(linkAndID); @@ -133,10 +129,10 @@ app.post('/upload/:id', (req, res, next) => { }); }); -let server = app.listen(conf.listen_port, () => { +app.listen(conf.listen_port, () => { log.info('startServer:', `Portal app listening on port ${conf.listen_port}!`); }); -let validateID = route_id => { +const validateID = route_id => { return route_id.match(/^[0-9a-fA-F]{32}$/) !== null; }; diff --git a/server/storage.js b/server/storage.js index 4405482f..13f2d8a0 100644 --- a/server/storage.js +++ b/server/storage.js @@ -7,11 +7,11 @@ const path = require('path'); const fetch = require('node-fetch'); const crypto = require('crypto'); -let notLocalHost = conf.notLocalHost; +const notLocalHost = conf.notLocalHost; const mozlog = require('./log.js'); -let log = mozlog('portal.storage'); +const log = mozlog('portal.storage'); const redis = require('redis'); const redis_client = redis.createClient({ @@ -67,7 +67,7 @@ function exists(id) { function localLength(id) { return new Promise((resolve, reject) => { try { - resolve(fs.statSync(__dirname + '/../static/' + id).size); + resolve(fs.statSync(path.join(__dirname, '../static', id)).size); } catch (err) { reject(); } @@ -75,15 +75,15 @@ function localLength(id) { } function localGet(id) { - return fs.createReadStream(__dirname + '/../static/' + id); + return fs.createReadStream(path.join(__dirname, '../static', id)); } function localSet(id, file, filename, url) { return new Promise((resolve, reject) => { - fstream = fs.createWriteStream(__dirname + '/../static/' + id); + const fstream = fs.createWriteStream(path.join(__dirname, '../static', id)); file.pipe(fstream); fstream.on('close', () => { - let uuid = crypto.randomBytes(10).toString('hex'); + const uuid = crypto.randomBytes(10).toString('hex'); redis_client.hmset([id, 'filename', filename, 'delete', uuid]); redis_client.expire(id, 86400000); @@ -105,7 +105,7 @@ function localDelete(id, delete_token) { reject(); } else { redis_client.del(id); - resolve(fs.unlinkSync(__dirname + '/../static/' + id)); + resolve(fs.unlinkSync(path.join(__dirname, '../static', id))); } }); }); @@ -114,12 +114,12 @@ function localDelete(id, delete_token) { function localForceDelete(id) { return new Promise((resolve, reject) => { redis_client.del(id); - resolve(fs.unlinkSync(__dirname + '/../static/' + id)); + resolve(fs.unlinkSync(path.join(__dirname, '../static', id))); }); } function awsLength(id) { - let params = { + const params = { Bucket: conf.s3_bucket, Key: id }; @@ -135,7 +135,7 @@ function awsLength(id) { } function awsGet(id) { - let params = { + const params = { Bucket: conf.s3_bucket, Key: id }; @@ -144,19 +144,19 @@ function awsGet(id) { } function awsSet(id, file, filename, url) { - let params = { + const params = { Bucket: conf.s3_bucket, Key: id, Body: file }; return new Promise((resolve, reject) => { - s3.upload(params, function(err, data) { + s3.upload(params, function(err, _data) { if (err) { log.info('awsUploadError:', err.stack); // an error occurred reject(); } else { - let uuid = crypto.randomBytes(10).toString('hex'); + const uuid = crypto.randomBytes(10).toString('hex'); redis_client.hmset([id, 'filename', filename, 'delete', uuid]); @@ -197,12 +197,12 @@ function awsDelete(id, delete_token) { reject(); } else { redis_client.del(id); - let params = { + const params = { Bucket: conf.s3_bucket, Key: id }; - s3.deleteObject(params, function(err, data) { + s3.deleteObject(params, function(err, _data) { resolve(err); }); } @@ -213,12 +213,12 @@ function awsDelete(id, delete_token) { function awsForceDelete(id) { return new Promise((resolve, reject) => { redis_client.del(id); - let params = { + const params = { Bucket: conf.s3_bucket, Key: id }; - s3.deleteObject(params, function(err, data) { + s3.deleteObject(params, function(err, _data) { resolve(err); }); });