mirror of
https://gitlab.com/timvisee/send.git
synced 2025-12-06 22:20:55 +03:00
Compare commits
58 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ea1ea2aa68 | ||
|
|
90d06d71d3 | ||
|
|
11f2deb7a6 | ||
|
|
0f5edf023a | ||
|
|
3be0621647 | ||
|
|
fc07bfdb85 | ||
|
|
581a989304 | ||
|
|
047d6a85ab | ||
|
|
90f6a07d4a | ||
|
|
8f4a53db64 | ||
|
|
c2dd51c638 | ||
|
|
cdd98af86a | ||
|
|
883f2bc0f9 | ||
|
|
94f1eabbc7 | ||
|
|
902bc6628e | ||
|
|
460b741f17 | ||
|
|
d5c488196d | ||
|
|
9ad9c9feb2 | ||
|
|
6576e4a74c | ||
|
|
950872109e | ||
|
|
87051d27ed | ||
|
|
3451803b37 | ||
|
|
ac15153e8f | ||
|
|
924f5dc682 | ||
|
|
ff9be6a213 | ||
|
|
883728570e | ||
|
|
0435f17f9a | ||
|
|
1e1268fff0 | ||
|
|
252d7817e3 | ||
|
|
ce28c38ebe | ||
|
|
f0407f9beb | ||
|
|
c6f222eb57 | ||
|
|
6dd6135185 | ||
|
|
8df339b66d | ||
|
|
8702fda651 | ||
|
|
807ecff471 | ||
|
|
927c981cd7 | ||
|
|
7073cc8ce6 | ||
|
|
c925fae696 | ||
|
|
966d7a5e35 | ||
|
|
96c750c098 | ||
|
|
0729064753 | ||
|
|
259a5a5f24 | ||
|
|
27be72e0cd | ||
|
|
e4231bbc0f | ||
|
|
1d184f06bf | ||
|
|
f7b46a99ac | ||
|
|
3fadb489c7 | ||
|
|
6378676c2d | ||
|
|
014d84e4c7 | ||
|
|
a08d8435a9 | ||
|
|
40a05c9ecf | ||
|
|
527040afef | ||
|
|
a48a447808 | ||
|
|
f3569d7f98 | ||
|
|
6ca7d11efb | ||
|
|
b71ae4a0ff | ||
|
|
7ba25664b5 |
@@ -1,10 +1,8 @@
|
||||
node_modules
|
||||
.git
|
||||
.tox
|
||||
.DS_Store
|
||||
firefox
|
||||
assets
|
||||
docs
|
||||
test
|
||||
coverage
|
||||
.circleci
|
||||
.nyc_output
|
||||
.vscode
|
||||
.DS_Store
|
||||
coverage
|
||||
docs
|
||||
firefox
|
||||
node_modules
|
||||
61
Dockerfile
61
Dockerfile
@@ -1,18 +1,59 @@
|
||||
FROM node:10 AS builder
|
||||
RUN addgroup --gid 10001 app && adduser --disabled-password --gecos '' --gid 10001 --home /app --uid 10001 app
|
||||
COPY package*.json /app/
|
||||
WORKDIR /app
|
||||
RUN npm install --production
|
||||
##
|
||||
# Firefox Send - Mozilla
|
||||
#
|
||||
# License https://github.com/mozilla/send/blob/master/LICENSE
|
||||
##
|
||||
|
||||
FROM node:10-slim
|
||||
RUN addgroup --gid 10001 app && adduser --disabled-password --gecos '' --gid 10001 --home /app --uid 10001 app
|
||||
|
||||
# Build project
|
||||
FROM node:10 AS builder
|
||||
RUN set -x \
|
||||
# Add user
|
||||
&& addgroup --gid 10001 app \
|
||||
&& adduser --disabled-password \
|
||||
--gecos '' \
|
||||
--gid 10001 \
|
||||
--home /app \
|
||||
--uid 10001 \
|
||||
app
|
||||
COPY --chown=app:app . /app
|
||||
USER app
|
||||
WORKDIR /app
|
||||
COPY --chown=app:app --from=builder /app .
|
||||
COPY --chown=app:app . .
|
||||
RUN ls -la
|
||||
RUN set -x \
|
||||
# Build
|
||||
&& npm ci \
|
||||
&& npm run build
|
||||
|
||||
|
||||
# Main image
|
||||
FROM node:10-slim
|
||||
RUN set -x \
|
||||
# Add user
|
||||
&& addgroup --gid 10001 app \
|
||||
&& adduser --disabled-password \
|
||||
--gecos '' \
|
||||
--gid 10001 \
|
||||
--home /app \
|
||||
--uid 10001 \
|
||||
app
|
||||
RUN apt-get update && apt-get -y install git-core
|
||||
USER app
|
||||
WORKDIR /app
|
||||
COPY --chown=app:app package*.json ./
|
||||
COPY --chown=app:app app app
|
||||
COPY --chown=app:app common common
|
||||
COPY --chown=app:app public/locales public/locales
|
||||
COPY --chown=app:app server server
|
||||
COPY --chown=app:app --from=builder /app/dist dist
|
||||
|
||||
RUN ls -la
|
||||
RUN npm ci --production && npm cache clean --force
|
||||
RUN mkdir -p /app/.config/configstore
|
||||
RUN ln -s dist/version.json version.json
|
||||
|
||||
ENV PORT=1443
|
||||
EXPOSE $PORT
|
||||
|
||||
EXPOSE ${PORT}
|
||||
|
||||
CMD ["node", "server/bin/prod.js"]
|
||||
|
||||
@@ -30,7 +30,7 @@ A file sharing experiment which allows you to send encrypted files to other user
|
||||
|
||||
## Requirements
|
||||
|
||||
- [Node.js 10.0+](https://nodejs.org/)
|
||||
- [Node.js 10.x](https://nodejs.org/)
|
||||
- [Redis server](https://redis.io/) (optional for development)
|
||||
- [AWS S3](https://aws.amazon.com/s3/) or compatible service. (optional)
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import 'intl-pluralrules';
|
||||
import choo from 'choo';
|
||||
import html from 'choo/html';
|
||||
import Raven from 'raven-js';
|
||||
import * as Sentry from '@sentry/browser';
|
||||
|
||||
import { setApiUrlPrefix, getConstants } from '../app/api';
|
||||
import metrics from '../app/metrics';
|
||||
@@ -82,7 +82,7 @@ function body(main) {
|
||||
state.archive = new Archive([], DEFAULTS.EXPIRE_SECONDS);
|
||||
state.storage = storage;
|
||||
state.user = new User(storage, LIMITS);
|
||||
state.raven = Raven;
|
||||
state.sentry = Sentry;
|
||||
});
|
||||
app.use(metrics);
|
||||
app.route('/', body(home));
|
||||
|
||||
@@ -12,7 +12,7 @@ export default function initialState(state, emitter) {
|
||||
getAsset(name) {
|
||||
return `${state.prefix}/${name}`;
|
||||
},
|
||||
raven: {
|
||||
sentry: {
|
||||
captureException: e => {
|
||||
console.error('ERROR ' + e + ' ' + e.stack);
|
||||
}
|
||||
|
||||
72
app/api.js
72
app/api.js
@@ -11,6 +11,15 @@ if (!fileProtocolWssUrl) {
|
||||
fileProtocolWssUrl = 'wss://send.firefox.com/api/ws';
|
||||
}
|
||||
|
||||
export class ConnectionError extends Error {
|
||||
constructor(cancelled, duration, size) {
|
||||
super(cancelled ? '0' : 'connection closed');
|
||||
this.cancelled = cancelled;
|
||||
this.duration = duration;
|
||||
this.size = size;
|
||||
}
|
||||
}
|
||||
|
||||
export function setFileProtocolWssUrl(url) {
|
||||
localStorage && localStorage.setItem('wssURL', url);
|
||||
fileProtocolWssUrl = url;
|
||||
@@ -137,17 +146,25 @@ export async function setPassword(id, owner_token, keychain) {
|
||||
}
|
||||
|
||||
function asyncInitWebSocket(server) {
|
||||
return new Promise(resolve => {
|
||||
const ws = new WebSocket(server);
|
||||
ws.onopen = () => {
|
||||
resolve(ws);
|
||||
};
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
const ws = new WebSocket(server);
|
||||
ws.addEventListener('open', () => resolve(ws), { once: true });
|
||||
} catch (e) {
|
||||
reject(new ConnectionError(false));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function listenForResponse(ws, canceller) {
|
||||
return new Promise((resolve, reject) => {
|
||||
function handleClose(event) {
|
||||
// a 'close' event before a 'message' event means the request failed
|
||||
ws.removeEventListener('message', handleMessage);
|
||||
reject(new ConnectionError(canceller.cancelled));
|
||||
}
|
||||
function handleMessage(msg) {
|
||||
ws.removeEventListener('close', handleClose);
|
||||
try {
|
||||
const response = JSON.parse(msg.data);
|
||||
if (response.error) {
|
||||
@@ -156,13 +173,11 @@ function listenForResponse(ws, canceller) {
|
||||
resolve(response);
|
||||
}
|
||||
} catch (e) {
|
||||
ws.close();
|
||||
canceller.cancelled = true;
|
||||
canceller.error = e;
|
||||
reject(e);
|
||||
}
|
||||
}
|
||||
ws.addEventListener('message', handleMessage, { once: true });
|
||||
ws.addEventListener('close', handleClose, { once: true });
|
||||
});
|
||||
}
|
||||
|
||||
@@ -176,6 +191,8 @@ async function upload(
|
||||
onprogress,
|
||||
canceller
|
||||
) {
|
||||
let size = 0;
|
||||
const start = Date.now();
|
||||
const host = window.location.hostname;
|
||||
const port = window.location.port;
|
||||
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
|
||||
@@ -203,31 +220,41 @@ async function upload(
|
||||
|
||||
const reader = stream.getReader();
|
||||
let state = await reader.read();
|
||||
let size = 0;
|
||||
while (!state.done) {
|
||||
const buf = state.value;
|
||||
if (canceller.cancelled) {
|
||||
throw canceller.error;
|
||||
ws.close();
|
||||
}
|
||||
|
||||
if (ws.readyState !== WebSocket.OPEN) {
|
||||
break;
|
||||
}
|
||||
const buf = state.value;
|
||||
ws.send(buf);
|
||||
|
||||
onprogress(size);
|
||||
size += buf.length;
|
||||
state = await reader.read();
|
||||
while (ws.bufferedAmount > ECE_RECORD_SIZE * 2) {
|
||||
while (
|
||||
ws.bufferedAmount > ECE_RECORD_SIZE * 2 &&
|
||||
ws.readyState === WebSocket.OPEN &&
|
||||
!canceller.cancelled
|
||||
) {
|
||||
await delay();
|
||||
}
|
||||
}
|
||||
const footer = new Uint8Array([0]);
|
||||
ws.send(footer);
|
||||
if (ws.readyState === WebSocket.OPEN) {
|
||||
ws.send(new Uint8Array([0])); //EOF
|
||||
}
|
||||
|
||||
await completedResponse;
|
||||
ws.close();
|
||||
uploadInfo.duration = Date.now() - start;
|
||||
return uploadInfo;
|
||||
} catch (e) {
|
||||
ws.close(4000);
|
||||
e.size = size;
|
||||
e.duration = Date.now() - start;
|
||||
throw e;
|
||||
} finally {
|
||||
if (![WebSocket.CLOSED, WebSocket.CLOSING].includes(ws.readyState)) {
|
||||
ws.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -244,7 +271,6 @@ export function uploadWs(
|
||||
|
||||
return {
|
||||
cancel: function() {
|
||||
canceller.error = new Error(0);
|
||||
canceller.cancelled = true;
|
||||
},
|
||||
|
||||
@@ -284,7 +310,7 @@ async function downloadS(id, keychain, signal) {
|
||||
return response.body;
|
||||
}
|
||||
|
||||
async function tryDownloadStream(id, keychain, signal, tries = 1) {
|
||||
async function tryDownloadStream(id, keychain, signal, tries = 2) {
|
||||
try {
|
||||
const result = await downloadS(id, keychain, signal);
|
||||
return result;
|
||||
@@ -306,7 +332,7 @@ export function downloadStream(id, keychain) {
|
||||
}
|
||||
return {
|
||||
cancel,
|
||||
result: tryDownloadStream(id, keychain, controller.signal, 2)
|
||||
result: tryDownloadStream(id, keychain, controller.signal)
|
||||
};
|
||||
}
|
||||
|
||||
@@ -346,7 +372,7 @@ async function download(id, keychain, onprogress, canceller) {
|
||||
});
|
||||
}
|
||||
|
||||
async function tryDownload(id, keychain, onprogress, canceller, tries = 1) {
|
||||
async function tryDownload(id, keychain, onprogress, canceller, tries = 2) {
|
||||
try {
|
||||
const result = await download(id, keychain, onprogress, canceller);
|
||||
return result;
|
||||
@@ -367,7 +393,7 @@ export function downloadFile(id, keychain, onprogress) {
|
||||
}
|
||||
return {
|
||||
cancel,
|
||||
result: tryDownload(id, keychain, onprogress, canceller, 2)
|
||||
result: tryDownload(id, keychain, onprogress, canceller)
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -76,8 +76,8 @@ async function polyfillStreams() {
|
||||
}
|
||||
|
||||
export default async function getCapabilities() {
|
||||
const serviceWorker =
|
||||
'serviceWorker' in navigator && browserName() !== 'edge';
|
||||
const browser = browserName();
|
||||
const serviceWorker = 'serviceWorker' in navigator && browser !== 'edge';
|
||||
let crypto = await checkCrypto();
|
||||
const nativeStreams = checkStreams();
|
||||
let polyStreams = false;
|
||||
@@ -97,13 +97,16 @@ export default async function getCapabilities() {
|
||||
window.matchMedia('(display-mode: standalone)').matches ||
|
||||
navigator.standalone;
|
||||
|
||||
const mobileFirefox =
|
||||
browser === 'firefox' && /mobile/i.test(navigator.userAgent);
|
||||
|
||||
return {
|
||||
account,
|
||||
crypto,
|
||||
serviceWorker,
|
||||
streamUpload: nativeStreams || polyStreams,
|
||||
streamDownload:
|
||||
nativeStreams && serviceWorker && browserName() !== 'safari',
|
||||
nativeStreams && serviceWorker && browser !== 'safari' && !mobileFirefox,
|
||||
multifile: nativeStreams || polyStreams,
|
||||
share,
|
||||
standalone
|
||||
|
||||
@@ -76,7 +76,7 @@ export default function(state, emitter) {
|
||||
state.storage.remove(ownedFile.id);
|
||||
await ownedFile.del();
|
||||
} catch (e) {
|
||||
state.raven.captureException(e);
|
||||
state.sentry.captureException(e);
|
||||
}
|
||||
render();
|
||||
});
|
||||
@@ -176,14 +176,17 @@ export default function(state, emitter) {
|
||||
} catch (err) {
|
||||
if (err.message === '0') {
|
||||
//cancelled. do nothing
|
||||
const duration = Date.now() - start;
|
||||
metrics.cancelledUpload(archive, duration);
|
||||
metrics.cancelledUpload(archive, err.duration);
|
||||
render();
|
||||
} else {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(err);
|
||||
state.raven.captureException(err);
|
||||
metrics.stoppedUpload(archive);
|
||||
state.sentry.withScope(scope => {
|
||||
scope.setExtra('duration', err.duration);
|
||||
scope.setExtra('size', err.size);
|
||||
state.sentry.captureException(err);
|
||||
});
|
||||
metrics.stoppedUpload(archive, err.duration);
|
||||
emitter.emit('pushState', '/error');
|
||||
}
|
||||
} finally {
|
||||
@@ -262,7 +265,12 @@ export default function(state, emitter) {
|
||||
state.transfer = null;
|
||||
const location = err.message === '404' ? '/404' : '/error';
|
||||
if (location === '/error') {
|
||||
state.raven.captureException(err);
|
||||
state.sentry.withScope(scope => {
|
||||
scope.setExtra('duration', err.duration);
|
||||
scope.setExtra('size', err.size);
|
||||
scope.setExtra('progress', err.progress);
|
||||
state.sentry.captureException(err);
|
||||
});
|
||||
const duration = Date.now() - start;
|
||||
metrics.stoppedDownload({
|
||||
size,
|
||||
|
||||
@@ -112,6 +112,7 @@ export default class FileReceiver extends Nanobus {
|
||||
}
|
||||
|
||||
async downloadStream(noSave = false) {
|
||||
const start = Date.now();
|
||||
const onprogress = p => {
|
||||
this.progress = [p, this.fileInfo.size];
|
||||
this.emit('progress');
|
||||
@@ -153,7 +154,7 @@ export default class FileReceiver extends Nanobus {
|
||||
const downloadPath = `/api/download/${this.fileInfo.id}`;
|
||||
let downloadUrl = getApiUrl(downloadPath);
|
||||
if (downloadUrl === downloadPath) {
|
||||
downloadUrl = `${location.protocol}//${location.host}/api/download/${this.fileInfo.id}`;
|
||||
downloadUrl = `${location.protocol}//${location.host}${downloadPath}`;
|
||||
}
|
||||
const a = document.createElement('a');
|
||||
a.href = downloadUrl;
|
||||
@@ -162,11 +163,29 @@ export default class FileReceiver extends Nanobus {
|
||||
}
|
||||
|
||||
let prog = 0;
|
||||
let hangs = 0;
|
||||
while (prog < this.fileInfo.size) {
|
||||
const msg = await this.sendMessageToSw({
|
||||
request: 'progress',
|
||||
id: this.fileInfo.id
|
||||
});
|
||||
if (msg.progress === prog) {
|
||||
hangs++;
|
||||
} else {
|
||||
hangs = 0;
|
||||
}
|
||||
if (hangs > 30) {
|
||||
// TODO: On Chrome we don't get a cancel
|
||||
// signal so one is indistinguishable from
|
||||
// a hang. We may be able to detect
|
||||
// which end is hung in the service worker
|
||||
// to improve on this.
|
||||
const e = new Error('hung download');
|
||||
e.duration = Date.now() - start;
|
||||
e.size = this.fileInfo.size;
|
||||
e.progress = prog;
|
||||
throw e;
|
||||
}
|
||||
prog = msg.progress;
|
||||
onprogress(prog);
|
||||
await delay(1000);
|
||||
|
||||
@@ -44,7 +44,6 @@ export default class FileSender extends Nanobus {
|
||||
}
|
||||
|
||||
async upload(archive, bearerToken) {
|
||||
const start = Date.now();
|
||||
if (this.cancelled) {
|
||||
throw new Error(0);
|
||||
}
|
||||
@@ -76,7 +75,6 @@ export default class FileSender extends Nanobus {
|
||||
this.emit('progress'); // HACK to kick MS Edge
|
||||
try {
|
||||
const result = await this.uploadRequest.result;
|
||||
const time = Date.now() - start;
|
||||
this.msg = 'notifyUploadEncryptDone';
|
||||
this.uploadRequest = null;
|
||||
this.progress = [1, 1];
|
||||
@@ -87,8 +85,8 @@ export default class FileSender extends Nanobus {
|
||||
name: archive.name,
|
||||
size: archive.size,
|
||||
manifest: archive.manifest,
|
||||
time: time,
|
||||
speed: archive.size / (time / 1000),
|
||||
time: result.duration,
|
||||
speed: archive.size / (result.duration / 1000),
|
||||
createdAt: Date.now(),
|
||||
expiresAt: Date.now() + archive.timeLimit * 1000,
|
||||
secretKey: secretKey,
|
||||
|
||||
10
app/main.js
10
app/main.js
@@ -12,15 +12,15 @@ import pasteManager from './pasteManager';
|
||||
import storage from './storage';
|
||||
import metrics from './metrics';
|
||||
import experiments from './experiments';
|
||||
import Raven from 'raven-js';
|
||||
import * as Sentry from '@sentry/browser';
|
||||
import './main.css';
|
||||
import User from './user';
|
||||
import { getTranslator } from './locale';
|
||||
import Archive from './archive';
|
||||
import { setTranslate, locale } from './utils';
|
||||
|
||||
if (navigator.doNotTrack !== '1' && window.RAVEN_CONFIG) {
|
||||
Raven.config(window.SENTRY_ID, window.RAVEN_CONFIG).install();
|
||||
if (navigator.doNotTrack !== '1' && window.SENTRY_CONFIG) {
|
||||
Sentry.init(window.SENTRY_CONFIG);
|
||||
}
|
||||
|
||||
if (process.env.NODE_ENV === 'production') {
|
||||
@@ -56,13 +56,13 @@ if (process.env.NODE_ENV === 'production') {
|
||||
capabilities,
|
||||
translate,
|
||||
storage,
|
||||
raven: Raven,
|
||||
sentry: Sentry,
|
||||
user: new User(storage, LIMITS, window.AUTH_CONFIG),
|
||||
transfer: null,
|
||||
fileInfo: null
|
||||
};
|
||||
|
||||
const app = routes(choo());
|
||||
const app = routes(choo({ hash: true }));
|
||||
// eslint-disable-next-line require-atomic-updates
|
||||
window.app = app;
|
||||
app.use(experiments);
|
||||
|
||||
@@ -107,9 +107,10 @@ function completedUpload(archive, duration) {
|
||||
});
|
||||
}
|
||||
|
||||
function stoppedUpload(archive) {
|
||||
function stoppedUpload(archive, duration = 0) {
|
||||
return addEvent('client_upload', {
|
||||
download_limit: archive.dlimit,
|
||||
duration: sizeOrder(duration),
|
||||
file_count: archive.numFiles,
|
||||
password_protected: !!archive.password,
|
||||
size: sizeOrder(archive.size),
|
||||
|
||||
@@ -2,7 +2,7 @@ const choo = require('choo');
|
||||
const download = require('./ui/download');
|
||||
const body = require('./ui/body');
|
||||
|
||||
module.exports = function(app = choo()) {
|
||||
module.exports = function(app = choo({ hash: true })) {
|
||||
app.route('/', body(require('./ui/home')));
|
||||
app.route('/download/:id', body(download));
|
||||
app.route('/download/:id/:key', body(download));
|
||||
|
||||
@@ -11,13 +11,14 @@ const map = new Map();
|
||||
const IMAGES = /.*\.(png|svg|jpg)$/;
|
||||
const VERSIONED_ASSET = /\.[A-Fa-f0-9]{8}\.(js|css|png|svg|jpg)$/;
|
||||
const DOWNLOAD_URL = /\/api\/download\/([A-Fa-f0-9]{4,})/;
|
||||
const FONT = /\.woff2?$/;
|
||||
|
||||
self.addEventListener('install', event => {
|
||||
event.waitUntil(precache());
|
||||
self.addEventListener('install', () => {
|
||||
self.skipWaiting();
|
||||
});
|
||||
|
||||
self.addEventListener('activate', event => {
|
||||
event.waitUntil(self.clients.claim());
|
||||
event.waitUntil(self.clients.claim().then(precache));
|
||||
});
|
||||
|
||||
async function decryptStream(id) {
|
||||
@@ -83,16 +84,28 @@ async function decryptStream(id) {
|
||||
}
|
||||
|
||||
async function precache() {
|
||||
try {
|
||||
await cleanCache();
|
||||
const cache = await caches.open(version);
|
||||
const images = assets.match(IMAGES);
|
||||
await cache.addAll(images);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
// cache will get populated on demand
|
||||
}
|
||||
}
|
||||
|
||||
async function cleanCache() {
|
||||
const oldCaches = await caches.keys();
|
||||
for (const c of oldCaches) {
|
||||
if (c !== version) {
|
||||
await caches.delete(c);
|
||||
}
|
||||
}
|
||||
const cache = await caches.open(version);
|
||||
const images = assets.match(IMAGES);
|
||||
await cache.addAll(images);
|
||||
return self.skipWaiting();
|
||||
}
|
||||
|
||||
function cacheable(url) {
|
||||
return VERSIONED_ASSET.test(url) || FONT.test(url);
|
||||
}
|
||||
|
||||
async function cachedOrFetched(req) {
|
||||
@@ -102,7 +115,7 @@ async function cachedOrFetched(req) {
|
||||
return cached;
|
||||
}
|
||||
const fetched = await fetch(req);
|
||||
if (fetched.ok && VERSIONED_ASSET.test(req.url)) {
|
||||
if (fetched.ok && cacheable(req.url)) {
|
||||
cache.put(req, fetched.clone());
|
||||
}
|
||||
return fetched;
|
||||
@@ -115,7 +128,7 @@ self.onfetch = event => {
|
||||
const dlmatch = DOWNLOAD_URL.exec(url.pathname);
|
||||
if (dlmatch) {
|
||||
event.respondWith(decryptStream(dlmatch[1]));
|
||||
} else if (VERSIONED_ASSET.test(url.pathname)) {
|
||||
} else if (cacheable(url.pathname)) {
|
||||
event.respondWith(cachedOrFetched(req));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# Custom Loaders
|
||||
|
||||
## Generate Asset Map
|
||||
## Android Index Plugin
|
||||
|
||||
This loader enumerates all the files in `assets/` so that `common/assets.js` can provide mappings from the source filename to the hashed filename used on the site.
|
||||
Generates the `index.html` page for the native android client
|
||||
|
||||
## Version Plugin
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const genmap = require('../build/generate_asset_map');
|
||||
const genmap = require('./generate_asset_map');
|
||||
const isServer = typeof genmap === 'function';
|
||||
let prefix = '';
|
||||
let manifest = {};
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
# Common Code
|
||||
|
||||
This directory contains code loaded by both the frontend `app` and backend `server`. The code here can be challenging to understand at first because the contexts for the two (three counting the dev server) environments that include them are quite different, but the purpose of these modules are quite simple, to provide mappings from the source assets (`copy-16.png`) to the concrete production assets (`copy-16.db66e0bf.svg`).
|
||||
This directory contains code loaded by both the frontend `app` and backend `server`. The code here can be challenging to understand at first because the contexts for the two (three counting the dev server) environments that include them are quite different, but the purpose of these modules are quite simple, to provide mappings from the source assets (`copy-16.png`) to the concrete production assets (`copy-16.db66e0bf.svg`).
|
||||
|
||||
## Generate Asset Map
|
||||
|
||||
This loader enumerates all the files in `assets/` so that `common/assets.js` can provide mappings from the source filename to the hashed filename used on the site.
|
||||
@@ -1,13 +1,6 @@
|
||||
## Setup
|
||||
|
||||
Before building the Docker image, you must build the production assets:
|
||||
|
||||
```sh
|
||||
npm run build
|
||||
```
|
||||
|
||||
Then you can run either `docker build` or `docker-compose up`.
|
||||
|
||||
Run `docker build -t send:latest .` to create an image or `docker-compose up` to run a full testable stack. *We don't recommend using docker-compose for production.*
|
||||
|
||||
## Environment variables:
|
||||
|
||||
|
||||
2429
package-lock.json
generated
2429
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
80
package.json
80
package.json
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "firefox-send",
|
||||
"description": "File Sharing Experiment",
|
||||
"version": "3.0.14",
|
||||
"version": "3.0.19",
|
||||
"author": "Mozilla (https://mozilla.org)",
|
||||
"repository": "mozilla/send",
|
||||
"homepage": "https://github.com/mozilla/send/",
|
||||
@@ -35,7 +35,8 @@
|
||||
"hooks": {
|
||||
"pre-commit": "lint-staged",
|
||||
"pre-push": "npm test",
|
||||
"post-merge": "npm install"
|
||||
"post-merge": "npm install",
|
||||
"post-checkout": "scripts/sync-npm-dependencies.sh"
|
||||
}
|
||||
},
|
||||
"lint-staged": {
|
||||
@@ -57,69 +58,69 @@
|
||||
"cache": true
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
"node": ">=10.0.0 <11.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.5.5",
|
||||
"@babel/core": "^7.6.0",
|
||||
"@babel/plugin-proposal-class-properties": "^7.5.5",
|
||||
"@babel/plugin-syntax-dynamic-import": "^7.2.0",
|
||||
"@babel/preset-env": "^7.5.5",
|
||||
"@babel/preset-env": "^7.6.0",
|
||||
"@dannycoates/webcrypto-liner": "^0.1.37",
|
||||
"@fullhuman/postcss-purgecss": "^1.2.0",
|
||||
"@fullhuman/postcss-purgecss": "^1.3.0",
|
||||
"@mattiasbuelens/web-streams-polyfill": "0.2.1",
|
||||
"@sentry/browser": "^5.6.3",
|
||||
"asmcrypto.js": "^0.22.0",
|
||||
"babel-loader": "^8.0.6",
|
||||
"babel-plugin-istanbul": "^5.2.0",
|
||||
"base64-js": "^1.3.0",
|
||||
"base64-js": "^1.3.1",
|
||||
"content-disposition": "^0.5.3",
|
||||
"copy-webpack-plugin": "^5.0.4",
|
||||
"core-js": "^3.1.4",
|
||||
"core-js": "^3.2.1",
|
||||
"crc": "^3.8.0",
|
||||
"cross-env": "^5.2.0",
|
||||
"css-loader": "^3.1.0",
|
||||
"cross-env": "^5.2.1",
|
||||
"css-loader": "^3.2.0",
|
||||
"css-mqpacker": "^7.0.0",
|
||||
"cssnano": "^4.1.10",
|
||||
"eslint": "^6.1.0",
|
||||
"eslint-config-prettier": "^6.0.0",
|
||||
"eslint-plugin-mocha": "^6.0.0",
|
||||
"eslint-plugin-node": "^9.1.0",
|
||||
"eslint": "^6.4.0",
|
||||
"eslint-config-prettier": "^6.3.0",
|
||||
"eslint-plugin-mocha": "^6.1.1",
|
||||
"eslint-plugin-node": "^9.2.0",
|
||||
"eslint-plugin-security": "^1.4.0",
|
||||
"expose-loader": "^0.7.5",
|
||||
"extract-loader": "^3.1.0",
|
||||
"extract-text-webpack-plugin": "^4.0.0-beta.0",
|
||||
"fast-text-encoding": "^1.0.0",
|
||||
"file-loader": "^4.1.0",
|
||||
"file-loader": "^4.2.0",
|
||||
"git-rev-sync": "^1.12.0",
|
||||
"html-loader": "^0.5.5",
|
||||
"http_ece": "^1.1.0",
|
||||
"husky": "^3.0.2",
|
||||
"husky": "^3.0.5",
|
||||
"intl-pluralrules": "^1.0.3",
|
||||
"lint-staged": "^9.2.1",
|
||||
"lint-staged": "^9.3.0",
|
||||
"mocha": "^6.2.0",
|
||||
"morgan": "^1.9.1",
|
||||
"nanobus": "^4.4.0",
|
||||
"nanohtml": "^1.6.3",
|
||||
"nanohtml": "^1.8.1",
|
||||
"nanotiming": "^7.3.1",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"nyc": "^14.1.1",
|
||||
"postcss-loader": "^3.0.0",
|
||||
"postcss-preset-env": "^6.7.0",
|
||||
"prettier": "^1.18.2",
|
||||
"proxyquire": "^2.1.1",
|
||||
"puppeteer": "^1.19.0",
|
||||
"raven-js": "^3.27.2",
|
||||
"proxyquire": "^2.1.3",
|
||||
"puppeteer": "^1.20.0",
|
||||
"raw-loader": "^3.1.0",
|
||||
"redis-mock": "^0.45.0",
|
||||
"rimraf": "^2.6.3",
|
||||
"redis-mock": "^0.46.0",
|
||||
"rimraf": "^3.0.0",
|
||||
"script-loader": "^0.7.2",
|
||||
"sinon": "^7.3.2",
|
||||
"sinon": "^7.5.0",
|
||||
"string-hash": "^1.1.3",
|
||||
"stylelint": "^10.1.0",
|
||||
"stylelint-config-standard": "^18.3.0",
|
||||
"stylelint-no-unsupported-browser-features": "^3.0.2",
|
||||
"svgo": "^1.3.0",
|
||||
"svgo-loader": "^2.2.1",
|
||||
"tailwindcss": "^1.0.6",
|
||||
"tailwindcss": "^1.1.2",
|
||||
"val-loader": "^1.1.1",
|
||||
"wdio-docker-service": "^1.4.2",
|
||||
"wdio-dot-reporter": "0.0.10",
|
||||
@@ -129,34 +130,34 @@
|
||||
"wdio-selenium-standalone-service": "0.0.12",
|
||||
"wdio-spec-reporter": "^0.1.5",
|
||||
"webdriverio": "^4.14.4",
|
||||
"webpack": "^4.39.1",
|
||||
"webpack-cli": "^3.3.6",
|
||||
"webpack-dev-middleware": "^3.7.0",
|
||||
"webpack-dev-server": "^3.7.2",
|
||||
"webpack-manifest-plugin": "^2.0.4",
|
||||
"webpack": "4.38.0",
|
||||
"webpack-cli": "^3.3.9",
|
||||
"webpack-dev-middleware": "^3.7.1",
|
||||
"webpack-dev-server": "^3.8.1",
|
||||
"webpack-manifest-plugin": "^2.1.0",
|
||||
"webpack-unassert-loader": "^1.2.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@dannycoates/express-ws": "^5.0.3",
|
||||
"@fluent/bundle": "^0.13.0",
|
||||
"@fluent/langneg": "^0.3.0",
|
||||
"@google-cloud/storage": "^3.0.4",
|
||||
"aws-sdk": "^2.503.0",
|
||||
"@google-cloud/storage": "^3.3.0",
|
||||
"@sentry/node": "^5.6.2",
|
||||
"aws-sdk": "^2.533.0",
|
||||
"body-parser": "^1.19.0",
|
||||
"choo": "^6.13.3",
|
||||
"choo": "^7.0.0",
|
||||
"cldr-core": "^35.1.0",
|
||||
"configstore": "github:dannycoates/configstore#master",
|
||||
"convict": "^5.1.0",
|
||||
"express": "^4.17.1",
|
||||
"express-ws": "github:dannycoates/express-ws",
|
||||
"fxa-geodb": "^1.0.4",
|
||||
"helmet": "^3.20.0",
|
||||
"helmet": "^3.21.1",
|
||||
"mkdirp": "^0.5.1",
|
||||
"mozlog": "^2.2.0",
|
||||
"node-fetch": "^2.6.0",
|
||||
"raven": "^2.6.4",
|
||||
"redis": "^2.8.0",
|
||||
"selenium-standalone": "^6.15.6",
|
||||
"ua-parser-js": "^0.7.20",
|
||||
"websocket-stream": "^5.5.0"
|
||||
"ua-parser-js": "^0.7.20"
|
||||
},
|
||||
"availableLanguages": [
|
||||
"en-US",
|
||||
@@ -179,6 +180,7 @@
|
||||
"es-ES",
|
||||
"es-MX",
|
||||
"et",
|
||||
"eu",
|
||||
"fi",
|
||||
"fr",
|
||||
"fy-NL",
|
||||
@@ -195,8 +197,10 @@
|
||||
"ko",
|
||||
"lt",
|
||||
"ml",
|
||||
"nb-NO",
|
||||
"nl",
|
||||
"nn-NO",
|
||||
"oc",
|
||||
"pa-IN",
|
||||
"pl",
|
||||
"pt-BR",
|
||||
|
||||
@@ -182,3 +182,5 @@ shareLinkDescription = شارِك الرابط الذي يصل إلى الملف
|
||||
shareLinkButton = شارِك الرابط
|
||||
# $name is the name of the file
|
||||
shareMessage = نزِّل ”{ $name }“ عبر { -send-brand }: خدمة لمشاركة الملفات بلا عناء وبخصوصية تامة
|
||||
trailheadPromo = يمكنك حماية خصوصيتك، طبعا. انضم إلى فَيَرفُكس.
|
||||
learnMore = اطّلع على المزيد.
|
||||
|
||||
@@ -196,5 +196,5 @@ shareLinkDescription = Sdílet odkaz na soubor:
|
||||
shareLinkButton = Sdílet odkaz
|
||||
# $name is the name of the file
|
||||
shareMessage = Stáhněte si soubor „{ $name }“ s { -send-brand(case: "ins") } - jednoduché a bezpečné sdílení souborů
|
||||
trailheadPromo = Existuje snadný způsob pro ochranu vašeho soukromí. Používejte Firefox.
|
||||
trailheadPromo = Existuje způsob, jak ochránit své soukromí. Používejte Firefox.
|
||||
learnMore = Zjistit více.
|
||||
|
||||
@@ -151,3 +151,5 @@ shareLinkDescription = Del linket til din fil:
|
||||
shareLinkButton = Del link
|
||||
# $name is the name of the file
|
||||
shareMessage = Hent { $name } med { -send-brand } - simpel og sikker fildeling
|
||||
trailheadPromo = Beskyt dine digitale rettigheder. Slut dig til Firefox.
|
||||
learnMore = Læs mere.
|
||||
|
||||
@@ -126,7 +126,7 @@ addPassword = Protegido con contraseña
|
||||
emailPlaceholder = Ingresa tu correo electrónico
|
||||
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
|
||||
signInSizeBump = Iniciar sesión para enviar hasta { $size }
|
||||
signInButton = Iniciar sesión/registrarse
|
||||
signInOnlyButton = Iniciar sesión
|
||||
accountBenefitTitle = Crear una cuenta de { -firefox } o iniciar sesión
|
||||
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
|
||||
accountBenefitLargeFiles = Compartir archivos de hasta { $size }
|
||||
@@ -145,3 +145,11 @@ noStreamsWarning = Puede que este navegador no pueda descifrar un archivo tan gr
|
||||
noStreamsOptionCopy = Copiar el enlace para abrir en otro navegador
|
||||
noStreamsOptionFirefox = Prueba nuestro navegador favorito
|
||||
noStreamsOptionDownload = Continuar con este navegador
|
||||
downloadFirefoxPromo = { -send-short-brand } te lo ofrece el nuevo { -firefox }.
|
||||
# the next line after the colon contains a file name
|
||||
shareLinkDescription = Comparte el enlace a tu archivo:
|
||||
shareLinkButton = Enlace para compartir
|
||||
# $name is the name of the file
|
||||
shareMessage = Descarga «{ $name }» con { -send-brand }: es sencillo y seguro
|
||||
trailheadPromo = Existe una forma de proteger tu privacidad. Únete a Firefox.
|
||||
learnMore = Saber más.
|
||||
|
||||
@@ -23,7 +23,7 @@ fileSizeProgress = ({ $totalSize } / { $partialSize })
|
||||
sendYourFilesLink = Probatu Firefox Send
|
||||
errorPageHeader = Zerbait gaizki joan da!
|
||||
fileTooBig = Fitxategia handiegia da kargatzeko. { $size } baino txikiagoa izan behar du.
|
||||
linkExpiredAlt = Lotura iraungita
|
||||
linkExpiredAlt = Lotura iraungi da
|
||||
notSupportedHeader = Zure nabigatzailea ez da onartzen.
|
||||
notSupportedLink = Zergatik ez da nire nabigatzailea onartzen?
|
||||
notSupportedOutdatedDetail = Zoritxarrez Firefox bertsio honek ez du Firefox Send-ek behar duen web teknologia onartzen. Zure nabigatzailea eguneratu behar duzu.
|
||||
@@ -54,7 +54,30 @@ passwordSetError = Pasahitz hau ezin da ezarri
|
||||
-firefox = Firefox
|
||||
-mozilla = Mozilla
|
||||
introTitle = Partekatu fitxategiak modu sinple eta pribatuan
|
||||
introDescription = { -send-brand } tresna fitxategiak partekatzeko da, muturretik muturrera zifratuta eta automatikoki iraungitzen diren loturekin. Hortaz, partekatzen duzuna pribatua izango da eta ziur egon zaitezke zure fitxategiak ez direla online egongo betirako.
|
||||
notifyUploadEncryptDone = Zure fitxategia zifratuta eta bidaltzeko prest dago
|
||||
# downloadCount is from the downloadCount string and timespan is a timespanMinutes string. ex. 'Expires after 2 downloads or 25 minutes'
|
||||
archiveExpiryInfo = { $downloadCount } edo { $timespan } ondoren iraungiko da
|
||||
timespanMinutes =
|
||||
{ $num ->
|
||||
[one] minutu 1
|
||||
*[other] { $num } minutu
|
||||
}
|
||||
timespanDays =
|
||||
{ $num ->
|
||||
[one] egun 1
|
||||
*[other] { $num } egun
|
||||
}
|
||||
timespanWeeks =
|
||||
{ $num ->
|
||||
[one] aste 1
|
||||
*[other] { $num } aste
|
||||
}
|
||||
fileCount =
|
||||
{ $num ->
|
||||
[one] fitxategi 1
|
||||
*[other] { $num } fitxategi
|
||||
}
|
||||
# byte abbreviation
|
||||
bytes = B
|
||||
# kibibyte abbreviation
|
||||
@@ -65,9 +88,33 @@ mb = MB
|
||||
gb = GB
|
||||
# localized number and byte abbreviation. example "2.5MB"
|
||||
fileSize = { $num }{ $units }
|
||||
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
|
||||
totalSize = Tamaina guztira: { $size }
|
||||
# the next line after the colon contains a file name
|
||||
copyLinkDescription = Kopiatu fitxategia partekatzeko lotura:
|
||||
copyLinkButton = Kopiatu lotura
|
||||
downloadTitle = Deskargatu fitxategiak
|
||||
downloadDescription = { -send-brand } bidez partekatu da fitxategia muturretik muturrera zifratuta eta automatikoki iraungitzen den lotura batekin.
|
||||
trySendDescription = Probatu { -send-brand } fitxategiak partekatzeko modu sinple eta segururako.
|
||||
# count will always be > 10
|
||||
tooManyFiles =
|
||||
{ $count ->
|
||||
[one] Soilik fitxategi bakarra igo daiteke aldi berean.
|
||||
*[other] Soilik { $count } fitxategi igo daitezke aldi berean.
|
||||
}
|
||||
# count will always be > 10
|
||||
tooManyArchives =
|
||||
{ $count ->
|
||||
[one] Soilik artxibo bakarra onartzen da.
|
||||
*[other] Soilik { $count } artxibo onartzen dira.
|
||||
}
|
||||
expiredTitle = Lotura hau iraungi da.
|
||||
notSupportedDescription = { -send-brand } ez da nabigatzaile honetan ibiliko. { -send-short-brand } hobeto dabil { -firefox }(r)en azken bertsioarekin; halaber, nabigatzaile gehienen azken bertsioarekin ibiliko da.
|
||||
downloadFirefox = Deskargatu { -firefox }
|
||||
legalTitle = { -send-short-brand } pribatutasun-oharra
|
||||
legalDateStamp = 1.0 bertsioa, 2019ko martxoaren 12koa.
|
||||
# A short representation of a countdown timer containing the number of days, hours, and minutes remaining as digits, example "2d 11h 56m"
|
||||
expiresDaysHoursMinutes = { $days }e { $hours }h { $minutes }m
|
||||
addFilesButton = Hautatu igotzeko fitxategiak
|
||||
uploadButton = Igo
|
||||
# the first part of the string 'Drag and drop files or click to send up to 1GB'
|
||||
@@ -77,7 +124,32 @@ dragAndDropFiles = Arrastatu eta jaregin fitxategiak
|
||||
orClickWithSize = edo egin klik { $size } arte igotzeko
|
||||
addPassword = Babestu pasahitzarekin
|
||||
emailPlaceholder = Idatzi zure helbide elektronikoa
|
||||
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
|
||||
signInSizeBump = Hasi saioa { $size } arte bidaltzeko
|
||||
signInOnlyButton = Hasi saioa
|
||||
accountBenefitTitle = Sortu { -firefox } kontu bat edo hasi saioa
|
||||
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
|
||||
accountBenefitLargeFiles = Partekatu { $size } arteko fitxategiak
|
||||
accountBenefitDownloadCount = Partekatu fitxategiak jende gehiagorekin
|
||||
accountBenefitTimeLimit =
|
||||
{ $count ->
|
||||
[one] Utzi loturak erabilgarri egun batez
|
||||
*[other] Utzi loturak erabilgarri { $count } egunez
|
||||
}
|
||||
accountBenefitSync = Kudeatu partekatutako fitxategiak edozein gailutatik
|
||||
accountBenefitMoz = { -mozilla }ren beste zerbitzuei buruzko argibide gehiago
|
||||
signOut = Amaitu saioa
|
||||
okButton = Ados
|
||||
downloadingTitle = Deskargatzen
|
||||
noStreamsWarning = Baliteke nabigatzailea gai ez izatea horrelako tamaina handiko fitxategiak deszifratzeko.
|
||||
noStreamsOptionCopy = Kopiatu lotura beste nabigatzaile batean irekitzeko
|
||||
noStreamsOptionFirefox = Probatu gure nabigatzaile gogokoena
|
||||
noStreamsOptionDownload = Jarraitu nabigatzaile honekin
|
||||
downloadFirefoxPromo = Erabat berritutako { -firefox }(e)k eskaintzen dizu { -send-short-brand }
|
||||
# the next line after the colon contains a file name
|
||||
shareLinkDescription = Partekatu zure fitxategirako lotura:
|
||||
shareLinkButton = Partekatu lotura
|
||||
# $name is the name of the file
|
||||
shareMessage = Deskargatu "{ $name }" { -send-brand } erabiliz: fitxategi-partekatze sinple eta segurua
|
||||
trailheadPromo = Badago zure pribatutasuna babesteko modua. Egizu bat Firefoxekin.
|
||||
learnMore = Argibide gehiago.
|
||||
|
||||
@@ -53,6 +53,7 @@ passwordSetError = امکان ثبت این گذواژه نیست
|
||||
-send-short-brand = ارسال
|
||||
-firefox = فایرفاکس
|
||||
-mozilla = موزیلا
|
||||
introTitle = اشتراکگذاری ساده و خصوصیِ پروندهها
|
||||
# byte abbreviation
|
||||
bytes = B
|
||||
# kibibyte abbreviation
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
# Firefox Send is a brand name and should not be localized.
|
||||
title = Firefox Send
|
||||
siteFeedback = משוב
|
||||
importingFile = מתבצע ייבוא...
|
||||
importingFile = מתבצע ייבוא…
|
||||
encryptingFile = מתבצעת הצפנה...
|
||||
decryptingFile = מתבצע פענוח...
|
||||
downloadCount =
|
||||
{ $num ->
|
||||
[one] הורדה אחת
|
||||
*[other] { $number } הורדות
|
||||
*[other] { $num } הורדות
|
||||
}
|
||||
timespanHours =
|
||||
{ $num ->
|
||||
[one] שעה אחת
|
||||
[two] שעתיים
|
||||
*[other] { $number } שעות
|
||||
*[other] { $num } שעות
|
||||
}
|
||||
copiedUrl = הועתק!
|
||||
unlockInputPlaceholder = ססמה
|
||||
|
||||
@@ -123,7 +123,7 @@ dragAndDropFiles = Traher e deponer files
|
||||
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
|
||||
orClickWithSize = o cliccar pro inviar usque { $size }
|
||||
addPassword = Proteger per contrasigno
|
||||
emailPlaceholder = Insere tu adresse email
|
||||
emailPlaceholder = Insere tu adresse de e-mail
|
||||
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
|
||||
signInSizeBump = Accede pro inviar usque { $size }
|
||||
signInOnlyButton = Authentica te
|
||||
|
||||
@@ -140,4 +140,5 @@ shareLinkDescription = ファイルへのリンクを共有しましょう:
|
||||
shareLinkButton = リンクを共有
|
||||
# $name is the name of the file
|
||||
shareMessage = { -send-brand } で "{ $name }" をダウンロード: シンプルで安全なファイル共有
|
||||
trailheadPromo = プライバシーを保護する方法があります。Firefox を試してください。
|
||||
learnMore = 詳細情報
|
||||
|
||||
@@ -5,7 +5,7 @@ importingFile = 가져오는 중…
|
||||
encryptingFile = 암호화 중…
|
||||
decryptingFile = 복호화 중…
|
||||
downloadCount = 다운로드 { $num }회
|
||||
timespanHours = 1 시간
|
||||
timespanHours = { $num }시간
|
||||
copiedUrl = 복사 완료!
|
||||
unlockInputPlaceholder = 비밀번호
|
||||
unlockButtonLabel = 잠금 해제
|
||||
|
||||
@@ -54,6 +54,7 @@ passwordSetError = Dette passordet kunne ikke settes
|
||||
-firefox = Firefox
|
||||
-mozilla = Mozilla
|
||||
introTitle = Enkel, privat fildeling
|
||||
introDescription = { -send-brand } lar deg dele filer via en tidsbegrenset lenke med ende-til-ende-kryptering. På den måten kan du dele filer privat og samtidig være trygg på at filene dine ikke blir liggende på nettet for alltid.
|
||||
notifyUploadEncryptDone = Filen din er kryptert og klar til å sende
|
||||
# downloadCount is from the downloadCount string and timespan is a timespanMinutes string. ex. 'Expires after 2 downloads or 25 minutes'
|
||||
archiveExpiryInfo = Utløper etter { $downloadCount } eller { $timespan }
|
||||
@@ -77,9 +78,78 @@ fileCount =
|
||||
[one] 1 fil
|
||||
*[other] { $num } filer
|
||||
}
|
||||
# size is a localized number followed by a unit of bytes, ex. 2.5GB
|
||||
# byte abbreviation
|
||||
bytes = B
|
||||
# kibibyte abbreviation
|
||||
kb = KB
|
||||
# mebibyte abbreviation
|
||||
mb = MB
|
||||
# gibibyte abbreviation
|
||||
gb = GB
|
||||
# localized number and byte abbreviation. example "2.5MB"
|
||||
fileSize = { $num }{ $units }
|
||||
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
|
||||
totalSize = Total størrelse: { $size }
|
||||
# the next line after the colon contains a file name
|
||||
copyLinkDescription = Kopier lenken for å dele filen din:
|
||||
copyLinkButton = Kopier lenke
|
||||
downloadTitle = Last ned filer
|
||||
downloadDescription = Denne filen ble delt via { -send-brand } med ende-til-ende-kryptering og en lenke som automatisk utløper.
|
||||
trySendDescription = Prøv { -send-brand } for enkel, sikker fildeling.
|
||||
# count will always be > 10
|
||||
tooManyFiles =
|
||||
{ $count ->
|
||||
[one] Kun 1 fil kan lastes opp om gangen.
|
||||
*[other] Kun { $count } filer kan lastes opp om gangen.
|
||||
}
|
||||
# count will always be > 10
|
||||
tooManyArchives =
|
||||
{ $count ->
|
||||
[one] Kun 1 arkiv er tillatt.
|
||||
*[other] Kun { $count } arkiver er tillatt.
|
||||
}
|
||||
expiredTitle = Denne lenken er utløpt.
|
||||
notSupportedDescription = { -send-brand } virker ikke med denne nettleseren. { -send-short-brand } fungerer best med den nyeste versjonen av { -firefox }, og vil fungere med den nyeste versjonen av de fleste nettlesere.
|
||||
downloadFirefox = Last ned { -firefox }
|
||||
legalTitle = { -send-short-brand } Personvernerklæring
|
||||
legalDateStamp = Versjon 1.0, datert den 12. mars 2019
|
||||
# A short representation of a countdown timer containing the number of days, hours, and minutes remaining as digits, example "2d 11h 56m"
|
||||
expiresDaysHoursMinutes = { $days }d { $hours }t { $minutes }m
|
||||
addFilesButton = Velg filer du vil laste opp
|
||||
uploadButton = Last opp
|
||||
# the first part of the string 'Drag and drop files or click to send up to 1GB'
|
||||
dragAndDropFiles = Dra og slipp filer
|
||||
# the second part of the string 'Drag and drop files or click to send up to 1GB'
|
||||
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
|
||||
orClickWithSize = eller klikk for å sende filer på opptil { $size }
|
||||
addPassword = Beskytt med passord
|
||||
emailPlaceholder = Skriv inn e-postadressen din
|
||||
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
|
||||
signInSizeBump = Logg inn for å sende opptil { $size }
|
||||
signInOnlyButton = Logg inn
|
||||
accountBenefitTitle = Opprett en { -firefox }-konto eller logg inn
|
||||
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
|
||||
accountBenefitLargeFiles = Del filer på opptil { $size }
|
||||
accountBenefitDownloadCount = Del filer med flere personer
|
||||
accountBenefitTimeLimit =
|
||||
{ $count ->
|
||||
[one] Hold lenker aktiv opptil 1 dag
|
||||
*[other] Hold lenker aktiv opptil { $count } dager
|
||||
}
|
||||
accountBenefitSync = Behandle delte filer fra en hvilken som helst enhet
|
||||
accountBenefitMoz = Les om andre { -mozilla }-tjenester
|
||||
signOut = Logg ut
|
||||
okButton = OK
|
||||
downloadingTitle = Laster ned
|
||||
noStreamsWarning = Denne nettleseren kan kanskje ikke dekryptere en så stor fil.
|
||||
noStreamsOptionCopy = Kopier lenken for å åpne den i en annen nettleser
|
||||
noStreamsOptionFirefox = Prøv favorittnettleseren vår
|
||||
noStreamsOptionDownload = Fortsett med denne nettleseren
|
||||
downloadFirefoxPromo = { -send-short-brand } presenteres for deg av den helt nye { -firefox }.
|
||||
# the next line after the colon contains a file name
|
||||
shareLinkDescription = Del lenken til filen din:
|
||||
shareLinkButton = Del lenke
|
||||
# $name is the name of the file
|
||||
shareMessage = Last ned ‹{ $name }› med { -send-brand }: enkel, trygg fildeling
|
||||
trailheadPromo = Det finnes en måte å ta vare på personvernet ditt. Bruk Firefox.
|
||||
learnMore = Les mer.
|
||||
|
||||
155
public/locales/oc/send.ftl
Normal file
155
public/locales/oc/send.ftl
Normal file
@@ -0,0 +1,155 @@
|
||||
# Firefox Send is a brand name and should not be localized.
|
||||
title = Firefox Send
|
||||
siteFeedback = Comentaris
|
||||
importingFile = Importacion…
|
||||
encryptingFile = Chiframent…
|
||||
decryptingFile = Deschiframent…
|
||||
downloadCount =
|
||||
{ $num ->
|
||||
[one] 1 telecargament
|
||||
*[other] { $num } telecargaments
|
||||
}
|
||||
timespanHours =
|
||||
{ $num ->
|
||||
[one] 1 ora
|
||||
*[other] { $num } oras
|
||||
}
|
||||
copiedUrl = Copiat !
|
||||
unlockInputPlaceholder = Senhal
|
||||
unlockButtonLabel = Desverrolhar
|
||||
downloadButtonLabel = Telecargar
|
||||
downloadFinish = Telecargament acabat
|
||||
fileSizeProgress = ({ $partialSize } sus { $totalSize })
|
||||
sendYourFilesLink = Ensajar Firefox Send
|
||||
errorPageHeader = I a quicòm que truca.
|
||||
fileTooBig = Aqueste fichièr es tròp gròs per l’enviar. Sa talha deu èsser inferiora a { $size }.
|
||||
linkExpiredAlt = Lo ligam a expirat
|
||||
notSupportedHeader = Vòstre navegador es pas compatible.
|
||||
notSupportedLink = Perqué mon navegador es pas compatible ?
|
||||
notSupportedOutdatedDetail = Aquesta version de Firefox es pas compatibla amb la tecnologia web amb la quala fonciona Firefox Send. Vos cal metre a jorn lo navegador.
|
||||
updateFirefox = Metre a jorn Firefox
|
||||
deletePopupCancel = Anullar
|
||||
deleteButtonHover = Suprimir
|
||||
footerLinkLegal = Mencions legalas
|
||||
footerLinkPrivacy = Vida privada
|
||||
footerLinkCookies = Cookies
|
||||
passwordTryAgain = Senhal incorrècte. Tornatz ensajar.
|
||||
javascriptRequired = Firefox Send requesís JavaScript
|
||||
whyJavascript = Perque Firefox Send requesís JavaScript ?
|
||||
enableJavascript = Volgatz activar lo JavaScript e ensajatz tornamai.
|
||||
# A short representation of a countdown timer containing the number of hours and minutes remaining as digits, example "13h 47m"
|
||||
expiresHoursMinutes = { $hours } h { $minutes } min
|
||||
# A short representation of a countdown timer containing the number of minutes remaining as digits, example "56m"
|
||||
expiresMinutes = { $minutes } min
|
||||
# A short status message shown when the user enters a long password
|
||||
maxPasswordLength = Talha maximala del senhal : { $length }
|
||||
# A short status message shown when there was an error setting the password
|
||||
passwordSetError = Aqueste senhal a pas pogut èsser definit
|
||||
|
||||
## Send version 2 strings
|
||||
|
||||
# Firefox Send, Send, Firefox, Mozilla are proper names and should not be localized
|
||||
-send-brand = Firefox Send
|
||||
-send-short-brand = Send
|
||||
-firefox = Firefox
|
||||
-mozilla = Mozilla
|
||||
introTitle = Partatge simple e privat de fichièrs
|
||||
introDescription = { -send-brand } vos permet de partejar de fichièr amb un chiframent del cap a la fin e un ligam qu’expira automaticament. Atal podètz gardar privat çò que partejatz e vos assegurar que demorarà pas en linha per totjorn.
|
||||
notifyUploadEncryptDone = Vòstre fichièr es chifrat e prèst per mandadís
|
||||
# downloadCount is from the downloadCount string and timespan is a timespanMinutes string. ex. 'Expires after 2 downloads or 25 minutes'
|
||||
archiveExpiryInfo = Expira aprèp { $downloadCount } o { $timespan }
|
||||
timespanMinutes =
|
||||
{ $num ->
|
||||
[one] 1 minuta
|
||||
*[other] { $num } minutas
|
||||
}
|
||||
timespanDays =
|
||||
{ $num ->
|
||||
[one] 1 jorn
|
||||
*[other] { $num } jorns
|
||||
}
|
||||
timespanWeeks =
|
||||
{ $num ->
|
||||
[one] 1 setmana
|
||||
*[other] { $num } setmanas
|
||||
}
|
||||
fileCount =
|
||||
{ $num ->
|
||||
[one] 1 fichièr
|
||||
*[other] { $num } fichièrs
|
||||
}
|
||||
# byte abbreviation
|
||||
bytes = o
|
||||
# kibibyte abbreviation
|
||||
kb = Ko
|
||||
# mebibyte abbreviation
|
||||
mb = Mo
|
||||
# gibibyte abbreviation
|
||||
gb = Go
|
||||
# localized number and byte abbreviation. example "2.5MB"
|
||||
fileSize = { $num } { $units }
|
||||
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
|
||||
totalSize = Talha totala : { $size }
|
||||
# the next line after the colon contains a file name
|
||||
copyLinkDescription = Copiatz lo ligam per partejar vòstre fichièr :
|
||||
copyLinkButton = Copiar lo ligam
|
||||
downloadTitle = Telecargar los fichièrs
|
||||
downloadDescription = Aqueste fichièr foguèt partejat via { -send-brand } amb chiframent del cap a la fin e un ligam qu’expira automaticament.
|
||||
trySendDescription = Ensajatz { -send-brand } per un partiment de fichièrs simple e segur.
|
||||
# count will always be > 10
|
||||
tooManyFiles =
|
||||
{ $count ->
|
||||
[one] Òm pòt pas qu’enviar 1 fichièr al còp.
|
||||
*[other] Òm pòt pas qu’enviar { $count } fichièrs al còp.
|
||||
}
|
||||
# count will always be > 10
|
||||
tooManyArchives =
|
||||
{ $count ->
|
||||
[one] Pas qu’un archiu es autorizat.
|
||||
*[other] Pas que { $count } archius son autorizats.
|
||||
}
|
||||
expiredTitle = Aqueste ligam a expirat.
|
||||
notSupportedDescription = { -send-brand } foncionarà pas amb aqueste navegador. { -send-short-brand } fonciona melhor amb la darrièra version de { -firefox } e foncionarà amb la version mai recenta de la màger part dels navegadors.
|
||||
downloadFirefox = Telecargar { -firefox }
|
||||
legalTitle = Avís de confidencialitat de { -send-short-brand }
|
||||
legalDateStamp = Version 1.0 del 12 de març de 2019
|
||||
# A short representation of a countdown timer containing the number of days, hours, and minutes remaining as digits, example "2d 11h 56m"
|
||||
expiresDaysHoursMinutes = { $days } j { $hours } h { $minutes } min
|
||||
addFilesButton = Seleccionatz los fichièrs de mandar
|
||||
uploadButton = Enviar
|
||||
# the first part of the string 'Drag and drop files or click to send up to 1GB'
|
||||
dragAndDropFiles = Lissatz-depausatz de fichièrs
|
||||
# the second part of the string 'Drag and drop files or click to send up to 1GB'
|
||||
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
|
||||
orClickWithSize = o clicatz per enviar fins a { $size }
|
||||
addPassword = Protegir amb un senhal
|
||||
emailPlaceholder = Picatz vòstra adreça electronica
|
||||
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
|
||||
signInSizeBump = Connectatz-vos per enviar fins a { $size }
|
||||
signInOnlyButton = Connexion
|
||||
accountBenefitTitle = Creatz un compte { -firefox } o connectatz-vos
|
||||
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
|
||||
accountBenefitLargeFiles = Partejatz de fichièrs fins a { $size }
|
||||
accountBenefitDownloadCount = Partejatz de fichièrs amb mai de personas
|
||||
accountBenefitTimeLimit =
|
||||
{ $count ->
|
||||
[one] Mantenètz los ligams actius fins a 1 jorn
|
||||
*[other] Mantenètz los ligams actius fins a { $count } jorns
|
||||
}
|
||||
accountBenefitSync = Gerissètz los fichièrs partejats de qualque siá periferic estant
|
||||
accountBenefitMoz = Aprenètz-ne mai suls autres servicis { -mozilla }
|
||||
signOut = Desconnexion
|
||||
okButton = D'acòrd
|
||||
downloadingTitle = Telecargament
|
||||
noStreamsWarning = Pòt arribar qu’aqueste navegador pòsca pas deschifrar un fichièr tan gròs.
|
||||
noStreamsOptionCopy = Copiatz lo ligam per lo dobrir dins un autre navegador
|
||||
noStreamsOptionFirefox = Ensajatz nòstre navegador preferit
|
||||
noStreamsOptionDownload = Contunhar amb aqueste navegador
|
||||
downloadFirefoxPromo = Lo nòu { -firefox } vos provesís { -send-short-brand }.
|
||||
# the next line after the colon contains a file name
|
||||
shareLinkDescription = Partejatz lo ligam cap a vòstre fichièr :
|
||||
shareLinkButton = Partejar lo ligam
|
||||
# $name is the name of the file
|
||||
shareMessage = Telecargar « { $name } » amb { -send-brand } : un biais simple e segur de partejar de fichièrs.
|
||||
trailheadPromo = Existís un biais de protegir vòstra vida privada. Rejonhètz Firefox.
|
||||
learnMore = Ne saber mai.
|
||||
@@ -151,3 +151,5 @@ shareLinkDescription = ਆਪਣੀ ਫਾਇਲ ਲਈ ਲਿੰਕ ਸਾਂ
|
||||
shareLinkButton = ਲਿੰਕ ਸਾਂਝਾ ਕਰੋ
|
||||
# $name is the name of the file
|
||||
shareMessage = { -send-brand } ਨਾਲ "{ $name }" ਡਾਊਨਲੋਡ ਕਰੋ: ਸੌਖਾ, ਸੁਰੱਖਿਅਤ ਫਾਇਲ ਸਾਂਝਾ ਕਰਨਾ
|
||||
trailheadPromo = ਤੁਹਾਡੀ ਪਰਦੇਦਾਰੀ ਦੀ ਸੁਰੱਖਿਆ ਦਾ ਢੰਗ ਹੈ। ਫਾਇਰਫਾਕਸ ਨਾਲ ਜੁੜੋ।
|
||||
learnMore = ਹੋਰ ਸਿੱਖੋ
|
||||
|
||||
@@ -54,7 +54,7 @@ passwordSetError = Essa senha não pôde ser definida
|
||||
-firefox = Firefox
|
||||
-mozilla = Mozilla
|
||||
introTitle = Compartilhamento de arquivos fácil e privativo
|
||||
introDescription = O { -send-brand } permite compartilhar arquivos com criptografia ponto a ponto e um link que expira automaticamente. Assim você pode manter o que compartilha privativo e ter certeza que suas coisas não ficarão online para sempre.
|
||||
introDescription = O { -send-brand } permite compartilhar arquivos com criptografia de ponta a ponta e um link que expira automaticamente. Assim você pode manter o que compartilha privativo e ter certeza que suas coisas não ficarão online para sempre.
|
||||
notifyUploadEncryptDone = Seu arquivo foi criptografado e está pronto para ser enviado
|
||||
# downloadCount is from the downloadCount string and timespan is a timespanMinutes string. ex. 'Expires after 2 downloads or 25 minutes'
|
||||
archiveExpiryInfo = Expirar após { $downloadCount } ou { $timespan }
|
||||
@@ -94,7 +94,7 @@ totalSize = Tamanho total: { $size }
|
||||
copyLinkDescription = Copie o link para compartilhar seu arquivo:
|
||||
copyLinkButton = Copiar link
|
||||
downloadTitle = Baixar arquivos
|
||||
downloadDescription = Este arquivo foi compartilhado via { -send-brand } com criptografia ponto a ponto e um link que expira automaticamente.
|
||||
downloadDescription = Este arquivo foi compartilhado via { -send-brand } com criptografia de ponta a ponta e um link que expira automaticamente.
|
||||
trySendDescription = Experimente o { -send-brand } para compartilhamento de arquivos simples e seguro.
|
||||
# count will always be > 10
|
||||
tooManyFiles =
|
||||
@@ -127,17 +127,17 @@ emailPlaceholder = Informe seu e-mail
|
||||
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
|
||||
signInSizeBump = Entre na sua conta para enviar até { $size }
|
||||
signInOnlyButton = Entrar
|
||||
accountBenefitTitle = Crie uma Conta { -firefox } ou entre na sua conta
|
||||
accountBenefitTitle = Crie uma Conta { -firefox } ou entre se já tiver
|
||||
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
|
||||
accountBenefitLargeFiles = Compartilhe arquivos até { $size }
|
||||
accountBenefitDownloadCount = Compartilhe arquivos com mais pessoas
|
||||
accountBenefitLargeFiles = Compartilhe arquivos até { $size }.
|
||||
accountBenefitDownloadCount = Compartilhe arquivos com mais pessoas.
|
||||
accountBenefitTimeLimit =
|
||||
{ $count ->
|
||||
[one] Mantenha links ativos por até 1 dia
|
||||
*[other] Mantenha links ativos por até { $count } dias
|
||||
[one] Mantenha links ativos por até 1 dia.
|
||||
*[other] Mantenha links ativos por até { $count } dias.
|
||||
}
|
||||
accountBenefitSync = Gerencie arquivos compartilhados a partir de qualquer dispositivo
|
||||
accountBenefitMoz = Conheça outros serviços da { -mozilla }
|
||||
accountBenefitSync = Gerencie arquivos compartilhados a partir de qualquer dispositivo.
|
||||
accountBenefitMoz = Conheça outros serviços da { -mozilla }.
|
||||
signOut = Sair
|
||||
okButton = OK
|
||||
downloadingTitle = Baixando
|
||||
|
||||
@@ -89,6 +89,7 @@ totalSize = మొత్తం పరిమాణం: { $size }
|
||||
copyLinkDescription = మీ ఫైలును భాగస్వామ్యం చేయడానికి ఈ లంకెను నకలు చేయండి:
|
||||
copyLinkButton = లంకెను నకలుతీయి
|
||||
downloadTitle = ఫైళ్లను దింపుకోండి
|
||||
expiredTitle = ఈ లంకె గడువు ముగిసింది.
|
||||
downloadFirefox = { -firefox } ను దింపుకోండి
|
||||
legalTitle = { -send-short-brand } గోప్యతా నోటీసు
|
||||
legalDateStamp = వెర్షన్ 1.0, మార్చి 12, 2019 నాటిది
|
||||
@@ -96,6 +97,11 @@ legalDateStamp = వెర్షన్ 1.0, మార్చి 12, 2019 నా
|
||||
expiresDaysHoursMinutes = { $days }d { $hours }h { $minutes }m
|
||||
addFilesButton = ఎక్కించడానికి ఫైళ్ళను ఎంచుకోండి
|
||||
uploadButton = ఎక్కించు
|
||||
# the first part of the string 'Drag and drop files or click to send up to 1GB'
|
||||
dragAndDropFiles = ఫైళ్ళను లాగండి మరియు వదలండి
|
||||
# the second part of the string 'Drag and drop files or click to send up to 1GB'
|
||||
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
|
||||
orClickWithSize = లేదా { $size } వరకు పంపడానికి నొక్కండి
|
||||
addPassword = సంకేతపదంతో రక్షించండి
|
||||
emailPlaceholder = ఈ ఈమెయిలును ఇవ్వండి
|
||||
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
|
||||
@@ -105,6 +111,7 @@ accountBenefitTitle = ఒక { -firefox } ఖాతాని సృష్టి
|
||||
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
|
||||
accountBenefitLargeFiles = { $size } పరిమాణం ఫైళ్ళ వరకు పంచుకోండి
|
||||
accountBenefitDownloadCount = ఫైళ్లను ఎక్కువ మందితో పంచుకోండి
|
||||
accountBenefitSync = ఏదైనా పరికరం నుండి పంచుకున్న ఫైళ్ళను నిర్వహించండి
|
||||
signOut = నిష్క్రమించు
|
||||
okButton = సరే
|
||||
downloadingTitle = దింపుకుంటోంది
|
||||
|
||||
@@ -87,7 +87,7 @@ totalSize = Tổng kích thước: { $size }
|
||||
# the next line after the colon contains a file name
|
||||
copyLinkDescription = Sao chép liên kết để chia sẻ tập tin của bạn:
|
||||
copyLinkButton = Sao chép liên kết
|
||||
downloadTitle = Tải tập tin
|
||||
downloadTitle = Tải xuống tập tin
|
||||
downloadDescription = Tập tin này đã được chia sẻ qua { -send-brand } với mã hóa đầu cuối và liên kết tự động hết hạn.
|
||||
trySendDescription = Hãy thử { -send-brand } để chia sẻ tập tin đơn giản, an toàn.
|
||||
# count will always be > 10
|
||||
|
||||
13
scripts/sync-npm-dependencies.sh
Executable file
13
scripts/sync-npm-dependencies.sh
Executable file
@@ -0,0 +1,13 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "checking package-lock.json for changes"
|
||||
IFS=' '
|
||||
read -ra G_PARAMS <<< "$HUSKY_GIT_PARAMS"
|
||||
PREV=${G_PARAMS[0]}
|
||||
NEXT=${G_PARAMS[1]}
|
||||
if [ "$PREV" != "$NEXT" ]; then
|
||||
DIFF=$(git diff $PREV $NEXT package-lock.json)
|
||||
if [ "$DIFF" != "" ]; then
|
||||
npm install
|
||||
fi
|
||||
fi
|
||||
@@ -3,7 +3,7 @@ const routes = require('../routes');
|
||||
const pages = require('../routes/pages');
|
||||
const tests = require('../../test/frontend/routes');
|
||||
const express = require('express');
|
||||
const expressWs = require('express-ws');
|
||||
const expressWs = require('@dannycoates/express-ws');
|
||||
const morgan = require('morgan');
|
||||
const config = require('../config');
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
const express = require('express');
|
||||
const path = require('path');
|
||||
const Raven = require('raven');
|
||||
const Sentry = require('@sentry/node');
|
||||
const config = require('../config');
|
||||
const routes = require('../routes');
|
||||
const pages = require('../routes/pages');
|
||||
const expressWs = require('express-ws');
|
||||
const expressWs = require('@dannycoates/express-ws');
|
||||
|
||||
if (config.sentry_dsn) {
|
||||
Raven.config(config.sentry_dsn).install();
|
||||
Sentry.init({ dsn: config.sentry_dsn });
|
||||
}
|
||||
|
||||
const app = express();
|
||||
|
||||
@@ -2,7 +2,7 @@ const assets = require('../../common/assets');
|
||||
const routes = require('../routes');
|
||||
const pages = require('../routes/pages');
|
||||
const tests = require('../../test/frontend/routes');
|
||||
const expressWs = require('express-ws');
|
||||
const expressWs = require('@dannycoates/express-ws');
|
||||
|
||||
module.exports = function(app, devServer) {
|
||||
assets.setMiddleware(devServer.middleware);
|
||||
|
||||
@@ -8,12 +8,10 @@ if (config.sentry_id) {
|
||||
//eslint-disable-next-line node/no-missing-require
|
||||
const version = require('../dist/version.json');
|
||||
sentry = `
|
||||
var RAVEN_CONFIG = {
|
||||
var SENTRY_CONFIG = {
|
||||
dsn: '${config.sentry_id}',
|
||||
release: '${version.version}',
|
||||
tags: {
|
||||
commit: '${version.commit}'
|
||||
},
|
||||
dataCallback: function (data) {
|
||||
beforeSend: function (data) {
|
||||
var hash = window.location.hash;
|
||||
if (hash) {
|
||||
return JSON.parse(JSON.stringify(data).replace(new RegExp(hash.slice(1), 'g'), ''));
|
||||
@@ -21,7 +19,6 @@ var RAVEN_CONFIG = {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
var SENTRY_ID = '${config.sentry_id}';
|
||||
`;
|
||||
}
|
||||
|
||||
|
||||
@@ -67,7 +67,10 @@ module.exports = function(app) {
|
||||
}
|
||||
app.use(function(req, res, next) {
|
||||
res.set('Pragma', 'no-cache');
|
||||
res.set('Cache-Control', 'no-cache');
|
||||
res.set(
|
||||
'Cache-Control',
|
||||
'private, no-cache, no-store, must-revalidate, max-age=0'
|
||||
);
|
||||
next();
|
||||
});
|
||||
app.use(bodyParser.json());
|
||||
|
||||
@@ -3,12 +3,11 @@ const storage = require('../storage');
|
||||
const config = require('../config');
|
||||
const mozlog = require('../log');
|
||||
const Limiter = require('../limiter');
|
||||
const wsStream = require('websocket-stream/stream');
|
||||
const fxa = require('../fxa');
|
||||
const { statUploadEvent } = require('../amplitude');
|
||||
const { encryptedSize } = require('../../app/utils');
|
||||
|
||||
const { Duplex } = require('stream');
|
||||
const { Transform } = require('stream');
|
||||
|
||||
const log = mozlog('send.upload');
|
||||
|
||||
@@ -76,25 +75,19 @@ module.exports = function(ws, req) {
|
||||
})
|
||||
);
|
||||
const limiter = new Limiter(encryptedSize(maxFileSize));
|
||||
const flowControl = new Duplex({
|
||||
read() {
|
||||
ws.resume();
|
||||
},
|
||||
write(chunk, encoding, callback) {
|
||||
const eof = new Transform({
|
||||
transform: function(chunk, encoding, callback) {
|
||||
if (chunk.length === 1 && chunk[0] === 0) {
|
||||
this.push(null);
|
||||
} else {
|
||||
if (!this.push(chunk)) {
|
||||
ws.pause();
|
||||
}
|
||||
this.push(chunk);
|
||||
}
|
||||
callback();
|
||||
}
|
||||
});
|
||||
const wsStream = ws.constructor.createWebSocketStream(ws);
|
||||
|
||||
fileStream = wsStream(ws, { binary: true })
|
||||
.pipe(flowControl)
|
||||
.pipe(limiter); // limiter needs to be the last in the chain
|
||||
fileStream = wsStream.pipe(eof).pipe(limiter); // limiter needs to be the last in the chain
|
||||
|
||||
await storage.set(newId, fileStream, meta, timeLimit);
|
||||
|
||||
@@ -126,8 +119,8 @@ module.exports = function(ws, req) {
|
||||
error: e === 'limit' ? 413 : 500
|
||||
})
|
||||
);
|
||||
ws.close();
|
||||
}
|
||||
}
|
||||
ws.close();
|
||||
});
|
||||
};
|
||||
|
||||
@@ -22,7 +22,7 @@ class GCSStorage {
|
||||
.pipe(
|
||||
this.bucket.file(id).createWriteStream({
|
||||
validation: false,
|
||||
resumable: false
|
||||
resumable: true
|
||||
})
|
||||
)
|
||||
.on('error', reject)
|
||||
|
||||
@@ -6,7 +6,7 @@ module.exports = {
|
||||
const webpack = require('webpack');
|
||||
const middleware = require('webpack-dev-middleware');
|
||||
const express = require('express');
|
||||
const expressWs = require('express-ws');
|
||||
const expressWs = require('@dannycoates/express-ws');
|
||||
const assets = require('../common/assets');
|
||||
const routes = require('../server/routes');
|
||||
const tests = require('./frontend/routes');
|
||||
|
||||
@@ -67,7 +67,7 @@ const serviceWorker = {
|
||||
},
|
||||
{
|
||||
// loads all assets from assets/ for use by common/assets.js
|
||||
test: require.resolve('./build/generate_asset_map.js'),
|
||||
test: require.resolve('./common/generate_asset_map.js'),
|
||||
use: ['babel-loader', 'val-loader']
|
||||
}
|
||||
]
|
||||
@@ -114,6 +114,7 @@ const web = {
|
||||
exclude: [
|
||||
path.resolve(__dirname, 'node_modules/crc'),
|
||||
path.resolve(__dirname, 'node_modules/@fluent'),
|
||||
path.resolve(__dirname, 'node_modules/@sentry'),
|
||||
path.resolve(__dirname, 'node_modules/tslib'),
|
||||
path.resolve(__dirname, 'node_modules/webcrypto-core')
|
||||
],
|
||||
@@ -175,7 +176,7 @@ const web = {
|
||||
},
|
||||
{
|
||||
// loads all assets from assets/ for use by common/assets.js
|
||||
test: require.resolve('./build/generate_asset_map.js'),
|
||||
test: require.resolve('./common/generate_asset_map.js'),
|
||||
use: ['babel-loader', 'val-loader']
|
||||
}
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user