mirror of
https://gitlab.com/timvisee/send.git
synced 2025-12-09 19:55:34 +00:00
Compare commits
35 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
030d65d7af | ||
|
|
aa113fd903 | ||
|
|
caeba94e04 | ||
|
|
a7de951115 | ||
|
|
e17d1f7235 | ||
|
|
51ba253f95 | ||
|
|
fef26e083a | ||
|
|
de826afb9b | ||
|
|
5944b85e67 | ||
|
|
d208a82089 | ||
|
|
a64eced8be | ||
|
|
ada45323e1 | ||
|
|
ced8c24f47 | ||
|
|
5b9e9d5146 | ||
|
|
280a4f65e7 | ||
|
|
d2dd9f4b4d | ||
|
|
2897a39131 | ||
|
|
626b9068a9 | ||
|
|
c3bb876a2c | ||
|
|
48912dd4d4 | ||
|
|
f1c894d14f | ||
|
|
60d61fa52c | ||
|
|
68705f60db | ||
|
|
92303988c0 | ||
|
|
49d578217c | ||
|
|
1abb3b7ebe | ||
|
|
4f3c2498a6 | ||
|
|
33babe6f67 | ||
|
|
a51ee89939 | ||
|
|
bca79489c0 | ||
|
|
ddfbb06e1a | ||
|
|
cd2c944d41 | ||
|
|
5f66496519 | ||
|
|
318964251d | ||
|
|
5effeb16d1 |
@@ -21,6 +21,7 @@ rules:
|
|||||||
|
|
||||||
eol-last: [error, always]
|
eol-last: [error, always]
|
||||||
eqeqeq: error
|
eqeqeq: error
|
||||||
|
no-alert: warn
|
||||||
no-console: warn
|
no-console: warn
|
||||||
no-path-concat: error
|
no-path-concat: error
|
||||||
no-unused-vars: [error, {argsIgnorePattern: "^_|err|event|next|reject"}]
|
no-unused-vars: [error, {argsIgnorePattern: "^_|err|event|next|reject"}]
|
||||||
|
|||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -4,6 +4,7 @@ public/upload.js
|
|||||||
public/download.js
|
public/download.js
|
||||||
public/version.json
|
public/version.json
|
||||||
public/l20n.min.js
|
public/l20n.min.js
|
||||||
|
public/polyfill.min.js
|
||||||
static/*
|
static/*
|
||||||
!static/info.txt
|
!static/info.txt
|
||||||
test/frontend/bundle.js
|
test/frontend/bundle.js
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ $ redis-server /usr/local/etc/redis.conf
|
|||||||
|
|
||||||
## Localization
|
## Localization
|
||||||
|
|
||||||
_Coming soon_ (see [#57](https://github.com/mozilla/send/issues/57))
|
Firefox Send localization is managed via [Pontoon](https://pontoon.mozilla.org/projects/test-pilot-firefox-send/), not direct pull requests to the repository. If you want to fix a typo, add a new language, or simply know more about localization, please get in touch with the [existing localization team](https://pontoon.mozilla.org/teams/) for your language, or Mozilla’s [l10n-drivers](https://wiki.mozilla.org/L10n:Mozilla_Team#Mozilla_Corporation) for guidance.
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ deployment:
|
|||||||
|
|
||||||
test:
|
test:
|
||||||
override:
|
override:
|
||||||
|
- npm run build:version
|
||||||
- npm run lint
|
- npm run lint
|
||||||
- npm test
|
- npm test
|
||||||
- nsp check
|
- nsp check
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
window.Raven = require('raven-js');
|
window.Raven = require('raven-js');
|
||||||
window.Raven.config(window.dsn).install();
|
if (navigator.doNotTrack !== '1' && window.RAVEN_CONFIG) {
|
||||||
window.dsn = undefined;
|
window.Raven.config(window.SENTRY_ID, window.RAVEN_CONFIG).install();
|
||||||
|
}
|
||||||
|
|
||||||
const testPilotGA = require('testpilot-ga');
|
const testPilotGA = require('testpilot-ga');
|
||||||
const { gcmCompliant, sendEvent } = require('./utils');
|
const { gcmCompliant, sendEvent } = require('./utils');
|
||||||
window.analytics = new testPilotGA({
|
window.analytics = new testPilotGA({
|
||||||
an: 'Firefox Send',
|
an: 'Firefox Send',
|
||||||
ds: 'web',
|
ds: 'web',
|
||||||
tid: window.trackerId
|
tid: window.GOOGLE_ANALYTICS_ID
|
||||||
});
|
});
|
||||||
|
|
||||||
const isSender = !location.pathname.includes('/download');
|
const isSender = !location.pathname.includes('/download');
|
||||||
|
|||||||
@@ -144,7 +144,7 @@ $(document).ready(function() {
|
|||||||
$('#download-btn').attr('hidden', true);
|
$('#download-btn').attr('hidden', true);
|
||||||
$('#expired-img').removeAttr('hidden');
|
$('#expired-img').removeAttr('hidden');
|
||||||
}
|
}
|
||||||
return;
|
throw err;
|
||||||
})
|
})
|
||||||
.then(([decrypted, fname]) => {
|
.then(([decrypted, fname]) => {
|
||||||
const endTime = Date.now();
|
const endTime = Date.now();
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
const EventEmitter = require('events');
|
const EventEmitter = require('events');
|
||||||
const { arrayToHex } = require('./utils');
|
const { arrayToHex } = require('./utils');
|
||||||
|
|
||||||
const Raven = window.Raven;
|
|
||||||
|
|
||||||
class FileSender extends EventEmitter {
|
class FileSender extends EventEmitter {
|
||||||
constructor(file) {
|
constructor(file) {
|
||||||
super();
|
super();
|
||||||
@@ -38,15 +36,14 @@ class FileSender extends EventEmitter {
|
|||||||
const self = this;
|
const self = this;
|
||||||
self.emit('loading', true);
|
self.emit('loading', true);
|
||||||
return Promise.all([
|
return Promise.all([
|
||||||
window.crypto.subtle
|
window.crypto.subtle.generateKey(
|
||||||
.generateKey(
|
{
|
||||||
{
|
name: 'AES-GCM',
|
||||||
name: 'AES-GCM',
|
length: 128
|
||||||
length: 128
|
},
|
||||||
},
|
true,
|
||||||
true,
|
['encrypt', 'decrypt']
|
||||||
['encrypt', 'decrypt']
|
),
|
||||||
),
|
|
||||||
new Promise((resolve, reject) => {
|
new Promise((resolve, reject) => {
|
||||||
const reader = new FileReader();
|
const reader = new FileReader();
|
||||||
reader.readAsArrayBuffer(this.file);
|
reader.readAsArrayBuffer(this.file);
|
||||||
@@ -133,10 +130,6 @@ class FileSender extends EventEmitter {
|
|||||||
);
|
);
|
||||||
xhr.send(fd);
|
xhr.send(fd);
|
||||||
});
|
});
|
||||||
})
|
|
||||||
.catch(err => {
|
|
||||||
Raven.captureException(err);
|
|
||||||
return Promise.reject(err);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,12 @@ class Storage {
|
|||||||
for (let i = 0; i < this.engine.length; i++) {
|
for (let i = 0; i < this.engine.length; i++) {
|
||||||
const k = this.engine.key(i);
|
const k = this.engine.key(i);
|
||||||
if (isFile(k)) {
|
if (isFile(k)) {
|
||||||
fs.push(JSON.parse(this.engine.getItem(k))); // parse or whatever else
|
try {
|
||||||
|
fs.push(JSON.parse(this.engine.getItem(k)));
|
||||||
|
} catch (err) {
|
||||||
|
// obviously you're not a golfer
|
||||||
|
this.engine.removeItem(k);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return fs.sort((file1, file2) => {
|
return fs.sort((file1, file2) => {
|
||||||
|
|||||||
@@ -1,12 +1,7 @@
|
|||||||
/* global MAXFILESIZE EXPIRE_SECONDS */
|
/* global MAXFILESIZE EXPIRE_SECONDS */
|
||||||
require('./common');
|
require('./common');
|
||||||
const FileSender = require('./fileSender');
|
const FileSender = require('./fileSender');
|
||||||
const {
|
const { notify, findMetric, sendEvent, ONE_DAY_IN_MS } = require('./utils');
|
||||||
notify,
|
|
||||||
findMetric,
|
|
||||||
sendEvent,
|
|
||||||
ONE_DAY_IN_MS
|
|
||||||
} = require('./utils');
|
|
||||||
const bytes = require('bytes');
|
const bytes = require('bytes');
|
||||||
const Storage = require('./storage');
|
const Storage = require('./storage');
|
||||||
const storage = new Storage(localStorage);
|
const storage = new Storage(localStorage);
|
||||||
|
|||||||
@@ -99,12 +99,7 @@ function findMetric(href) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function isFile(id) {
|
function isFile(id) {
|
||||||
return ![
|
return /^[0-9a-fA-F]{10}$/.test(id);
|
||||||
'referrer',
|
|
||||||
'totalDownloads',
|
|
||||||
'totalUploads',
|
|
||||||
'testpilot_ga__cid'
|
|
||||||
].includes(id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function sendEvent() {
|
function sendEvent() {
|
||||||
|
|||||||
147
package-lock.json
generated
147
package-lock.json
generated
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "firefox-send",
|
"name": "firefox-send",
|
||||||
"version": "1.0.2",
|
"version": "1.0.3",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -263,6 +263,43 @@
|
|||||||
"js-tokens": "3.0.2"
|
"js-tokens": "3.0.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"babel-polyfill": {
|
||||||
|
"version": "6.23.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.23.0.tgz",
|
||||||
|
"integrity": "sha1-g2TKYt+Or7gwSZ9pkXdGbDsDSZ0=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"babel-runtime": "6.25.0",
|
||||||
|
"core-js": "2.4.1",
|
||||||
|
"regenerator-runtime": "0.10.5"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"core-js": {
|
||||||
|
"version": "2.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.4.1.tgz",
|
||||||
|
"integrity": "sha1-TekR5mew6ukSTjQlS1OupvxhjT4=",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"babel-runtime": {
|
||||||
|
"version": "6.25.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.25.0.tgz",
|
||||||
|
"integrity": "sha1-M7mOql1IK7AajRqmtDetKwGuxBw=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"core-js": "2.4.1",
|
||||||
|
"regenerator-runtime": "0.10.5"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"core-js": {
|
||||||
|
"version": "2.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.4.1.tgz",
|
||||||
|
"integrity": "sha1-TekR5mew6ukSTjQlS1OupvxhjT4=",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"balanced-match": {
|
"balanced-match": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
|
||||||
@@ -271,12 +308,12 @@
|
|||||||
"base64-js": {
|
"base64-js": {
|
||||||
"version": "1.2.1",
|
"version": "1.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.1.tgz",
|
||||||
"integrity": "sha1-qRlH2h9KUW6jjltOwOw3c2deCIY="
|
"integrity": "sha512-dwVUVIXsBZXwTuwnXI9RK8sBmgq09NDHzyR9SAph9eqk76gKK2JSQmZARC2zRC81JC2QTtxD0ARU5qTS25gIGw=="
|
||||||
},
|
},
|
||||||
"bn.js": {
|
"bn.js": {
|
||||||
"version": "4.11.7",
|
"version": "4.11.7",
|
||||||
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.7.tgz",
|
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.7.tgz",
|
||||||
"integrity": "sha1-3bBI5Q2UgnkAlME+s/z8gzznq0Y=",
|
"integrity": "sha512-LxFiV5mefv0ley0SzqkOPR1bC4EbpPx8LkOz5vMe/Yi15t5hzwgO/G+tc7wOtL4PZTYjwHu8JnEiSLumuSjSfA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"body-parser": {
|
"body-parser": {
|
||||||
@@ -451,7 +488,7 @@
|
|||||||
"glob": {
|
"glob": {
|
||||||
"version": "7.1.2",
|
"version": "7.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
|
||||||
"integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=",
|
"integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"fs.realpath": "1.0.0",
|
"fs.realpath": "1.0.0",
|
||||||
@@ -480,7 +517,7 @@
|
|||||||
"string_decoder": {
|
"string_decoder": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
|
||||||
"integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=",
|
"integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"safe-buffer": "5.1.1"
|
"safe-buffer": "5.1.1"
|
||||||
@@ -917,65 +954,75 @@
|
|||||||
"resolved": "https://registry.npmjs.org/convict/-/convict-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/convict/-/convict-3.0.0.tgz",
|
||||||
"integrity": "sha1-JZ8wv7h+4JRIYEhiA1GdRntNUbU=",
|
"integrity": "sha1-JZ8wv7h+4JRIYEhiA1GdRntNUbU=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"depd": "https://registry.npmjs.org/depd/-/depd-1.1.0.tgz",
|
"depd": "1.1.0",
|
||||||
"json5": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz",
|
"json5": "0.5.1",
|
||||||
"lodash.clonedeep": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
|
"lodash.clonedeep": "4.5.0",
|
||||||
"minimist": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
|
"minimist": "1.2.0",
|
||||||
"moment": "https://registry.npmjs.org/moment/-/moment-2.17.1.tgz",
|
"moment": "2.17.1",
|
||||||
"validator": "https://registry.npmjs.org/validator/-/validator-7.0.0.tgz",
|
"validator": "7.0.0",
|
||||||
"varify": "https://registry.npmjs.org/varify/-/varify-0.2.0.tgz"
|
"varify": "0.2.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"depd": {
|
"depd": {
|
||||||
"version": "https://registry.npmjs.org/depd/-/depd-1.1.0.tgz",
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.0.tgz",
|
||||||
"integrity": "sha1-4b2Cxqq2ztlluXuIsX7T5SjKGMM="
|
"integrity": "sha1-4b2Cxqq2ztlluXuIsX7T5SjKGMM="
|
||||||
},
|
},
|
||||||
"json5": {
|
"json5": {
|
||||||
"version": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz",
|
"version": "0.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz",
|
||||||
"integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE="
|
"integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE="
|
||||||
},
|
},
|
||||||
"lodash.clonedeep": {
|
"lodash.clonedeep": {
|
||||||
"version": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
|
"version": "4.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
|
||||||
"integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8="
|
"integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8="
|
||||||
},
|
},
|
||||||
"minimist": {
|
"minimist": {
|
||||||
"version": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
|
||||||
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ="
|
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ="
|
||||||
},
|
},
|
||||||
"moment": {
|
"moment": {
|
||||||
"version": "https://registry.npmjs.org/moment/-/moment-2.17.1.tgz",
|
"version": "2.17.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/moment/-/moment-2.17.1.tgz",
|
||||||
"integrity": "sha1-/tlQYGPzaxDwZsi1mhRNf66+HYI="
|
"integrity": "sha1-/tlQYGPzaxDwZsi1mhRNf66+HYI="
|
||||||
},
|
},
|
||||||
"validator": {
|
"validator": {
|
||||||
"version": "https://registry.npmjs.org/validator/-/validator-7.0.0.tgz",
|
"version": "7.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/validator/-/validator-7.0.0.tgz",
|
||||||
"integrity": "sha1-x03rgGNRL6w1VHk45vCxUEooL9I="
|
"integrity": "sha1-x03rgGNRL6w1VHk45vCxUEooL9I="
|
||||||
},
|
},
|
||||||
"varify": {
|
"varify": {
|
||||||
"version": "https://registry.npmjs.org/varify/-/varify-0.2.0.tgz",
|
"version": "0.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/varify/-/varify-0.2.0.tgz",
|
||||||
"integrity": "sha1-GR2p/p3EzWjQ0USY1OKpEP9OZRY=",
|
"integrity": "sha1-GR2p/p3EzWjQ0USY1OKpEP9OZRY=",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"redeyed": "https://registry.npmjs.org/redeyed/-/redeyed-1.0.1.tgz",
|
"redeyed": "1.0.1",
|
||||||
"through": "https://registry.npmjs.org/through/-/through-2.3.8.tgz"
|
"through": "2.3.8"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"redeyed": {
|
"redeyed": {
|
||||||
"version": "https://registry.npmjs.org/redeyed/-/redeyed-1.0.1.tgz",
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/redeyed/-/redeyed-1.0.1.tgz",
|
||||||
"integrity": "sha1-6WwZO0DAgWsArshCaY5hGF5VSYo=",
|
"integrity": "sha1-6WwZO0DAgWsArshCaY5hGF5VSYo=",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"esprima": "https://registry.npmjs.org/esprima/-/esprima-3.0.0.tgz"
|
"esprima": "3.0.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"esprima": {
|
"esprima": {
|
||||||
"version": "https://registry.npmjs.org/esprima/-/esprima-3.0.0.tgz",
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/esprima/-/esprima-3.0.0.tgz",
|
||||||
"integrity": "sha1-U88kes2ncxPlUcOqLnM0LT+099k=",
|
"integrity": "sha1-U88kes2ncxPlUcOqLnM0LT+099k=",
|
||||||
"optional": true
|
"optional": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"through": {
|
"through": {
|
||||||
"version": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
|
"version": "2.3.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
|
||||||
"integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
|
"integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
|
||||||
"optional": true
|
"optional": true
|
||||||
}
|
}
|
||||||
@@ -1302,7 +1349,7 @@
|
|||||||
"string_decoder": {
|
"string_decoder": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
|
||||||
"integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=",
|
"integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"safe-buffer": "5.1.1"
|
"safe-buffer": "5.1.1"
|
||||||
@@ -1526,7 +1573,7 @@
|
|||||||
"eslint-plugin-security": {
|
"eslint-plugin-security": {
|
||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/eslint-plugin-security/-/eslint-plugin-security-1.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/eslint-plugin-security/-/eslint-plugin-security-1.4.0.tgz",
|
||||||
"integrity": "sha1-1PMUSEqAsbYTuMiIboT1Lv4VJsI=",
|
"integrity": "sha512-xlS7P2PLMXeqfhyf3NpqbvbnW04kN8M9NtmhpR3XGyOvt/vNKS7XPXT5EDbwKW9vCjWH4PpfQvgD/+JgN0VJKA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"safe-regex": "1.1.0"
|
"safe-regex": "1.1.0"
|
||||||
@@ -1730,7 +1777,7 @@
|
|||||||
"iconv-lite": {
|
"iconv-lite": {
|
||||||
"version": "0.4.18",
|
"version": "0.4.18",
|
||||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.18.tgz",
|
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.18.tgz",
|
||||||
"integrity": "sha1-I9hlaxaq5nQqwpcy6o8DNqR4nPI=",
|
"integrity": "sha512-sr1ZQph3UwHTR0XftSbK85OvBbxe/abLGzEnPENCQwmHf7sck8Oyu4ob3LgBxWWxRoM+QszeUyl7jbqapu2TqA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2002,7 +2049,7 @@
|
|||||||
"globals": {
|
"globals": {
|
||||||
"version": "9.18.0",
|
"version": "9.18.0",
|
||||||
"resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz",
|
"resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz",
|
||||||
"integrity": "sha1-qjiWs+abSH8X4x7SFD1pqOMMLYo=",
|
"integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"globby": {
|
"globby": {
|
||||||
@@ -2022,7 +2069,7 @@
|
|||||||
"glob": {
|
"glob": {
|
||||||
"version": "7.1.2",
|
"version": "7.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
|
||||||
"integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=",
|
"integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"fs.realpath": "1.0.0",
|
"fs.realpath": "1.0.0",
|
||||||
@@ -2947,7 +2994,7 @@
|
|||||||
"lru-cache": {
|
"lru-cache": {
|
||||||
"version": "4.1.1",
|
"version": "4.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz",
|
||||||
"integrity": "sha1-Yi4y6CSItJJ5EUpPns9F581rulU=",
|
"integrity": "sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"pseudomap": "1.0.2",
|
"pseudomap": "1.0.2",
|
||||||
@@ -3093,7 +3140,7 @@
|
|||||||
"minimatch": {
|
"minimatch": {
|
||||||
"version": "3.0.4",
|
"version": "3.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
|
||||||
"integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=",
|
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"brace-expansion": "1.1.8"
|
"brace-expansion": "1.1.8"
|
||||||
}
|
}
|
||||||
@@ -3226,7 +3273,7 @@
|
|||||||
"string_decoder": {
|
"string_decoder": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
|
||||||
"integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=",
|
"integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"safe-buffer": "5.1.1"
|
"safe-buffer": "5.1.1"
|
||||||
@@ -3787,7 +3834,7 @@
|
|||||||
"promise": {
|
"promise": {
|
||||||
"version": "7.3.1",
|
"version": "7.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz",
|
||||||
"integrity": "sha1-BktyYCsY+Q8pGSuLG8QY/9Hr078=",
|
"integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"asap": "2.0.6"
|
"asap": "2.0.6"
|
||||||
}
|
}
|
||||||
@@ -3919,7 +3966,7 @@
|
|||||||
"randombytes": {
|
"randombytes": {
|
||||||
"version": "2.0.5",
|
"version": "2.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.5.tgz",
|
||||||
"integrity": "sha1-3ACaJGuNCaF3tLegrne8Vw9LG3k=",
|
"integrity": "sha512-8T7Zn1AhMsQ/HI1SjcCfT/t4ii3eAqco3yOcSzS4mozsOz69lHLsoMXmF9nZgnFanYscnSlUSgs8uZyKzpE6kg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"safe-buffer": "5.1.1"
|
"safe-buffer": "5.1.1"
|
||||||
@@ -4005,7 +4052,7 @@
|
|||||||
"string_decoder": {
|
"string_decoder": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
|
||||||
"integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=",
|
"integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"safe-buffer": "5.1.1"
|
"safe-buffer": "5.1.1"
|
||||||
@@ -4142,6 +4189,12 @@
|
|||||||
"resolved": "https://registry.npmjs.org/referrer-policy/-/referrer-policy-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/referrer-policy/-/referrer-policy-1.1.0.tgz",
|
||||||
"integrity": "sha1-NXdOtzW/UPtsB46DM0tHI1AgfXk="
|
"integrity": "sha1-NXdOtzW/UPtsB46DM0tHI1AgfXk="
|
||||||
},
|
},
|
||||||
|
"regenerator-runtime": {
|
||||||
|
"version": "0.10.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz",
|
||||||
|
"integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"regex-cache": {
|
"regex-cache": {
|
||||||
"version": "0.4.3",
|
"version": "0.4.3",
|
||||||
"resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.3.tgz",
|
"resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.3.tgz",
|
||||||
@@ -4246,7 +4299,7 @@
|
|||||||
"glob": {
|
"glob": {
|
||||||
"version": "7.1.2",
|
"version": "7.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
|
||||||
"integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=",
|
"integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"fs.realpath": "1.0.0",
|
"fs.realpath": "1.0.0",
|
||||||
@@ -4296,7 +4349,7 @@
|
|||||||
"safe-buffer": {
|
"safe-buffer": {
|
||||||
"version": "5.1.1",
|
"version": "5.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
|
||||||
"integrity": "sha1-iTMSr2myEj3vcfV4iQAWce6yyFM=",
|
"integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"safe-regex": {
|
"safe-regex": {
|
||||||
@@ -4444,7 +4497,7 @@
|
|||||||
"glob": {
|
"glob": {
|
||||||
"version": "7.1.2",
|
"version": "7.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
|
||||||
"integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=",
|
"integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"fs.realpath": "1.0.0",
|
"fs.realpath": "1.0.0",
|
||||||
@@ -4590,7 +4643,7 @@
|
|||||||
"string_decoder": {
|
"string_decoder": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
|
||||||
"integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=",
|
"integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"safe-buffer": "5.1.1"
|
"safe-buffer": "5.1.1"
|
||||||
@@ -4635,7 +4688,7 @@
|
|||||||
"string_decoder": {
|
"string_decoder": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
|
||||||
"integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=",
|
"integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"safe-buffer": "5.1.1"
|
"safe-buffer": "5.1.1"
|
||||||
@@ -4646,7 +4699,7 @@
|
|||||||
"stream-http": {
|
"stream-http": {
|
||||||
"version": "2.7.2",
|
"version": "2.7.2",
|
||||||
"resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.7.2.tgz",
|
"resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.7.2.tgz",
|
||||||
"integrity": "sha1-QKBQ7I3DtTsz2ZCUFcAsC/Gr+60=",
|
"integrity": "sha512-c0yTD2rbQzXtSsFSVhtpvY/vS6u066PcXOX9kBB3mSO76RiUQzL340uJkGBWnlBg4/HZzqiUXtaVA7wcRcJgEw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"builtin-status-codes": "3.0.0",
|
"builtin-status-codes": "3.0.0",
|
||||||
@@ -4674,7 +4727,7 @@
|
|||||||
"string_decoder": {
|
"string_decoder": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
|
||||||
"integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=",
|
"integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"safe-buffer": "5.1.1"
|
"safe-buffer": "5.1.1"
|
||||||
@@ -4710,7 +4763,7 @@
|
|||||||
"string_decoder": {
|
"string_decoder": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
|
||||||
"integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=",
|
"integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"safe-buffer": "5.1.1"
|
"safe-buffer": "5.1.1"
|
||||||
@@ -5007,7 +5060,7 @@
|
|||||||
"readable-stream": {
|
"readable-stream": {
|
||||||
"version": "2.3.3",
|
"version": "2.3.3",
|
||||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz",
|
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz",
|
||||||
"integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=",
|
"integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"core-util-is": "1.0.2",
|
"core-util-is": "1.0.2",
|
||||||
@@ -5022,7 +5075,7 @@
|
|||||||
"string_decoder": {
|
"string_decoder": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
|
||||||
"integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=",
|
"integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"safe-buffer": "5.1.1"
|
"safe-buffer": "5.1.1"
|
||||||
@@ -5152,7 +5205,7 @@
|
|||||||
"string_decoder": {
|
"string_decoder": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
|
||||||
"integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=",
|
"integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"safe-buffer": "5.1.1"
|
"safe-buffer": "5.1.1"
|
||||||
|
|||||||
37
package.json
37
package.json
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "firefox-send",
|
"name": "firefox-send",
|
||||||
"description": "File Sharing Experiment",
|
"description": "File Sharing Experiment",
|
||||||
"version": "1.0.2",
|
"version": "1.0.3",
|
||||||
"author": "Mozilla (https://mozilla.org)",
|
"author": "Mozilla (https://mozilla.org)",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"aws-sdk": "^2.89.0",
|
"aws-sdk": "^2.89.0",
|
||||||
@@ -17,6 +17,7 @@
|
|||||||
"redis": "^2.7.1"
|
"redis": "^2.7.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"babel-polyfill": "^6.23.0",
|
||||||
"browserify": "^14.4.0",
|
"browserify": "^14.4.0",
|
||||||
"eslint": "^4.3.0",
|
"eslint": "^4.3.0",
|
||||||
"eslint-plugin-mocha": "^4.11.0",
|
"eslint-plugin-mocha": "^4.11.0",
|
||||||
@@ -46,49 +47,55 @@
|
|||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
"repository": "mozilla/send",
|
"repository": "mozilla/send",
|
||||||
"availableLanguages": [
|
"availableLanguages": [
|
||||||
"en-US",
|
"az",
|
||||||
"zh-TW",
|
|
||||||
"zh-CN",
|
|
||||||
"cs",
|
"cs",
|
||||||
|
"cy",
|
||||||
|
"de",
|
||||||
|
"dsb",
|
||||||
|
"en-US",
|
||||||
|
"es-ES",
|
||||||
|
"es-MX",
|
||||||
"fr",
|
"fr",
|
||||||
"fy-NL",
|
"fy-NL",
|
||||||
"de",
|
"hsb",
|
||||||
"hu",
|
"hu",
|
||||||
"it",
|
"it",
|
||||||
"ja",
|
"ja",
|
||||||
"kab",
|
"kab",
|
||||||
"ms",
|
"ms",
|
||||||
"nb-NO",
|
"nb-NO",
|
||||||
|
"nl",
|
||||||
"nn-NO",
|
"nn-NO",
|
||||||
"pt-PT",
|
|
||||||
"pt-BR",
|
"pt-BR",
|
||||||
|
"pt-PT",
|
||||||
"ru",
|
"ru",
|
||||||
"sk",
|
"sk",
|
||||||
"sl",
|
"sl",
|
||||||
"dsb",
|
"sr",
|
||||||
"hsb",
|
|
||||||
"es-CL",
|
|
||||||
"es-ES",
|
|
||||||
"es-MX",
|
|
||||||
"sv-SE",
|
"sv-SE",
|
||||||
"tr",
|
"zh-CN",
|
||||||
"cy"
|
"zh-TW"
|
||||||
],
|
],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "npm-run-all build:*",
|
"build": "npm-run-all build:*",
|
||||||
"build:upload": "browserify frontend/src/upload.js -g uglifyify -o public/upload.js",
|
"build:upload": "browserify frontend/src/upload.js -g uglifyify -o public/upload.js",
|
||||||
"build:download": "browserify frontend/src/download.js -g uglifyify -o public/download.js",
|
"build:download": "browserify frontend/src/download.js -g uglifyify -o public/download.js",
|
||||||
"build:version": "node scripts/version",
|
"build:version": "node scripts/version",
|
||||||
"build:l10n": "cp node_modules/l20n/dist/web/l20n.min.js public",
|
"build:vendor": "cp node_modules/l20n/dist/web/l20n.min.js node_modules/babel-polyfill/dist/polyfill.min.js public",
|
||||||
"dev": "npm run build && npm start",
|
"dev": "npm run build && npm start",
|
||||||
"format": "prettier '{frontend/src/,scripts/,server/,test/**/!(bundle)}*.js' 'public/*.css' --single-quote --write",
|
"format": "prettier '{frontend/src/,scripts/,server/,test/**/!(bundle)}*.js' 'public/*.css' --single-quote --write",
|
||||||
|
"get-prod-locales": "node scripts/get-prod-locales",
|
||||||
|
"get-prod-locales:write": "npm run get-prod-locales -- --write",
|
||||||
"lint": "npm-run-all lint:*",
|
"lint": "npm-run-all lint:*",
|
||||||
"lint:css": "stylelint 'public/*.css'",
|
"lint:css": "stylelint 'public/*.css'",
|
||||||
"lint:js": "eslint .",
|
"lint:js": "eslint .",
|
||||||
|
"lint-locales": "node scripts/lint-locales",
|
||||||
|
"lint-locales:dev": "npm run lint-locales",
|
||||||
|
"lint-locales:prod": "npm run lint-locales -- --production",
|
||||||
"start": "node server/server",
|
"start": "node server/server",
|
||||||
"test": "npm-run-all test:*",
|
"test": "npm-run-all test:*",
|
||||||
"test:unit": "mocha test/unit",
|
"test:unit": "mocha test/unit",
|
||||||
"test:server": "mocha test/server",
|
"test:server": "mocha test/server",
|
||||||
"test:browser": "browserify test/frontend/frontend.bundle.js -o test/frontend/bundle.js -d && node test/frontend/driver.js"
|
"test--browser": "browserify test/frontend/frontend.bundle.js -o test/frontend/bundle.js -d && node test/frontend/driver.js"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
94
public/locales/az/send.ftl
Normal file
94
public/locales/az/send.ftl
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
// Firefox Send is a brand name and should not be localized.
|
||||||
|
title = Firefox Send
|
||||||
|
siteSubtitle = web eksperiment
|
||||||
|
siteFeedback = Geri dönüş
|
||||||
|
uploadPageHeader = Məxfi, Şifrələnmiş Fayl Paylaşma
|
||||||
|
uploadPageExplainer = Fayllarınızı təhlükəsiz, məxfi, şifrələnmiş və daima onlayn qalmaması üçün avtomatik silinən keçidlə göndərin.
|
||||||
|
uploadPageLearnMore = Ətraflı öyrən
|
||||||
|
uploadPageDropMessage = Yükləmək üçün faylınızı buraya daşıyın
|
||||||
|
uploadPageSizeMessage = Xidmətin daha yaxşı işləməsi üçün faylınız 1 GB-dan az olmalıdır
|
||||||
|
uploadPageBrowseButton = Kompüterinizdən fayl seçin
|
||||||
|
.title = Kompüterinizdən fayl seçin
|
||||||
|
uploadPageMultipleFilesAlert = Birdən çox fayl və ya qovluq yükləmə hələlik dəstəklənmir.
|
||||||
|
uploadPageBrowseButtonTitle = Fayl yüklə
|
||||||
|
uploadingPageHeader = Faylınız yüklənir
|
||||||
|
importingFile = İdxal edilir…
|
||||||
|
verifyingFile = Təsdiqlənir…
|
||||||
|
encryptingFile = Şifrələnir...
|
||||||
|
decryptingFile = Şifrə açılır...
|
||||||
|
notifyUploadDone = Yükləməniz hazırdır.
|
||||||
|
uploadingPageMessage = Faylınız yükləndikdən sonra vaxtı çıxma seçimlərini qura biləcəksiz.
|
||||||
|
uploadingPageCancel = Yükləməni ləğv et
|
||||||
|
.title = Yükləməni ləğv et
|
||||||
|
uploadCancelNotification = Yükləməniz ləğv edildi.
|
||||||
|
uploadingPageLargeFileMessage = Fayl böyükdür və yükləmək çox vaxt ala bilər. Səbirli olun!
|
||||||
|
uploadingFileNotification = Yükləmə bitdiyində xəbər ver.
|
||||||
|
uploadSuccessConfirmHeader = Göndərməyə hazır
|
||||||
|
uploadSvgAlt
|
||||||
|
.alt = Yüklə
|
||||||
|
uploadSuccessTimingHeader = Faylınızın keçidinin 1 endirmədən və ya 24 saatdan sonra vaxtı çıxacaq.
|
||||||
|
copyUrlFormLabelWithName = Faylınızı göndərmək üçün keçidi köçürün: { $filename }
|
||||||
|
// Note: Title text for button should be the same.
|
||||||
|
copyUrlFormButton = Buferə köçür
|
||||||
|
.title = Mübadilə buferinə köçür
|
||||||
|
copiedUrl = Köçürüldü!
|
||||||
|
// Note: Title text for button should be the same.
|
||||||
|
deleteFileButton = Faylı sil
|
||||||
|
.title = Faylı sil
|
||||||
|
// Note: Title text for button should be the same.
|
||||||
|
sendAnotherFileLink = Başqa fayl göndər
|
||||||
|
.title = Başqa fayl göndər
|
||||||
|
// Alternative text used on the download link/button (indicates an action).
|
||||||
|
downloadAltText
|
||||||
|
.alt = Endir
|
||||||
|
downloadFileName = { $filename } faylını endir
|
||||||
|
downloadFileSize = ({ $size })
|
||||||
|
// Firefox Send is a brand name and should not be localized.
|
||||||
|
downloadMessage = Yoldaşınız Firefox Send ilə sizə fayl göndərir, fayllarınızı təhlükəsiz, məxfi, şifrələnmiş və daima onlayn qalmaması üçün avtomatik silən fayl göndərmə xidməti.
|
||||||
|
// Text and title used on the download link/button (indicates an action).
|
||||||
|
downloadButtonLabel = Endir
|
||||||
|
.title = Endir
|
||||||
|
downloadNotification = Endirməniz tamamlandı.
|
||||||
|
downloadFinish = Endirmə Tamamlandı
|
||||||
|
// Firefox Send is a brand name and should not be localized. Title text for button should be the same.
|
||||||
|
sendYourFilesLink = Firefox Send Yoxla
|
||||||
|
.title = Firefox Send Yoxla
|
||||||
|
downloadingPageProgress = { $filename } faylı ({ $size }) endirilir
|
||||||
|
downloadingPageMessage = Lütfən faylı endirib şifrəsini açarkən vərəqi açıq buraxın.
|
||||||
|
errorAltText
|
||||||
|
.alt = Yükləmə xətası
|
||||||
|
errorPageHeader = Nəsə səhv getdi!
|
||||||
|
errorPageMessage = Faylı yüklərkən xəta baş verdi.
|
||||||
|
errorPageLink = Başqa fayl göndər
|
||||||
|
fileTooBig = Fayl yükləmək üçün çox böyükdür. Fayl { $size }-dan az olmalıdır.
|
||||||
|
linkExpiredAlt
|
||||||
|
.alt = Keçidin vaxtı çıxıb
|
||||||
|
expiredPageHeader = Keçidin vaxtı çıxıb və ya heç vaxt olmayıb!
|
||||||
|
notSupportedHeader = Səyyahınız dəstəklənmir.
|
||||||
|
// Firefox Send is a brand name and should not be localized.
|
||||||
|
notSupportedDetail = Heyf ki, bu səyyah Firefox Send-ə güc verən web texnologiyalarını dəstəkləmir. Fərqli bir səyyah yoxlamalısınız. Biz Firefox məsləhət görürük!
|
||||||
|
notSupportedOutdatedDetail = Heyf ki, Firefox səyyahının bu versiyası Firefox Send-ə güc verən web texnologiyalarını dəstəkləmir. Səyyahınızı yeniləməlisiniz.
|
||||||
|
updateFirefox = Firefox-u Yenilə
|
||||||
|
downloadFirefoxButtonSub = Pulsuz Endir
|
||||||
|
uploadedFile = Fayl
|
||||||
|
copyFileList = Keçidi Köçürt
|
||||||
|
// expiryFileList is used as a column header
|
||||||
|
expiryFileList = Vaxtı çıxma tarixi
|
||||||
|
deleteFileList = Sil
|
||||||
|
nevermindButton = Vacib deyil
|
||||||
|
legalHeader = Şərtlər və Məxfilik
|
||||||
|
legalNoticeTestPilot = Firefox Send Test Pilot eksperimentidir, Test Pilot <a>Xidmət Şərtləri</a> və <a>Məxfilik Bildirişi</a>-nə tabedir. Bu eksperiment və məlumat yığma haqqında <a>buradan</a> öyrənə bilərsiz.
|
||||||
|
legalNoticeMozilla = Firefox Send saytının istifadəsi həmçinin Mozilla-nın <a>Saytlar üçün Məxfilik Bildirişi</a> və <a>Sayt İstifadə Şərtləri</a>-nə tabedir.
|
||||||
|
deletePopupText = Fayl silinsin?
|
||||||
|
deletePopupYes = Bəli
|
||||||
|
deletePopupCancel = Ləğv et
|
||||||
|
deleteButtonHover
|
||||||
|
.title = Sil
|
||||||
|
copyUrlHover
|
||||||
|
.title = Keçidi Köçürt
|
||||||
|
footerLinkLegal = Hüquqi
|
||||||
|
// Test Pilot is a proper name and should not be localized.
|
||||||
|
footerLinkAbout = Test Pilot Haqqında
|
||||||
|
footerLinkPrivacy = Məxfilik
|
||||||
|
footerLinkTerms = Şərtlər
|
||||||
|
footerLinkCookies = Çərəzlər
|
||||||
@@ -26,7 +26,7 @@ uploadingFileNotification = Upozornit, až bude nahrávání dokončeno.
|
|||||||
uploadSuccessConfirmHeader = Připraveno k odeslání
|
uploadSuccessConfirmHeader = Připraveno k odeslání
|
||||||
uploadSvgAlt
|
uploadSvgAlt
|
||||||
.alt = Nahrát
|
.alt = Nahrát
|
||||||
uploadSuccessTimingHeader = Platnost odkazu na váš souboru vyprší pro jeho prvním stažení, nebo po 24 hodinách.
|
uploadSuccessTimingHeader = Platnost odkazu na váš souboru vyprší po jeho prvním stažení, nebo po 24 hodinách.
|
||||||
copyUrlFormLabelWithName = Zkopírujte a sdílejte odkaz na váš soubor: { $filename }
|
copyUrlFormLabelWithName = Zkopírujte a sdílejte odkaz na váš soubor: { $filename }
|
||||||
// Note: Title text for button should be the same.
|
// Note: Title text for button should be the same.
|
||||||
copyUrlFormButton = Zkopírovat do schránky
|
copyUrlFormButton = Zkopírovat do schránky
|
||||||
|
|||||||
@@ -67,6 +67,8 @@ expiredPageHeader = ¡El enlace ha caducado o nunca existió!
|
|||||||
notSupportedHeader = Tu navegador no está admitido.
|
notSupportedHeader = Tu navegador no está admitido.
|
||||||
// Firefox Send is a brand name and should not be localized.
|
// Firefox Send is a brand name and should not be localized.
|
||||||
notSupportedDetail = Lamentablemente, este navegador no admite la tecnología web que necesita Firefox Send. Tendrás que probar otro navegador. ¡Te recomendamos Firefox!
|
notSupportedDetail = Lamentablemente, este navegador no admite la tecnología web que necesita Firefox Send. Tendrás que probar otro navegador. ¡Te recomendamos Firefox!
|
||||||
|
notSupportedOutdatedDetail = Lamentablemente, esta versión de Firefox no admite la tecnología web que impulsa Firefox Send. Tendrás que actualizar tu navegador.
|
||||||
|
updateFirefox = Actualizar Firefox
|
||||||
downloadFirefoxButtonSub = Descarga gratuita
|
downloadFirefoxButtonSub = Descarga gratuita
|
||||||
uploadedFile = Archivo
|
uploadedFile = Archivo
|
||||||
copyFileList = Copiar URL
|
copyFileList = Copiar URL
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ uploadPageHeader = Privee, fersifere bestânsdieling
|
|||||||
uploadPageExplainer = Ferstjoer bestannen troch in feilich, privee en fersifere keppeling dy't automatysk ferrint, om foar te kommen dat jo guod net foar altyd online bliuwt.
|
uploadPageExplainer = Ferstjoer bestannen troch in feilich, privee en fersifere keppeling dy't automatysk ferrint, om foar te kommen dat jo guod net foar altyd online bliuwt.
|
||||||
uploadPageLearnMore = Mear ynfo
|
uploadPageLearnMore = Mear ynfo
|
||||||
uploadPageDropMessage = Sleep jo bestân hjir hinne om opladen te starten
|
uploadPageDropMessage = Sleep jo bestân hjir hinne om opladen te starten
|
||||||
uploadPageSizeMessage = Foar de meast betrouber wurking, is it it bêste om jo bestân lytser as 1 GB te hâlden
|
uploadPageSizeMessage = Foar de meast betroubere wurking, is it it bêste om jo bestân lytser as 1 GB te hâlden
|
||||||
uploadPageBrowseButton = Selektearje in bestân op jo kompjûter
|
uploadPageBrowseButton = Selektearje in bestân op jo kompjûter
|
||||||
.title = Selektearje in bestân op jo kompjûter
|
.title = Selektearje in bestân op jo kompjûter
|
||||||
uploadPageMultipleFilesAlert = Opladen fan mear bestannen tagelyk of in map wurdt op dit stuit net stipe.
|
uploadPageMultipleFilesAlert = Opladen fan mear bestannen tagelyk of in map wurdt op dit stuit net stipe.
|
||||||
|
|||||||
78
public/locales/id/send.ftl
Normal file
78
public/locales/id/send.ftl
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
// Firefox Send is a brand name and should not be localized.
|
||||||
|
title = Firefox Send
|
||||||
|
siteSubtitle = eksperimen web
|
||||||
|
siteFeedback = Saran
|
||||||
|
uploadPageHeader = Pribadi, Berbagi Berkas Terenskripsi
|
||||||
|
uploadPageLearnMore = Pelajari lebih lanjut
|
||||||
|
uploadPageBrowseButtonTitle = Unggah berkas
|
||||||
|
uploadingPageHeader = Mengunggah Berkas Anda
|
||||||
|
importingFile = Mengimpor…
|
||||||
|
verifyingFile = Memverifikasi…
|
||||||
|
encryptingFile = Mengenkripsi...
|
||||||
|
decryptingFile = Mendekripsi...
|
||||||
|
notifyUploadDone = Unggahan Anda telah selesai.
|
||||||
|
uploadingPageMessage = Setelah berkas diunggah, Anda dapat mengatur pilihan kedaluwarsa.
|
||||||
|
uploadingPageCancel = Batal unggah
|
||||||
|
.title = Batal unggah
|
||||||
|
uploadCancelNotification = Unggahan Anda dibatalkan.
|
||||||
|
uploadingPageLargeFileMessage = Berkas ini berukuran besar dan mungkin perlu beberapa saat untuk mengunggahnya. Silakan tunggu!
|
||||||
|
uploadingFileNotification = Beri tahu saya ketika unggahan telah selesai.
|
||||||
|
uploadSuccessConfirmHeader = Siap untuk Dikirim
|
||||||
|
uploadSvgAlt
|
||||||
|
.alt = Unggah
|
||||||
|
uploadSuccessTimingHeader = Tautan ke berkas Anda akan berakhir setelah 1 unduhan atau dalam 24 jam.
|
||||||
|
copyUrlFormLabelWithName = Salin dan bagikan tautan untuk mengirim berkas Anda: { $filename }
|
||||||
|
// Note: Title text for button should be the same.
|
||||||
|
copyUrlFormButton = Salin ke papan klip
|
||||||
|
.title = Salin ke papan klip
|
||||||
|
copiedUrl = Tersalin!
|
||||||
|
// Note: Title text for button should be the same.
|
||||||
|
deleteFileButton = Hapus berkas
|
||||||
|
.title = Hapus berkas
|
||||||
|
// Note: Title text for button should be the same.
|
||||||
|
sendAnotherFileLink = Kirim berkas lain
|
||||||
|
.title = Kirim berkas lain
|
||||||
|
// Alternative text used on the download link/button (indicates an action).
|
||||||
|
downloadAltText
|
||||||
|
.alt = Unduh
|
||||||
|
downloadFileName = Unduh { $filename }
|
||||||
|
downloadFileSize = ({ $size })
|
||||||
|
downloadNotification = Unduhan Anda telah selesai.
|
||||||
|
downloadFinish = Unduhan Selesai
|
||||||
|
// Firefox Send is a brand name and should not be localized. Title text for button should be the same.
|
||||||
|
sendYourFilesLink = Coba Firefox Send
|
||||||
|
.title = Coba Firefox Send
|
||||||
|
downloadingPageProgress = Mengunduh { $filename } ({ $size })
|
||||||
|
downloadingPageMessage = Sila biarkan tab ini terbuka sementara kami memproses berkas Anda dan mendekripsinya.
|
||||||
|
errorAltText
|
||||||
|
.alt = Unggahan bermasalah
|
||||||
|
errorPageHeader = Terjadi kesalahan!
|
||||||
|
errorPageMessage = Terjadi kesalahan saat mengunggah berkas.
|
||||||
|
errorPageLink = Kirim berkas lain
|
||||||
|
fileTooBig = Berkas terlalu besar untuk diunggah. Harus kurang dari { $size }.
|
||||||
|
linkExpiredAlt
|
||||||
|
.alt = Tautan kedaluwarsa
|
||||||
|
expiredPageHeader = Tautan ini telah kedaluwarsa atau tidak pernah ada!
|
||||||
|
notSupportedHeader = Peramban Anda tidak mendukung.
|
||||||
|
updateFirefox = Perbarui Firefox
|
||||||
|
downloadFirefoxButtonSub = Unduh Gratis
|
||||||
|
uploadedFile = Berkas
|
||||||
|
copyFileList = Salin URL
|
||||||
|
// expiryFileList is used as a column header
|
||||||
|
expiryFileList = Kedaluwarsa Pada
|
||||||
|
deleteFileList = Hapus
|
||||||
|
nevermindButton = Abaikan
|
||||||
|
legalHeader = Syarat & Privasi
|
||||||
|
deletePopupText = Hapus berkas ini?
|
||||||
|
deletePopupYes = Ya
|
||||||
|
deletePopupCancel = Batal
|
||||||
|
deleteButtonHover
|
||||||
|
.title = Hapus
|
||||||
|
copyUrlHover
|
||||||
|
.title = Salin URL
|
||||||
|
footerLinkLegal = Legal
|
||||||
|
// Test Pilot is a proper name and should not be localized.
|
||||||
|
footerLinkAbout = Tentang Test Pilot
|
||||||
|
footerLinkPrivacy = Privasi
|
||||||
|
footerLinkTerms = Ketentuan
|
||||||
|
footerLinkCookies = Kuki
|
||||||
94
public/locales/nl/send.ftl
Normal file
94
public/locales/nl/send.ftl
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
// Firefox Send is a brand name and should not be localized.
|
||||||
|
title = Firefox Send
|
||||||
|
siteSubtitle = webexperiment
|
||||||
|
siteFeedback = Feedback
|
||||||
|
uploadPageHeader = Privé, versleuteld bestanden delen
|
||||||
|
uploadPageExplainer = Stuur bestanden via een veilige, private en versleutelde koppeling die automatisch verloopt, zodat u zeker weet dat uw zaken niet onbeperkt online blijven.
|
||||||
|
uploadPageLearnMore = Meer info
|
||||||
|
uploadPageDropMessage = Sleep uw bestand hiernaartoe om het te uploaden
|
||||||
|
uploadPageSizeMessage = Voor de meest betrouwbare werking kunt u uw bestand het beste onder de 1 GB houden
|
||||||
|
uploadPageBrowseButton = Selecteer een bestand op uw computer
|
||||||
|
.title = Selecteer een bestand op uw computer
|
||||||
|
uploadPageMultipleFilesAlert = Het uploaden van meerdere bestanden of een map wordt momenteel niet ondersteund.
|
||||||
|
uploadPageBrowseButtonTitle = bestand uploaden
|
||||||
|
uploadingPageHeader = Uw bestand wordt geüpload
|
||||||
|
importingFile = Importeren…
|
||||||
|
verifyingFile = Verifiëren…
|
||||||
|
encryptingFile = Versleutelen…
|
||||||
|
decryptingFile = Ontcijferen…
|
||||||
|
notifyUploadDone = Uw upload is voltooid.
|
||||||
|
uploadingPageMessage = Zodra uw bestand wordt geüpload, kunt u vervalopties instellen.
|
||||||
|
uploadingPageCancel = Uploaden annuleren
|
||||||
|
.title = Uploaden annuleren
|
||||||
|
uploadCancelNotification = Uw upload is geannuleerd.
|
||||||
|
uploadingPageLargeFileMessage = Dit bestand is groot en het uploaden kan even duren. Even geduld…
|
||||||
|
uploadingFileNotification = Mij waarschuwen zodra het uploaden is voltooid
|
||||||
|
uploadSuccessConfirmHeader = Gereed voor verzending
|
||||||
|
uploadSvgAlt
|
||||||
|
.alt = Uploaden
|
||||||
|
uploadSuccessTimingHeader = De koppeling naar uw bestand zal na 1 download of 24 uur verlopen.
|
||||||
|
copyUrlFormLabelWithName = Kopieer en deel de koppeling om uw bestand te verzenden: { $filename }
|
||||||
|
// Note: Title text for button should be the same.
|
||||||
|
copyUrlFormButton = Kopiëren naar klembord
|
||||||
|
.title = Kopiëren naar klembord
|
||||||
|
copiedUrl = Gekopieerd!
|
||||||
|
// Note: Title text for button should be the same.
|
||||||
|
deleteFileButton = Bestand verwijderen
|
||||||
|
.title = Bestand verwijderen
|
||||||
|
// Note: Title text for button should be the same.
|
||||||
|
sendAnotherFileLink = Nog een bestand verzenden
|
||||||
|
.title = Nog een bestand verzenden
|
||||||
|
// Alternative text used on the download link/button (indicates an action).
|
||||||
|
downloadAltText
|
||||||
|
.alt = Downloaden
|
||||||
|
downloadFileName = { $filename } downloaden
|
||||||
|
downloadFileSize = ({ $size })
|
||||||
|
// Firefox Send is a brand name and should not be localized.
|
||||||
|
downloadMessage = Uw vriend(in) stuurt u een bestand met Firefox Send, een dienst waarmee u bestanden kunt verzenden met een veilige, private en versleutelde koppeling die automatisch verloopt, zodat u zeker weet dat uw zaken niet onbeperkt online blijven.
|
||||||
|
// Text and title used on the download link/button (indicates an action).
|
||||||
|
downloadButtonLabel = Downloaden
|
||||||
|
.title = Downloaden
|
||||||
|
downloadNotification = Uw download is voltooid.
|
||||||
|
downloadFinish = Downloaden voltooid
|
||||||
|
// Firefox Send is a brand name and should not be localized. Title text for button should be the same.
|
||||||
|
sendYourFilesLink = Firefox Send proberen
|
||||||
|
.title = Firefox Send proberen
|
||||||
|
downloadingPageProgress = { $filename } ({ $size }) wordt gedownload
|
||||||
|
downloadingPageMessage = Laat dit tabblad geopend terwijl uw bestand wordt opgehaald en ontcijferd.
|
||||||
|
errorAltText
|
||||||
|
.alt = Uploadfout
|
||||||
|
errorPageHeader = Er is iets misgegaan!
|
||||||
|
errorPageMessage = Er is een fout opgetreden bij het uploaden van het bestand.
|
||||||
|
errorPageLink = Nog een bestand verzenden
|
||||||
|
fileTooBig = Dat bestand is te groot om te worden geüpload. Het moet kleiner zijn dan { $size }.
|
||||||
|
linkExpiredAlt
|
||||||
|
.alt = Koppeling verlopen
|
||||||
|
expiredPageHeader = Deze koppeling is verlopen of heeft überhaupt nooit bestaan!
|
||||||
|
notSupportedHeader = Uw browser wordt niet ondersteund.
|
||||||
|
// Firefox Send is a brand name and should not be localized.
|
||||||
|
notSupportedDetail = Helaas ondersteunt deze browser de webtechnologie die Firefox Send gebruikt niet. U dient een andere browser te proberen. Firefox wordt aanbevolen!
|
||||||
|
notSupportedOutdatedDetail = Helaas ondersteunt deze versie van Firefox de webtechnologie die Firefox Send gebruikt niet. U dient uw browser bij te werken.
|
||||||
|
updateFirefox = Firefox bijwerken
|
||||||
|
downloadFirefoxButtonSub = Gratis download
|
||||||
|
uploadedFile = Bestand
|
||||||
|
copyFileList = URL kopiëren
|
||||||
|
// expiryFileList is used as a column header
|
||||||
|
expiryFileList = Verloopt over
|
||||||
|
deleteFileList = Verwijderen
|
||||||
|
nevermindButton = Maakt niet uit
|
||||||
|
legalHeader = Voorwaarden en privacy
|
||||||
|
legalNoticeTestPilot = Firefox Send is momenteel een Test Pilot-experiment en onderhevig aan de <a>Servicevoorwaarden</a> en <a>Privacyverklaring</a> van Test Pilot. <a>Hier</a> vindt u meer info over dit experiment en de gegevensverzameling ervan.
|
||||||
|
legalNoticeMozilla = Gebruik van de Firefox Send-website is ook onderhevig aan de <a>Privacyverklaring voor websites</a> en <a>Servicevoorwaarden voor websites</a> van Mozilla.
|
||||||
|
deletePopupText = Dit bestand verwijderen?
|
||||||
|
deletePopupYes = Ja
|
||||||
|
deletePopupCancel = Annuleren
|
||||||
|
deleteButtonHover
|
||||||
|
.title = Verwijderen
|
||||||
|
copyUrlHover
|
||||||
|
.title = URL kopiëren
|
||||||
|
footerLinkLegal = Juridisch
|
||||||
|
// Test Pilot is a proper name and should not be localized.
|
||||||
|
footerLinkAbout = Over Test Pilot
|
||||||
|
footerLinkPrivacy = Privacy
|
||||||
|
footerLinkTerms = Voorwaarden
|
||||||
|
footerLinkCookies = Cookies
|
||||||
94
public/locales/sr/send.ftl
Normal file
94
public/locales/sr/send.ftl
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
// Firefox Send is a brand name and should not be localized.
|
||||||
|
title = Firefox Send
|
||||||
|
siteSubtitle = веб експеримент
|
||||||
|
siteFeedback = Повратне информације
|
||||||
|
uploadPageHeader = Приватно и шифровано дељење датотека
|
||||||
|
uploadPageExplainer = Шаљите датотеке преко безбедне, приватне и шифроване везе која самостално истиче да ваше ствари не би остале на нету заувек.
|
||||||
|
uploadPageLearnMore = Сазнајте више
|
||||||
|
uploadPageDropMessage = Превуците ваше датотеке овде да бисте кренули са отпремањем
|
||||||
|
uploadPageSizeMessage = За бољи рад предлажемо да датотека не буде већа од 1GB
|
||||||
|
uploadPageBrowseButton = Изаберите датотеку на рачунару
|
||||||
|
.title = Изаберите датотеку на рачунару
|
||||||
|
uploadPageMultipleFilesAlert = Отпремање фасцикли или више датотека тренутно није подржано.
|
||||||
|
uploadPageBrowseButtonTitle = Отпреми датотеку
|
||||||
|
uploadingPageHeader = Ваша датотека се отпрема
|
||||||
|
importingFile = Увозим…
|
||||||
|
verifyingFile = Потврђујем…
|
||||||
|
encryptingFile = Шифрујем…
|
||||||
|
decryptingFile = Дешифрујем…
|
||||||
|
notifyUploadDone = Ваше отпремање је завршено.
|
||||||
|
uploadingPageMessage = Након што се ваша датотека отпреми, моћи ћете да подесите опције истека.
|
||||||
|
uploadingPageCancel = Откажи отпремање
|
||||||
|
.title = Откажи отпремање
|
||||||
|
uploadCancelNotification = Ваше отпремање је отказано.
|
||||||
|
uploadingPageLargeFileMessage = Ово је велика датотека и отпремање може потрајати. Будите стрпљиви!
|
||||||
|
uploadingFileNotification = Обавести ме када се отпремање заврши.
|
||||||
|
uploadSuccessConfirmHeader = Спреман за слање
|
||||||
|
uploadSvgAlt
|
||||||
|
.alt = Отпреми
|
||||||
|
uploadSuccessTimingHeader = Веза ка вашој датотеци ће истећи након једног преузимања или након 24 сата.
|
||||||
|
copyUrlFormLabelWithName = Ископирајте и поделите везу да бисте послали вашу датотеку: { $filename }
|
||||||
|
// Note: Title text for button should be the same.
|
||||||
|
copyUrlFormButton = Копирај у оставу
|
||||||
|
.title = Копирај у оставу
|
||||||
|
copiedUrl = Ископирано!
|
||||||
|
// Note: Title text for button should be the same.
|
||||||
|
deleteFileButton = Обриши датотеку
|
||||||
|
.title = Обриши датотеку
|
||||||
|
// Note: Title text for button should be the same.
|
||||||
|
sendAnotherFileLink = Пошаљи другу датотеку
|
||||||
|
.title = Пошаљи другу датотеку
|
||||||
|
// Alternative text used on the download link/button (indicates an action).
|
||||||
|
downloadAltText
|
||||||
|
.alt = Преузми
|
||||||
|
downloadFileName = Преузимање датотеке { $filename }
|
||||||
|
downloadFileSize = ({ $size })
|
||||||
|
// Firefox Send is a brand name and should not be localized.
|
||||||
|
downloadMessage = Ваш пријатељ вам је послао датотеку преко услуге Firefox Send која вам омогућава да делите датотеке преко безбедне, приватне и шифроване везе која самостално истиче да ваше ствари не би остале на нету заувек.
|
||||||
|
// Text and title used on the download link/button (indicates an action).
|
||||||
|
downloadButtonLabel = Преузми
|
||||||
|
.title = Преузми
|
||||||
|
downloadNotification = Ваше преузимање је завршено.
|
||||||
|
downloadFinish = Преузимање је завршено.
|
||||||
|
// Firefox Send is a brand name and should not be localized. Title text for button should be the same.
|
||||||
|
sendYourFilesLink = Испробајте Firefox Send
|
||||||
|
.title = Испробајте Firefox Send
|
||||||
|
downloadingPageProgress = Преузимам датотеку { $filename } ({ $size })
|
||||||
|
downloadingPageMessage = Оставите овај језичак отвореним док не добавимо вашу датотеку и док је не дешифрујемо.
|
||||||
|
errorAltText
|
||||||
|
.alt = Грешка при отпремању
|
||||||
|
errorPageHeader = Нешто је пошло наопако!
|
||||||
|
errorPageMessage = Догодила се грешка приликом отпремања датотеке.
|
||||||
|
errorPageLink = Пошаљи другу датотеку
|
||||||
|
fileTooBig = Та датотека је превелика за отпремање. Треба да буде мања од { $size }.
|
||||||
|
linkExpiredAlt
|
||||||
|
.alt = Веза је истекла
|
||||||
|
expiredPageHeader = Веза је или истекла, или никада није ни постојала!
|
||||||
|
notSupportedHeader = Ваш прегледач није подржан.
|
||||||
|
// Firefox Send is a brand name and should not be localized.
|
||||||
|
notSupportedDetail = Нажалост, овај прегледач не подржава веб технологију која омогућава Firefox Send. Мораћете да пробате са другим прегледачем. Ми предлажемо Firefox!
|
||||||
|
notSupportedOutdatedDetail = Нажалост, ово издање Firefox-a не подржава веб технологију која омогућава Firefox Send. Мораћете да ажурирате ваш прегледач.
|
||||||
|
updateFirefox = Ажурирај Firefox
|
||||||
|
downloadFirefoxButtonSub = Бесплатно преузимање
|
||||||
|
uploadedFile = Датотека
|
||||||
|
copyFileList = URL за копирање
|
||||||
|
// expiryFileList is used as a column header
|
||||||
|
expiryFileList = Истиче за
|
||||||
|
deleteFileList = Брисање
|
||||||
|
nevermindButton = Занемари
|
||||||
|
legalHeader = Услови и приватност
|
||||||
|
legalNoticeTestPilot = Firefox Send је тренутно Тест Пилот експеримент и подложан је <a>условима коришћења</a> Тест Пилота и <a>обавештењем о приватности</a>. Можете сазнати више о овом експерименту и о његовом сакупљању података <a>овде</a>.
|
||||||
|
legalNoticeMozilla = Коришћење Firefox Send веб сајта подлеже Mozilla-ином <a>обавештењу о приватности на веб сајтовима</a> и <a>условима коришћења веб сајтова</a>.
|
||||||
|
deletePopupText = Обрисати ову датотеку?
|
||||||
|
deletePopupYes = Да
|
||||||
|
deletePopupCancel = Откажи
|
||||||
|
deleteButtonHover
|
||||||
|
.title = Обриши
|
||||||
|
copyUrlHover
|
||||||
|
.title = Ископирај URL
|
||||||
|
footerLinkLegal = Правни подаци
|
||||||
|
// Test Pilot is a proper name and should not be localized.
|
||||||
|
footerLinkAbout = О Тест Пилоту
|
||||||
|
footerLinkPrivacy = Приватност
|
||||||
|
footerLinkTerms = Услови
|
||||||
|
footerLinkCookies = Колачићи
|
||||||
@@ -1,12 +1,8 @@
|
|||||||
/*** index.html ***/
|
/*** index.html ***/
|
||||||
html {
|
html {
|
||||||
background: url('resources/send_bg.svg');
|
background: url('resources/send_bg.svg');
|
||||||
font-family: -apple-system,
|
font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Text', Helvetica,
|
||||||
BlinkMacSystemFont,
|
Arial, sans-serif;
|
||||||
'SF Pro Text',
|
|
||||||
Helvetica,
|
|
||||||
Arial,
|
|
||||||
sans-serif;
|
|
||||||
font-weight: 200;
|
font-weight: 200;
|
||||||
background-size: 110%;
|
background-size: 110%;
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
@@ -39,6 +35,14 @@ body {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.send-logo h1 {
|
||||||
|
transition: color 50ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
.send-logo h1:hover {
|
||||||
|
color: #0297f8;
|
||||||
|
}
|
||||||
|
|
||||||
.send-logo > a {
|
.send-logo > a {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
@@ -67,7 +71,7 @@ body {
|
|||||||
transition: color 50ms;
|
transition: color 50ms;
|
||||||
}
|
}
|
||||||
|
|
||||||
.send-logo:hover a {
|
.site-subtitle a:hover {
|
||||||
color: #0297f8;
|
color: #0297f8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
6
scripts/.eslintrc.yml
Normal file
6
scripts/.eslintrc.yml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
rules:
|
||||||
|
node/shebang: off
|
||||||
|
security/detect-child-process: off
|
||||||
|
|
||||||
|
no-console: off
|
||||||
|
no-process-exit: off
|
||||||
49
scripts/get-prod-locales.js
Executable file
49
scripts/get-prod-locales.js
Executable file
@@ -0,0 +1,49 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
const cp = require('child_process');
|
||||||
|
const { promisify } = require('util');
|
||||||
|
const fs = require('fs');
|
||||||
|
const pkg = require('../package.json');
|
||||||
|
|
||||||
|
const availableLanguages = pkg.availableLanguages.sort();
|
||||||
|
const exec = promisify(cp.exec);
|
||||||
|
|
||||||
|
const arrayDiff = (current, package) =>
|
||||||
|
current.filter(locale => !package.includes(locale));
|
||||||
|
|
||||||
|
const cmd = 'compare-locales l10n.toml . `ls public/locales` --data=json';
|
||||||
|
|
||||||
|
exec(cmd)
|
||||||
|
.then(({ stdout }) => JSON.parse(stdout))
|
||||||
|
.then(({ summary }) => {
|
||||||
|
const locales = Object.keys(summary)
|
||||||
|
.filter(locale => {
|
||||||
|
const loc = summary[locale];
|
||||||
|
const hasMissing = loc.hasOwnProperty('missing');
|
||||||
|
const hasErrors = loc.hasOwnProperty('errors');
|
||||||
|
return !hasMissing && !hasErrors;
|
||||||
|
})
|
||||||
|
.sort();
|
||||||
|
|
||||||
|
if (locales.join(',') !== availableLanguages.join(',')) {
|
||||||
|
const missingLanguages = arrayDiff(locales, availableLanguages);
|
||||||
|
|
||||||
|
console.log('current 100%:', JSON.stringify(locales));
|
||||||
|
console.log('package.json:', JSON.stringify(availableLanguages));
|
||||||
|
console.log('missing prod:', JSON.stringify(missingLanguages));
|
||||||
|
|
||||||
|
if (process.argv.includes('--write')) {
|
||||||
|
const pkgPath = require.resolve('../package.json');
|
||||||
|
pkg.availableLanguages = locales;
|
||||||
|
const str = JSON.stringify(pkg, null, 2) + '\n';
|
||||||
|
console.log('Updating /package.json availableLanguages');
|
||||||
|
fs.writeFileSync(pkgPath, str, 'utf-8');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log('Production locales are up to date!');
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.error(err);
|
||||||
|
process.exit(1);
|
||||||
|
});
|
||||||
51
scripts/lint-locales.js
Normal file
51
scripts/lint-locales.js
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
const cp = require('child_process');
|
||||||
|
const { promisify } = require('util');
|
||||||
|
const pkg = require('../package.json');
|
||||||
|
const conf = require('../server/config');
|
||||||
|
|
||||||
|
const exec = promisify(cp.exec);
|
||||||
|
const cmd = `compare-locales l10n.toml . ${getLocales()} --data=json`;
|
||||||
|
|
||||||
|
console.log(cmd);
|
||||||
|
|
||||||
|
exec(cmd)
|
||||||
|
.then(({ stdout }) => JSON.parse(stdout))
|
||||||
|
.then(({ details }) => filterErrors(details))
|
||||||
|
.then(results => {
|
||||||
|
if (results.length) {
|
||||||
|
results.forEach(({ locale, data }) => {
|
||||||
|
console.log(locale);
|
||||||
|
data.forEach(msg => console.log(`- ${msg}`));
|
||||||
|
console.log('');
|
||||||
|
});
|
||||||
|
process.exit(2);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.error(err);
|
||||||
|
process.exit(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
function filterErrors(details) {
|
||||||
|
return Object.keys(details)
|
||||||
|
.sort()
|
||||||
|
.map(locale => {
|
||||||
|
const data = details[locale]
|
||||||
|
.filter(item => item.hasOwnProperty('error'))
|
||||||
|
.map(({ error }) => error);
|
||||||
|
return { locale, data };
|
||||||
|
})
|
||||||
|
.filter(({ data }) => data.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getLocales() {
|
||||||
|
// If we're in a "production" env (or passed the `--production` flag), only
|
||||||
|
// check the locales from the package.json file's `availableLanguages` array.
|
||||||
|
if (conf.env === 'production' || process.argv.includes('--production')) {
|
||||||
|
return pkg.availableLanguages.sort().join(' ');
|
||||||
|
}
|
||||||
|
// Lint all the locales.
|
||||||
|
return '`ls public/locales`';
|
||||||
|
}
|
||||||
@@ -14,7 +14,7 @@ const filename = path.join(__dirname, '..', 'public', 'version.json');
|
|||||||
const filedata = {
|
const filedata = {
|
||||||
commit,
|
commit,
|
||||||
source: pkg.homepage,
|
source: pkg.homepage,
|
||||||
version: process.env.CIRCLE_TAG || pkg.version
|
version: process.env.CIRCLE_TAG || `v${pkg.version}`
|
||||||
};
|
};
|
||||||
|
|
||||||
fs.writeFileSync(filename, JSON.stringify(filedata, null, 2) + '\n');
|
fs.writeFileSync(filename, JSON.stringify(filedata, null, 2) + '\n');
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ const storage = require('./storage.js');
|
|||||||
const Raven = require('raven');
|
const Raven = require('raven');
|
||||||
const crypto = require('crypto');
|
const crypto = require('crypto');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
|
const version = require('../public/version.json');
|
||||||
|
|
||||||
if (conf.sentry_dsn) {
|
if (conf.sentry_dsn) {
|
||||||
Raven.config(conf.sentry_dsn).install();
|
Raven.config(conf.sentry_dsn).install();
|
||||||
@@ -106,8 +107,10 @@ app.get('/legal', (req, res) => {
|
|||||||
app.get('/jsconfig.js', (req, res) => {
|
app.get('/jsconfig.js', (req, res) => {
|
||||||
res.set('Content-Type', 'application/javascript');
|
res.set('Content-Type', 'application/javascript');
|
||||||
res.render('jsconfig', {
|
res.render('jsconfig', {
|
||||||
trackerId: conf.analytics_id,
|
googleAnalyticsId: conf.analytics_id,
|
||||||
dsn: conf.sentry_id,
|
sentryId: conf.sentry_id,
|
||||||
|
version: version.version,
|
||||||
|
commit: version.commit,
|
||||||
maxFileSize: conf.max_file_size,
|
maxFileSize: conf.max_file_size,
|
||||||
expireSeconds: conf.expire_seconds,
|
expireSeconds: conf.expire_seconds,
|
||||||
layout: false
|
layout: false
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ window.Raven = {
|
|||||||
captureException: function(err) {
|
captureException: function(err) {
|
||||||
console.error(err, err.stack);
|
console.error(err, err.stack);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
window.FakeFile = FakeFile;
|
window.FakeFile = FakeFile;
|
||||||
window.FileSender = require('../../frontend/src/fileSender');
|
window.FileSender = require('../../frontend/src/fileSender');
|
||||||
|
|||||||
@@ -15,83 +15,84 @@ let originalBlob;
|
|||||||
|
|
||||||
describe('File Sender', function() {
|
describe('File Sender', function() {
|
||||||
before(function() {
|
before(function() {
|
||||||
server.respondImmediately = true;
|
server.respondImmediately = true;
|
||||||
server.respondWith(
|
server.respondWith('POST', '/upload', function(request) {
|
||||||
'POST',
|
const reader = new FileReader();
|
||||||
'/upload',
|
reader.readAsArrayBuffer(request.requestBody.get('data'));
|
||||||
function(request) {
|
|
||||||
const reader = new FileReader();
|
|
||||||
reader.readAsArrayBuffer(request.requestBody.get('data'));
|
|
||||||
|
|
||||||
reader.onload = function(event) {
|
reader.onload = function(event) {
|
||||||
file = this.result;
|
file = this.result;
|
||||||
}
|
};
|
||||||
|
|
||||||
const responseObj = JSON.parse(request.requestHeaders['X-File-Metadata']);
|
const responseObj = JSON.parse(request.requestHeaders['X-File-Metadata']);
|
||||||
request.respond(
|
request.respond(
|
||||||
200,
|
200,
|
||||||
{'Content-Type': 'application/json'},
|
{ 'Content-Type': 'application/json' },
|
||||||
JSON.stringify({url: 'some url',
|
JSON.stringify({
|
||||||
id: responseObj.id,
|
url: 'some url',
|
||||||
delete: responseObj.delete})
|
id: responseObj.id,
|
||||||
)
|
delete: responseObj.delete
|
||||||
}
|
})
|
||||||
)
|
);
|
||||||
})
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('Should get a loading event emission', function() {
|
it('Should get a loading event emission', function() {
|
||||||
const file = new FakeFile('hello_world.txt', ['This is some data.'])
|
const file = new FakeFile('hello_world.txt', ['This is some data.']);
|
||||||
const fs = new FileSender(file);
|
const fs = new FileSender(file);
|
||||||
let testLoading = true;
|
let testLoading = true;
|
||||||
|
|
||||||
fs.on('loading', isStillLoading => {
|
fs.on('loading', isStillLoading => {
|
||||||
assert(!(!testLoading && isStillLoading));
|
assert(!(!testLoading && isStillLoading));
|
||||||
testLoading = isStillLoading;
|
testLoading = isStillLoading;
|
||||||
|
});
|
||||||
|
|
||||||
|
return fs
|
||||||
|
.upload()
|
||||||
|
.then(info => {
|
||||||
|
assert(info);
|
||||||
|
assert(!testLoading);
|
||||||
})
|
})
|
||||||
|
.catch(err => {
|
||||||
return fs.upload()
|
console.log(err, err.stack);
|
||||||
.then(info => {
|
assert.fail();
|
||||||
assert(info);
|
});
|
||||||
assert(!testLoading);
|
});
|
||||||
})
|
|
||||||
.catch(err => {
|
|
||||||
console.log(err, err.stack);
|
|
||||||
assert.fail();
|
|
||||||
});
|
|
||||||
})
|
|
||||||
|
|
||||||
it('Should get a hashing event emission', function() {
|
it('Should get a hashing event emission', function() {
|
||||||
const file = new FakeFile('hello_world.txt', ['This is some data.'])
|
const file = new FakeFile('hello_world.txt', ['This is some data.']);
|
||||||
const fs = new FileSender(file);
|
const fs = new FileSender(file);
|
||||||
let testHashing = true;
|
let testHashing = true;
|
||||||
|
|
||||||
fs.on('hashing', isStillHashing => {
|
fs.on('hashing', isStillHashing => {
|
||||||
assert(!(!testHashing && isStillHashing));
|
assert(!(!testHashing && isStillHashing));
|
||||||
testHashing = isStillHashing;
|
testHashing = isStillHashing;
|
||||||
})
|
});
|
||||||
|
|
||||||
return fs.upload()
|
return fs
|
||||||
.then(info => {
|
.upload()
|
||||||
assert(info);
|
.then(info => {
|
||||||
assert(!testHashing);
|
assert(info);
|
||||||
})
|
assert(!testHashing);
|
||||||
.catch(err => {
|
})
|
||||||
console.log(err, err.stack);
|
.catch(err => {
|
||||||
assert.fail();
|
console.log(err, err.stack);
|
||||||
});
|
assert.fail();
|
||||||
})
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('Should get a encrypting event emission', function() {
|
it('Should get a encrypting event emission', function() {
|
||||||
const file = new FakeFile('hello_world.txt', ['This is some data.'])
|
const file = new FakeFile('hello_world.txt', ['This is some data.']);
|
||||||
const fs = new FileSender(file);
|
const fs = new FileSender(file);
|
||||||
let testEncrypting = true;
|
let testEncrypting = true;
|
||||||
|
|
||||||
fs.on('encrypting', isStillEncrypting => {
|
fs.on('encrypting', isStillEncrypting => {
|
||||||
assert(!(!testEncrypting && isStillEncrypting));
|
assert(!(!testEncrypting && isStillEncrypting));
|
||||||
testEncrypting = isStillEncrypting;
|
testEncrypting = isStillEncrypting;
|
||||||
})
|
});
|
||||||
|
|
||||||
return fs.upload()
|
return fs
|
||||||
|
.upload()
|
||||||
.then(info => {
|
.then(info => {
|
||||||
assert(info);
|
assert(info);
|
||||||
assert(!testEncrypting);
|
assert(!testEncrypting);
|
||||||
@@ -100,67 +101,68 @@ describe('File Sender', function() {
|
|||||||
console.log(err, err.stack);
|
console.log(err, err.stack);
|
||||||
assert.fail();
|
assert.fail();
|
||||||
});
|
});
|
||||||
})
|
});
|
||||||
|
|
||||||
it('Should encrypt a file properly', function(done) {
|
it('Should encrypt a file properly', function(done) {
|
||||||
const newFile = new FakeFile('hello_world.txt', ['This is some data.'])
|
const newFile = new FakeFile('hello_world.txt', ['This is some data.']);
|
||||||
const fs = new FileSender(newFile);
|
const fs = new FileSender(newFile);
|
||||||
fs.upload().then(info => {
|
fs.upload().then(info => {
|
||||||
const key = info.secretKey;
|
const key = info.secretKey;
|
||||||
secretKey = info.secretKey;
|
secretKey = info.secretKey;
|
||||||
const IV = info.fileId;
|
const IV = info.fileId;
|
||||||
encryptedIV = info.fileId;
|
encryptedIV = info.fileId;
|
||||||
|
|
||||||
const readRaw = new FileReader;
|
const readRaw = new FileReader();
|
||||||
readRaw.onload = function(event) {
|
readRaw.onload = function(event) {
|
||||||
const rawArray = new Uint8Array(this.result);
|
const rawArray = new Uint8Array(this.result);
|
||||||
originalBlob = rawArray;
|
originalBlob = rawArray;
|
||||||
|
|
||||||
window.crypto.subtle.digest('SHA-256', rawArray).then(hash => {
|
window.crypto.subtle.digest('SHA-256', rawArray).then(hash => {
|
||||||
fileHash = hash;
|
fileHash = hash;
|
||||||
window.crypto.subtle.importKey(
|
window.crypto.subtle
|
||||||
'jwk',
|
.importKey(
|
||||||
{
|
'jwk',
|
||||||
kty: 'oct',
|
|
||||||
k: key,
|
|
||||||
alg: 'A128GCM',
|
|
||||||
ext: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'AES-GCM'
|
|
||||||
},
|
|
||||||
true,
|
|
||||||
['encrypt', 'decrypt']
|
|
||||||
)
|
|
||||||
.then(cryptoKey => {
|
|
||||||
window.crypto.subtle.encrypt(
|
|
||||||
{
|
{
|
||||||
name: 'AES-GCM',
|
kty: 'oct',
|
||||||
iv: hexToArray(IV),
|
k: key,
|
||||||
additionalData: hash,
|
alg: 'A128GCM',
|
||||||
tagLength: 128
|
ext: true
|
||||||
},
|
},
|
||||||
cryptoKey,
|
{
|
||||||
rawArray
|
name: 'AES-GCM'
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
['encrypt', 'decrypt']
|
||||||
)
|
)
|
||||||
.then(encrypted => {
|
.then(cryptoKey => {
|
||||||
assert(new Uint8Array(encrypted).toString() ===
|
window.crypto.subtle
|
||||||
new Uint8Array(file).toString());
|
.encrypt(
|
||||||
done();
|
{
|
||||||
})
|
name: 'AES-GCM',
|
||||||
})
|
iv: hexToArray(IV),
|
||||||
})
|
additionalData: hash,
|
||||||
|
tagLength: 128
|
||||||
}
|
},
|
||||||
|
cryptoKey,
|
||||||
|
rawArray
|
||||||
|
)
|
||||||
|
.then(encrypted => {
|
||||||
|
assert(
|
||||||
|
new Uint8Array(encrypted).toString() ===
|
||||||
|
new Uint8Array(file).toString()
|
||||||
|
);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
readRaw.readAsArrayBuffer(newFile);
|
readRaw.readAsArrayBuffer(newFile);
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('File Receiver', function() {
|
describe('File Receiver', function() {
|
||||||
|
|
||||||
class FakeXHR {
|
class FakeXHR {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.response = file;
|
this.response = file;
|
||||||
@@ -169,19 +171,19 @@ describe('File Receiver', function() {
|
|||||||
|
|
||||||
static setup() {
|
static setup() {
|
||||||
FakeXHR.prototype.open = sinon.spy();
|
FakeXHR.prototype.open = sinon.spy();
|
||||||
FakeXHR.prototype.send = function () {
|
FakeXHR.prototype.send = function() {
|
||||||
this.onload();
|
this.onload();
|
||||||
}
|
};
|
||||||
|
|
||||||
FakeXHR.prototype.originalXHR = window.XMLHttpRequest;
|
FakeXHR.prototype.originalXHR = window.XMLHttpRequest;
|
||||||
|
|
||||||
FakeXHR.prototype.getResponseHeader = function () {
|
FakeXHR.prototype.getResponseHeader = function() {
|
||||||
return JSON.stringify({
|
return JSON.stringify({
|
||||||
aad: arrayToHex(new Uint8Array(fileHash)),
|
aad: arrayToHex(new Uint8Array(fileHash)),
|
||||||
filename: 'hello_world.txt',
|
filename: 'hello_world.txt',
|
||||||
id: encryptedIV
|
id: encryptedIV
|
||||||
})
|
});
|
||||||
}
|
};
|
||||||
window.XMLHttpRequest = FakeXHR;
|
window.XMLHttpRequest = FakeXHR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,38 +193,47 @@ describe('File Receiver', function() {
|
|||||||
window.XMLHttpRequest.prototype.originalXHR.restore();
|
window.XMLHttpRequest.prototype.originalXHR.restore();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const cb = function(done) {
|
const cb = function(done) {
|
||||||
if (file === undefined ||
|
if (
|
||||||
encryptedIV === undefined ||
|
file === undefined ||
|
||||||
fileHash === undefined ||
|
encryptedIV === undefined ||
|
||||||
secretKey === undefined) {
|
fileHash === undefined ||
|
||||||
assert.fail('Please run file sending tests before trying to receive the files.');
|
secretKey === undefined
|
||||||
|
) {
|
||||||
|
assert.fail(
|
||||||
|
'Please run file sending tests before trying to receive the files.'
|
||||||
|
);
|
||||||
done();
|
done();
|
||||||
}
|
}
|
||||||
|
|
||||||
FakeXHR.setup();
|
FakeXHR.setup();
|
||||||
done();
|
done();
|
||||||
}
|
};
|
||||||
|
|
||||||
before(cb)
|
before(cb);
|
||||||
|
|
||||||
after(function() {
|
after(function() {
|
||||||
FakeXHR.restore();
|
FakeXHR.restore();
|
||||||
})
|
});
|
||||||
|
|
||||||
it('Should decrypt properly', function() {
|
it('Should decrypt properly', function() {
|
||||||
const fr = new FileReceiver();
|
const fr = new FileReceiver();
|
||||||
location.hash = secretKey;
|
location.hash = secretKey;
|
||||||
return fr.download().then(([decrypted, name]) => {
|
return fr
|
||||||
assert(name);
|
.download()
|
||||||
assert(new Uint8Array(decrypted).toString() ===
|
.then(([decrypted, name]) => {
|
||||||
new Uint8Array(originalBlob).toString())
|
assert(name);
|
||||||
}).catch(err => {
|
assert(
|
||||||
console.log(err, err.stack);
|
new Uint8Array(decrypted).toString() ===
|
||||||
assert.fail();
|
new Uint8Array(originalBlob).toString()
|
||||||
})
|
);
|
||||||
})
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.log(err, err.stack);
|
||||||
|
assert.fail();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('Should emit decrypting events', function() {
|
it('Should emit decrypting events', function() {
|
||||||
const fr = new FileReceiver();
|
const fr = new FileReceiver();
|
||||||
@@ -237,17 +248,20 @@ describe('File Receiver', function() {
|
|||||||
|
|
||||||
fr.on('safe', isSafe => {
|
fr.on('safe', isSafe => {
|
||||||
assert(isSafe);
|
assert(isSafe);
|
||||||
})
|
});
|
||||||
|
|
||||||
return fr.download().then(([decrypted, name]) => {
|
return fr
|
||||||
assert(decrypted);
|
.download()
|
||||||
assert(name);
|
.then(([decrypted, name]) => {
|
||||||
assert(!testDecrypting);
|
assert(decrypted);
|
||||||
}).catch(err => {
|
assert(name);
|
||||||
console.log(err, err.stack);
|
assert(!testDecrypting);
|
||||||
assert.fail();
|
})
|
||||||
})
|
.catch(err => {
|
||||||
})
|
console.log(err, err.stack);
|
||||||
|
assert.fail();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('Should emit hashing events', function() {
|
it('Should emit hashing events', function() {
|
||||||
const fr = new FileReceiver();
|
const fr = new FileReceiver();
|
||||||
@@ -262,99 +276,109 @@ describe('File Receiver', function() {
|
|||||||
|
|
||||||
fr.on('safe', isSafe => {
|
fr.on('safe', isSafe => {
|
||||||
assert(isSafe);
|
assert(isSafe);
|
||||||
})
|
});
|
||||||
|
|
||||||
return fr.download().then(([decrypted, name]) => {
|
return fr
|
||||||
assert(decrypted);
|
.download()
|
||||||
assert(name);
|
.then(([decrypted, name]) => {
|
||||||
assert(!testHashing);
|
assert(decrypted);
|
||||||
}).catch(err => {
|
assert(name);
|
||||||
assert.fail();
|
assert(!testHashing);
|
||||||
})
|
})
|
||||||
})
|
.catch(err => {
|
||||||
|
assert.fail();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('Should catch fraudulent checksums', function(done) {
|
it('Should catch fraudulent checksums', function(done) {
|
||||||
// Use the secret key and file hash of the previous file to encrypt,
|
// Use the secret key and file hash of the previous file to encrypt,
|
||||||
// which has a different hash than this one (different strings).
|
// which has a different hash than this one (different strings).
|
||||||
const newFile = new FakeFile('hello_world.txt',
|
const newFile = new FakeFile('hello_world.txt', [
|
||||||
['This is some data, with a changed hash.'])
|
'This is some data, with a changed hash.'
|
||||||
|
]);
|
||||||
const readRaw = new FileReader();
|
const readRaw = new FileReader();
|
||||||
|
|
||||||
readRaw.onload = function(event) {
|
readRaw.onload = function(event) {
|
||||||
const plaintext = new Uint8Array(this.result);
|
const plaintext = new Uint8Array(this.result);
|
||||||
window.crypto.subtle.importKey(
|
window.crypto.subtle
|
||||||
'jwk',
|
.importKey(
|
||||||
{
|
'jwk',
|
||||||
kty: 'oct',
|
|
||||||
k: secretKey,
|
|
||||||
alg: 'A128GCM',
|
|
||||||
ext: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'AES-GCM'
|
|
||||||
},
|
|
||||||
true,
|
|
||||||
['encrypt', 'decrypt']
|
|
||||||
)
|
|
||||||
.then(key => {
|
|
||||||
// The file hash used here is the hash of the fake
|
|
||||||
// file from the previous test; it's a phony checksum.
|
|
||||||
return window.crypto.subtle.encrypt(
|
|
||||||
{
|
{
|
||||||
name: 'AES-GCM',
|
kty: 'oct',
|
||||||
iv: hexToArray(encryptedIV),
|
k: secretKey,
|
||||||
additionalData: fileHash,
|
alg: 'A128GCM',
|
||||||
tagLength: 128
|
ext: true
|
||||||
},
|
},
|
||||||
key,
|
{
|
||||||
plaintext
|
name: 'AES-GCM'
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
['encrypt', 'decrypt']
|
||||||
)
|
)
|
||||||
})
|
.then(key => {
|
||||||
.then(encrypted => {
|
// The file hash used here is the hash of the fake
|
||||||
file = encrypted;
|
// file from the previous test; it's a phony checksum.
|
||||||
const fr = new FileReceiver();
|
return window.crypto.subtle.encrypt(
|
||||||
location.hash = secretKey;
|
{
|
||||||
|
name: 'AES-GCM',
|
||||||
fr.on('unsafe', isUnsafe => {
|
iv: hexToArray(encryptedIV),
|
||||||
assert(isUnsafe)
|
additionalData: fileHash,
|
||||||
|
tagLength: 128
|
||||||
|
},
|
||||||
|
key,
|
||||||
|
plaintext
|
||||||
|
);
|
||||||
})
|
})
|
||||||
|
.then(encrypted => {
|
||||||
|
file = encrypted;
|
||||||
|
const fr = new FileReceiver();
|
||||||
|
location.hash = secretKey;
|
||||||
|
|
||||||
fr.on('safe', () => {
|
fr.on('unsafe', isUnsafe => {
|
||||||
// This event should not be emitted.
|
assert(isUnsafe);
|
||||||
assert.fail();
|
});
|
||||||
})
|
|
||||||
|
|
||||||
fr.download().then(() => {
|
fr.on('safe', () => {
|
||||||
assert.fail();
|
// This event should not be emitted.
|
||||||
done();
|
assert.fail();
|
||||||
}).catch(err => {
|
});
|
||||||
assert(1);
|
|
||||||
done();
|
fr
|
||||||
})
|
.download()
|
||||||
})
|
.then(() => {
|
||||||
}
|
assert.fail();
|
||||||
|
done();
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
assert(1);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
readRaw.readAsArrayBuffer(newFile);
|
readRaw.readAsArrayBuffer(newFile);
|
||||||
})
|
});
|
||||||
|
|
||||||
it('Should not decrypt with an incorrect checksum', function() {
|
it('Should not decrypt with an incorrect checksum', function() {
|
||||||
FakeXHR.prototype.getResponseHeader = function () {
|
FakeXHR.prototype.getResponseHeader = function() {
|
||||||
return JSON.stringify({
|
return JSON.stringify({
|
||||||
aad: 'some_bad_hashz',
|
aad: 'some_bad_hashz',
|
||||||
filename: 'hello_world.txt',
|
filename: 'hello_world.txt',
|
||||||
id: encryptedIV
|
id: encryptedIV
|
||||||
})
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
const fr = new FileReceiver();
|
const fr = new FileReceiver();
|
||||||
location.hash = secretKey;
|
location.hash = secretKey;
|
||||||
|
|
||||||
return fr.download().then(([decrypted, name]) => {
|
return fr
|
||||||
assert(decrypted);
|
.download()
|
||||||
assert(name);
|
.then(([decrypted, name]) => {
|
||||||
assert.fail();
|
assert(decrypted);
|
||||||
}).catch(err => {
|
assert(name);
|
||||||
assert(1);
|
assert.fail();
|
||||||
})
|
})
|
||||||
})
|
.catch(err => {
|
||||||
|
assert(1);
|
||||||
})
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ const proxyquire = require('proxyquire');
|
|||||||
const request = require('supertest');
|
const request = require('supertest');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
|
|
||||||
|
|
||||||
const logStub = {};
|
const logStub = {};
|
||||||
logStub.info = sinon.stub();
|
logStub.info = sinon.stub();
|
||||||
logStub.error = sinon.stub();
|
logStub.error = sinon.stub();
|
||||||
@@ -38,17 +37,21 @@ describe('Server integration tests', function() {
|
|||||||
storage.flushall();
|
storage.flushall();
|
||||||
storage.quit();
|
storage.quit();
|
||||||
server.close();
|
server.close();
|
||||||
})
|
});
|
||||||
|
|
||||||
function upload() {
|
function upload() {
|
||||||
return request(server).post('/upload')
|
return request(server)
|
||||||
.field('fname', 'test_upload.txt')
|
.post('/upload')
|
||||||
.set('X-File-Metadata', JSON.stringify({
|
.field('fname', 'test_upload.txt')
|
||||||
aad: '11111',
|
.set(
|
||||||
id: '111111111111111111111111',
|
'X-File-Metadata',
|
||||||
filename: 'test_upload.txt'
|
JSON.stringify({
|
||||||
}))
|
aad: '11111',
|
||||||
.attach('file', './test/test_upload.txt')
|
id: '111111111111111111111111',
|
||||||
|
filename: 'test_upload.txt'
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.attach('file', './test/test_upload.txt');
|
||||||
}
|
}
|
||||||
|
|
||||||
it('Responds with a 200 when the service is up', function() {
|
it('Responds with a 200 when the service is up', function() {
|
||||||
@@ -56,115 +59,123 @@ describe('Server integration tests', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Rejects with a 404 when a file id is not valid', function() {
|
it('Rejects with a 404 when a file id is not valid', function() {
|
||||||
return request(server).post('/upload/123')
|
return request(server)
|
||||||
.field('fname', 'test_upload.txt')
|
.post('/upload/123')
|
||||||
.set('X-File-Metadata', JSON.stringify({
|
.field('fname', 'test_upload.txt')
|
||||||
'silly': 'text'
|
.set(
|
||||||
}))
|
'X-File-Metadata',
|
||||||
.attach('file', './test/test_upload.txt')
|
JSON.stringify({
|
||||||
.expect(404)
|
silly: 'text'
|
||||||
})
|
})
|
||||||
|
)
|
||||||
|
.attach('file', './test/test_upload.txt')
|
||||||
|
.expect(404);
|
||||||
|
});
|
||||||
|
|
||||||
it('Accepts a file and stores it when properly uploaded', function(done) {
|
it('Accepts a file and stores it when properly uploaded', function(done) {
|
||||||
upload().then(res => {
|
upload().then(res => {
|
||||||
assert(res.body.hasOwnProperty('delete'));
|
assert(res.body.hasOwnProperty('delete'));
|
||||||
uuid = res.body.delete;
|
uuid = res.body.delete;
|
||||||
assert(res.body.hasOwnProperty('url'));
|
assert(res.body.hasOwnProperty('url'));
|
||||||
assert(res.body.hasOwnProperty('id'));
|
assert(res.body.hasOwnProperty('id'));
|
||||||
fileId = res.body.id;
|
fileId = res.body.id;
|
||||||
fs.access('./static/' + fileId, fs.constants.F_OK, err => {
|
fs.access('./static/' + fileId, fs.constants.F_OK, err => {
|
||||||
if (err) {
|
if (err) {
|
||||||
done(new Error('The file does not exist'));
|
done(new Error('The file does not exist'));
|
||||||
} else {
|
} else {
|
||||||
done();
|
done();
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
|
|
||||||
it('Responds with a 200 if a file exists', function() {
|
it('Responds with a 200 if a file exists', function() {
|
||||||
return request(server).get('/exists/' + fileId)
|
return request(server).get('/exists/' + fileId).expect(200);
|
||||||
.expect(200)
|
});
|
||||||
})
|
|
||||||
|
|
||||||
it('Exists in the redis server', function() {
|
it('Exists in the redis server', function() {
|
||||||
return storage.exists(fileId)
|
return storage
|
||||||
.then(() => assert(1))
|
.exists(fileId)
|
||||||
.catch(err => assert.fail())
|
.then(() => assert(1))
|
||||||
})
|
.catch(err => assert.fail());
|
||||||
|
});
|
||||||
|
|
||||||
it('Fails delete if the delete token does not match', function() {
|
it('Fails delete if the delete token does not match', function() {
|
||||||
return request(server).post('/delete/' + fileId)
|
return request(server)
|
||||||
.send({ delete_token: 11 })
|
.post('/delete/' + fileId)
|
||||||
.expect(404);
|
.send({ delete_token: 11 })
|
||||||
})
|
.expect(404);
|
||||||
|
});
|
||||||
|
|
||||||
it('Fails delete if the id is invalid', function() {
|
it('Fails delete if the id is invalid', function() {
|
||||||
return request(server).post('/delete/1')
|
return request(server).post('/delete/1').expect(404);
|
||||||
.expect(404);
|
});
|
||||||
})
|
|
||||||
|
|
||||||
it('Successfully deletes if the id is valid and the delete token matches', function(done) {
|
it('Successfully deletes if the id is valid and the delete token matches', function(
|
||||||
request(server).post('/delete/' + fileId)
|
done
|
||||||
.send({ delete_token: uuid })
|
) {
|
||||||
.expect(200)
|
request(server)
|
||||||
.then(() => {
|
.post('/delete/' + fileId)
|
||||||
fs.access('./static/' + fileId, fs.constants.F_OK, err => {
|
.send({ delete_token: uuid })
|
||||||
if (err) {
|
.expect(200)
|
||||||
done();
|
.then(() => {
|
||||||
} else {
|
fs.access('./static/' + fileId, fs.constants.F_OK, err => {
|
||||||
done(new Error('The file does not exist'));
|
if (err) {
|
||||||
}
|
done();
|
||||||
})
|
} else {
|
||||||
})
|
done(new Error('The file does not exist'));
|
||||||
})
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('Responds with a 404 if a file does not exist', function() {
|
it('Responds with a 404 if a file does not exist', function() {
|
||||||
return request(server).get('/exists/notfound')
|
return request(server).get('/exists/notfound').expect(404);
|
||||||
.expect(404)
|
});
|
||||||
})
|
|
||||||
|
|
||||||
it('Uploads properly after a delete', function(done) {
|
it('Uploads properly after a delete', function(done) {
|
||||||
upload().then(res => {
|
upload().then(res => {
|
||||||
assert(res.body.hasOwnProperty('delete'));
|
assert(res.body.hasOwnProperty('delete'));
|
||||||
uuid = res.body.delete;
|
uuid = res.body.delete;
|
||||||
assert(res.body.hasOwnProperty('url'));
|
assert(res.body.hasOwnProperty('url'));
|
||||||
assert(res.body.hasOwnProperty('id'));
|
assert(res.body.hasOwnProperty('id'));
|
||||||
fileId = res.body.id;
|
fileId = res.body.id;
|
||||||
fs.access('./static/' + fileId, fs.constants.F_OK, err => {
|
fs.access('./static/' + fileId, fs.constants.F_OK, err => {
|
||||||
if (err) {
|
if (err) {
|
||||||
done(new Error('The file does not exist'));
|
done(new Error('The file does not exist'));
|
||||||
} else {
|
} else {
|
||||||
done();
|
done();
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
|
|
||||||
it('Responds with a 200 for the download page', function() {
|
it('Responds with a 200 for the download page', function() {
|
||||||
return request(server).get('/download/' + fileId)
|
return request(server).get('/download/' + fileId).expect(200);
|
||||||
.expect(200);
|
});
|
||||||
})
|
|
||||||
|
|
||||||
it('Downloads a file properly', function() {
|
it('Downloads a file properly', function() {
|
||||||
return request(server).get('/assets/download/' + fileId)
|
return request(server).get('/assets/download/' + fileId).then(res => {
|
||||||
.then(res => {
|
assert(res.header.hasOwnProperty('content-disposition'));
|
||||||
assert(res.header.hasOwnProperty('content-disposition'));
|
assert(res.header.hasOwnProperty('content-type'));
|
||||||
assert(res.header.hasOwnProperty('content-type'))
|
assert(res.header.hasOwnProperty('content-length'));
|
||||||
assert(res.header.hasOwnProperty('content-length'))
|
assert(res.header.hasOwnProperty('x-file-metadata'));
|
||||||
assert(res.header.hasOwnProperty('x-file-metadata'))
|
assert.equal(
|
||||||
assert.equal(res.header['content-disposition'], 'attachment; filename=test_upload.txt')
|
res.header['content-disposition'],
|
||||||
assert.equal(res.header['content-type'], 'application/octet-stream')
|
'attachment; filename=test_upload.txt'
|
||||||
})
|
);
|
||||||
})
|
assert.equal(res.header['content-type'], 'application/octet-stream');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('The file is deleted after one download', function() {
|
it('The file is deleted after one download', function() {
|
||||||
assert(!fs.existsSync('./static/' + fileId));
|
assert(!fs.existsSync('./static/' + fileId));
|
||||||
})
|
});
|
||||||
|
|
||||||
it('No longer exists in the redis server', function() {
|
it('No longer exists in the redis server', function() {
|
||||||
return storage.exists(fileId)
|
return storage
|
||||||
.then(() => assert.fail())
|
.exists(fileId)
|
||||||
.catch(err => assert(1))
|
.then(() => assert.fail())
|
||||||
})
|
.catch(err => assert(1));
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -110,9 +110,9 @@ describe('Testing Set using aws', function() {
|
|||||||
it('Should pass when the file is successfully uploaded', function() {
|
it('Should pass when the file is successfully uploaded', function() {
|
||||||
const buf = Buffer.alloc(10);
|
const buf = Buffer.alloc(10);
|
||||||
sinon.stub(crypto, 'randomBytes').returns(buf);
|
sinon.stub(crypto, 'randomBytes').returns(buf);
|
||||||
s3Stub.upload.returns({promise: () => Promise.resolve()});
|
s3Stub.upload.returns({ promise: () => Promise.resolve() });
|
||||||
return storage
|
return storage
|
||||||
.set('123', {on: sinon.stub()}, 'Filename.moz', {})
|
.set('123', { on: sinon.stub() }, 'Filename.moz', {})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
assert(expire.calledOnce);
|
assert(expire.calledOnce);
|
||||||
assert(expire.calledWith('123', 86400));
|
assert(expire.calledWith('123', 86400));
|
||||||
@@ -121,9 +121,9 @@ describe('Testing Set using aws', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Should fail if there was an error during uploading', function() {
|
it('Should fail if there was an error during uploading', function() {
|
||||||
s3Stub.upload.returns({promise: () => Promise.reject()});
|
s3Stub.upload.returns({ promise: () => Promise.reject() });
|
||||||
return storage
|
return storage
|
||||||
.set('123', {on: sinon.stub()}, 'Filename.moz', 'url.com')
|
.set('123', { on: sinon.stub() }, 'Filename.moz', 'url.com')
|
||||||
.then(_reply => assert.fail())
|
.then(_reply => assert.fail())
|
||||||
.catch(err => assert(1));
|
.catch(err => assert(1));
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -35,5 +35,5 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<a class="send-new" data-l10n-id="sendYourFilesLink"></a>
|
<a class="send-new" data-l10n-id="sendYourFilesLink" target="_blank"></a>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -5,11 +5,24 @@ if (isIE && !isUnsupportedPage) {
|
|||||||
window.location.replace('/unsupported/ie');
|
window.location.replace('/unsupported/ie');
|
||||||
}
|
}
|
||||||
|
|
||||||
{{#if dsn}}
|
{{#if sentryId}}
|
||||||
window.dsn = '{{{dsn}}}';
|
var RAVEN_CONFIG = {
|
||||||
|
release: '{{{version}}}',
|
||||||
|
tags: {
|
||||||
|
commit: '{{{commit}}}'
|
||||||
|
},
|
||||||
|
dataCallback: function (data) {
|
||||||
|
var hash = window.location.hash;
|
||||||
|
if (hash) {
|
||||||
|
return JSON.parse(JSON.stringify(data).replace(new RegExp(hash.slice(1), 'g'), ''));
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var SENTRY_ID = '{{{sentryId}}}';
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#if trackerId}}
|
{{#if googleAnalyticsId}}
|
||||||
window.trackerId = '{{{trackerId}}}';
|
var GOOGLE_ANALYTICS_ID = '{{{googleAnalyticsId}}}';
|
||||||
{{/if}}
|
{{/if}}
|
||||||
var MAXFILESIZE = {{{maxFileSize}}};
|
var MAXFILESIZE = {{{maxFileSize}}};
|
||||||
var EXPIRE_SECONDS = {{{expireSeconds}}};
|
var EXPIRE_SECONDS = {{{expireSeconds}}};
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
<link rel="icon" type="image/png" href="/resources/favicon-32x32.png" sizes="32x32" />
|
<link rel="icon" type="image/png" href="/resources/favicon-32x32.png" sizes="32x32" />
|
||||||
<link rel="localization" href="/locales/{locale}/send.ftl">
|
<link rel="localization" href="/locales/{locale}/send.ftl">
|
||||||
|
<script src="/polyfill.min.js"></script>
|
||||||
<script defer src="/l20n.min.js"></script>
|
<script defer src="/l20n.min.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|||||||
Reference in New Issue
Block a user