mirror of
https://gitlab.com/timvisee/send.git
synced 2025-12-06 22:20:55 +03:00
Compare commits
106 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0f8c3caf18 | ||
|
|
3a7677b46d | ||
|
|
3fd64d9956 | ||
|
|
1a4cea7b4f | ||
|
|
bbb1c42641 | ||
|
|
7ce2320eda | ||
|
|
1729b30f89 | ||
|
|
25d6595d5e | ||
|
|
3b31b9d65b | ||
|
|
e9e64fed3f | ||
|
|
3b88ea9b1c | ||
|
|
623f76fa6c | ||
|
|
19efcb1a0d | ||
|
|
31c8916622 | ||
|
|
7a0b189a1d | ||
|
|
fa0d56d57a | ||
|
|
85670bbc6a | ||
|
|
fc9a85b6ad | ||
|
|
8760b132da | ||
|
|
d7084829c3 | ||
|
|
243d72eed5 | ||
|
|
aa60e97d5d | ||
|
|
4ae12db99c | ||
|
|
98ad058e2e | ||
|
|
58cc381abf | ||
|
|
d039c38f00 | ||
|
|
81f3347981 | ||
|
|
b96d2949f7 | ||
|
|
a2e745a349 | ||
|
|
0fe02b18ce | ||
|
|
655eb8c253 | ||
|
|
d9356f8171 | ||
|
|
be7d23163c | ||
|
|
7ac2e57484 | ||
|
|
727ea1283a | ||
|
|
3314057059 | ||
|
|
df1b00fa2c | ||
|
|
6434329f61 | ||
|
|
454853dc93 | ||
|
|
b663bf94e4 | ||
|
|
081cf081c5 | ||
|
|
f86b164c62 | ||
|
|
92b79e8272 | ||
|
|
335086c9d7 | ||
|
|
60806a3954 | ||
|
|
e0e96e7b9b | ||
|
|
cda35eb127 | ||
|
|
bf1ef345a2 | ||
|
|
e54ae7a51f | ||
|
|
a5a2d654ae | ||
|
|
b6340d8657 | ||
|
|
cdb87e2ac2 | ||
|
|
a0baed4e14 | ||
|
|
573a2d4fb1 | ||
|
|
df3ae9e22d | ||
|
|
52bffa024e | ||
|
|
459499d5f5 | ||
|
|
7cc94f6829 | ||
|
|
53d5b08559 | ||
|
|
c517b074f1 | ||
|
|
503ba43ebc | ||
|
|
b0755f4bc5 | ||
|
|
89ece1ec4c | ||
|
|
9fcaefbd99 | ||
|
|
81f33c7bbd | ||
|
|
0ce1bf2360 | ||
|
|
bb10c1aa9d | ||
|
|
b2c1daa6c7 | ||
|
|
da4338ed69 | ||
|
|
1849d712b1 | ||
|
|
28a7e0f717 | ||
|
|
ddbfc79cae | ||
|
|
ec8900d38f | ||
|
|
8aadd5d775 | ||
|
|
268f9306d9 | ||
|
|
866552254c | ||
|
|
42f87424c6 | ||
|
|
4899fb27ec | ||
|
|
c2c8d2bdaa | ||
|
|
daa373967f | ||
|
|
dccc9bfbcd | ||
|
|
f51a873752 | ||
|
|
bad5efc5e8 | ||
|
|
edf8384348 | ||
|
|
65c2f0e191 | ||
|
|
427a09296c | ||
|
|
ba11d62003 | ||
|
|
900dbe781e | ||
|
|
ee19aa8f2e | ||
|
|
e9cff66852 | ||
|
|
f63894bea7 | ||
|
|
35a285d71a | ||
|
|
ba80b01150 | ||
|
|
c9be359db4 | ||
|
|
46a3933dbb | ||
|
|
7b4060f9e1 | ||
|
|
beb3a6e67b | ||
|
|
b393c35284 | ||
|
|
ad371553ba | ||
|
|
0107fb9486 | ||
|
|
7cf70317e8 | ||
|
|
7d8aaac5d2 | ||
|
|
2b5f7d126f | ||
|
|
3cbc71ca1b | ||
|
|
9c4ac38a6c | ||
|
|
9ae64a97ba |
@@ -1,10 +1,10 @@
|
||||
import hash from 'string-hash';
|
||||
|
||||
const experiments = {
|
||||
'SyI-hI7gT9agiH-f3f0BYg': {
|
||||
id: 'SyI-hI7gT9agiH-f3f0BYg',
|
||||
XnN0idVWSxO6A0kiNkxzGw: {
|
||||
id: 'XnN0idVWSxO6A0kiNkxzGw',
|
||||
run: function(variant, state, emitter) {
|
||||
state.promo = variant === 1 ? 'body' : 'header';
|
||||
state.promo = variant === 1 ? 'blue' : 'grey';
|
||||
emitter.emit('render');
|
||||
},
|
||||
eligible: function() {
|
||||
|
||||
@@ -97,6 +97,13 @@ export default function(state, emitter) {
|
||||
lastRender = Date.now();
|
||||
});
|
||||
|
||||
emitter.on('changeLimit', async ({ file, value }) => {
|
||||
await FileSender.changeLimit(file.id, file.ownerToken, value);
|
||||
file.dlimit = value;
|
||||
state.storage.writeFiles();
|
||||
metrics.changedDownloadLimit(file);
|
||||
});
|
||||
|
||||
emitter.on('delete', async ({ file, location }) => {
|
||||
try {
|
||||
metrics.deletedUpload({
|
||||
@@ -108,7 +115,7 @@ export default function(state, emitter) {
|
||||
location
|
||||
});
|
||||
state.storage.remove(file.id);
|
||||
await FileSender.delete(file.id, file.deleteToken);
|
||||
await FileSender.delete(file.id, file.ownerToken);
|
||||
} catch (e) {
|
||||
state.raven.captureException(e);
|
||||
}
|
||||
|
||||
@@ -116,7 +116,8 @@ export default class FileReceiver extends Nanobus {
|
||||
// TODO
|
||||
}
|
||||
|
||||
fetchMetadata(sig) {
|
||||
async fetchMetadata(nonce) {
|
||||
const authHeader = await this.getAuthHeader(nonce);
|
||||
return new Promise((resolve, reject) => {
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.onreadystatechange = () => {
|
||||
@@ -126,13 +127,15 @@ export default class FileReceiver extends Nanobus {
|
||||
if (xhr.status === 200) {
|
||||
return resolve(xhr.response);
|
||||
}
|
||||
reject(new Error(xhr.status));
|
||||
const err = new Error(xhr.status);
|
||||
err.nonce = nonce;
|
||||
reject(err);
|
||||
}
|
||||
};
|
||||
xhr.onerror = () => reject(new Error(0));
|
||||
xhr.ontimeout = () => reject(new Error(0));
|
||||
xhr.open('get', `/api/metadata/${this.file.id}`);
|
||||
xhr.setRequestHeader('Authorization', `send-v1 ${arrayToB64(sig)}`);
|
||||
xhr.setRequestHeader('Authorization', authHeader);
|
||||
xhr.responseType = 'json';
|
||||
xhr.timeout = 2000;
|
||||
xhr.send();
|
||||
@@ -140,16 +143,18 @@ export default class FileReceiver extends Nanobus {
|
||||
}
|
||||
|
||||
async getMetadata(nonce) {
|
||||
let data = null;
|
||||
try {
|
||||
const authKey = await this.authKeyPromise;
|
||||
const sig = await window.crypto.subtle.sign(
|
||||
{
|
||||
name: 'HMAC'
|
||||
},
|
||||
authKey,
|
||||
b64ToArray(nonce)
|
||||
);
|
||||
const data = await this.fetchMetadata(new Uint8Array(sig));
|
||||
try {
|
||||
data = await this.fetchMetadata(nonce);
|
||||
} catch (e) {
|
||||
if (e.message === '401' && nonce !== e.nonce) {
|
||||
// allow one retry for changed nonce
|
||||
data = await this.fetchMetadata(e.nonce);
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
const metaKey = await this.metaKeyPromise;
|
||||
const json = await window.crypto.subtle.decrypt(
|
||||
{
|
||||
@@ -174,7 +179,8 @@ export default class FileReceiver extends Nanobus {
|
||||
}
|
||||
}
|
||||
|
||||
downloadFile(sig) {
|
||||
async downloadFile(nonce) {
|
||||
const authHeader = await this.getAuthHeader(nonce);
|
||||
return new Promise((resolve, reject) => {
|
||||
const xhr = new XMLHttpRequest();
|
||||
|
||||
@@ -190,9 +196,10 @@ export default class FileReceiver extends Nanobus {
|
||||
reject(new Error('notfound'));
|
||||
return;
|
||||
}
|
||||
|
||||
if (xhr.status !== 200) {
|
||||
return reject(new Error(xhr.status));
|
||||
const err = new Error(xhr.status);
|
||||
err.nonce = xhr.getResponseHeader('WWW-Authenticate').split(' ')[1];
|
||||
return reject(err);
|
||||
}
|
||||
|
||||
const blob = new Blob([xhr.response]);
|
||||
@@ -205,26 +212,39 @@ export default class FileReceiver extends Nanobus {
|
||||
};
|
||||
|
||||
xhr.open('get', this.url);
|
||||
xhr.setRequestHeader('Authorization', `send-v1 ${arrayToB64(sig)}`);
|
||||
xhr.setRequestHeader('Authorization', authHeader);
|
||||
xhr.responseType = 'blob';
|
||||
xhr.send();
|
||||
});
|
||||
}
|
||||
|
||||
async getAuthHeader(nonce) {
|
||||
const authKey = await this.authKeyPromise;
|
||||
const sig = await window.crypto.subtle.sign(
|
||||
{
|
||||
name: 'HMAC'
|
||||
},
|
||||
authKey,
|
||||
b64ToArray(nonce)
|
||||
);
|
||||
return `send-v1 ${arrayToB64(new Uint8Array(sig))}`;
|
||||
}
|
||||
|
||||
async download(nonce) {
|
||||
this.state = 'downloading';
|
||||
this.emit('progress', this.progress);
|
||||
try {
|
||||
const encryptKey = await this.encryptKeyPromise;
|
||||
const authKey = await this.authKeyPromise;
|
||||
const sig = await window.crypto.subtle.sign(
|
||||
{
|
||||
name: 'HMAC'
|
||||
},
|
||||
authKey,
|
||||
b64ToArray(nonce)
|
||||
);
|
||||
const ciphertext = await this.downloadFile(new Uint8Array(sig));
|
||||
let ciphertext = null;
|
||||
try {
|
||||
ciphertext = await this.downloadFile(nonce);
|
||||
} catch (e) {
|
||||
if (e.message === '401' && nonce !== e.nonce) {
|
||||
ciphertext = await this.downloadFile(e.nonce);
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
this.msg = 'decryptingFile';
|
||||
this.emit('decrypting');
|
||||
const plaintext = await window.crypto.subtle.decrypt(
|
||||
|
||||
@@ -1,6 +1,44 @@
|
||||
import Nanobus from 'nanobus';
|
||||
import { arrayToB64, b64ToArray, bytes } from './utils';
|
||||
|
||||
async function getAuthHeader(authKey, nonce) {
|
||||
const sig = await window.crypto.subtle.sign(
|
||||
{
|
||||
name: 'HMAC'
|
||||
},
|
||||
authKey,
|
||||
b64ToArray(nonce)
|
||||
);
|
||||
return `send-v1 ${arrayToB64(new Uint8Array(sig))}`;
|
||||
}
|
||||
|
||||
async function sendPassword(file, authKey, rawAuth) {
|
||||
const authHeader = await getAuthHeader(authKey, file.nonce);
|
||||
return new Promise((resolve, reject) => {
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.onreadystatechange = () => {
|
||||
if (xhr.readyState === XMLHttpRequest.DONE) {
|
||||
if (xhr.status === 200) {
|
||||
return resolve(xhr.response);
|
||||
}
|
||||
if (xhr.status === 401) {
|
||||
const nonce = xhr.getResponseHeader('WWW-Authenticate').split(' ')[1];
|
||||
file.nonce = nonce;
|
||||
}
|
||||
reject(new Error(xhr.status));
|
||||
}
|
||||
};
|
||||
xhr.onerror = () => reject(new Error(0));
|
||||
xhr.ontimeout = () => reject(new Error(0));
|
||||
xhr.open('post', `/api/password/${file.id}`);
|
||||
xhr.setRequestHeader('Authorization', authHeader);
|
||||
xhr.setRequestHeader('Content-Type', 'application/json');
|
||||
xhr.responseType = 'json';
|
||||
xhr.timeout = 2000;
|
||||
xhr.send(JSON.stringify({ auth: arrayToB64(new Uint8Array(rawAuth)) }));
|
||||
});
|
||||
}
|
||||
|
||||
export default class FileSender extends Nanobus {
|
||||
constructor(file) {
|
||||
super('FileSender');
|
||||
@@ -35,7 +73,26 @@ export default class FileSender extends Nanobus {
|
||||
}
|
||||
};
|
||||
|
||||
xhr.send(JSON.stringify({ delete_token: token }));
|
||||
xhr.send(JSON.stringify({ owner_token: token }));
|
||||
});
|
||||
}
|
||||
|
||||
static changeLimit(id, owner_token, dlimit) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!id || !owner_token) {
|
||||
return reject();
|
||||
}
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.open('POST', `/api/params/${id}`);
|
||||
xhr.setRequestHeader('Content-Type', 'application/json');
|
||||
|
||||
xhr.onreadystatechange = () => {
|
||||
if (xhr.readyState === XMLHttpRequest.DONE) {
|
||||
resolve();
|
||||
}
|
||||
};
|
||||
|
||||
xhr.send(JSON.stringify({ owner_token, dlimit }));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -100,7 +157,7 @@ export default class FileSender extends Nanobus {
|
||||
url: responseObj.url,
|
||||
id: responseObj.id,
|
||||
secretKey: arrayToB64(this.rawSecret),
|
||||
deleteToken: responseObj.delete,
|
||||
ownerToken: responseObj.owner,
|
||||
nonce
|
||||
});
|
||||
}
|
||||
@@ -229,13 +286,6 @@ export default class FileSender extends Nanobus {
|
||||
true,
|
||||
['sign']
|
||||
);
|
||||
const sig = await window.crypto.subtle.sign(
|
||||
{
|
||||
name: 'HMAC'
|
||||
},
|
||||
authKey,
|
||||
b64ToArray(file.nonce)
|
||||
);
|
||||
const pwdKey = await window.crypto.subtle.importKey(
|
||||
'raw',
|
||||
encoder.encode(password),
|
||||
@@ -259,33 +309,14 @@ export default class FileSender extends Nanobus {
|
||||
['sign']
|
||||
);
|
||||
const rawAuth = await window.crypto.subtle.exportKey('raw', newAuthKey);
|
||||
return new Promise((resolve, reject) => {
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.onreadystatechange = () => {
|
||||
if (xhr.readyState === XMLHttpRequest.DONE) {
|
||||
if (xhr.status === 200) {
|
||||
return resolve(xhr.response);
|
||||
}
|
||||
if (xhr.status === 401) {
|
||||
const nonce = xhr
|
||||
.getResponseHeader('WWW-Authenticate')
|
||||
.split(' ')[1];
|
||||
file.nonce = nonce;
|
||||
}
|
||||
reject(new Error(xhr.status));
|
||||
}
|
||||
};
|
||||
xhr.onerror = () => reject(new Error(0));
|
||||
xhr.ontimeout = () => reject(new Error(0));
|
||||
xhr.open('post', `/api/password/${file.id}`);
|
||||
xhr.setRequestHeader(
|
||||
'Authorization',
|
||||
`send-v1 ${arrayToB64(new Uint8Array(sig))}`
|
||||
);
|
||||
xhr.setRequestHeader('Content-Type', 'application/json');
|
||||
xhr.responseType = 'json';
|
||||
xhr.timeout = 2000;
|
||||
xhr.send(JSON.stringify({ auth: arrayToB64(new Uint8Array(rawAuth)) }));
|
||||
});
|
||||
try {
|
||||
await sendPassword(file, authKey, rawAuth);
|
||||
} catch (e) {
|
||||
if (e.message === '401' && file.nonce !== e.nonce) {
|
||||
await sendPassword(file, authKey, rawAuth);
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import 'fluent-intl-polyfill';
|
||||
import app from './routes';
|
||||
import locale from '../common/locales';
|
||||
import fileManager from './fileManager';
|
||||
|
||||
@@ -205,6 +205,16 @@ function stoppedUpload(params) {
|
||||
});
|
||||
}
|
||||
|
||||
function changedDownloadLimit(params) {
|
||||
return sendEvent('sender', 'download-limit-changed', {
|
||||
cm1: params.size,
|
||||
cm5: storage.totalUploads,
|
||||
cm6: storage.files.length,
|
||||
cm7: storage.totalDownloads,
|
||||
cm8: params.dlimit
|
||||
});
|
||||
}
|
||||
|
||||
function completedDownload(params) {
|
||||
return sendEvent('recipient', 'download-stopped', {
|
||||
cm1: params.size,
|
||||
@@ -272,6 +282,7 @@ export {
|
||||
cancelledUpload,
|
||||
stoppedUpload,
|
||||
completedUpload,
|
||||
changedDownloadLimit,
|
||||
deletedUpload,
|
||||
startedDownload,
|
||||
cancelledDownload,
|
||||
|
||||
@@ -10,7 +10,7 @@ const app = choo();
|
||||
function body(template) {
|
||||
return function(state, emit) {
|
||||
const b = html`<body>
|
||||
${state.promo === 'header' ? fxPromo(state, emit) : ''}
|
||||
${state.promo ? fxPromo(state, emit) : ''}
|
||||
${header(state)}
|
||||
<div class="all">
|
||||
<noscript>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
const html = require('choo/html');
|
||||
const progress = require('./progress');
|
||||
const { fadeOut } = require('../utils');
|
||||
const fxPromo = require('./fxPromo');
|
||||
|
||||
module.exports = function(state, emit) {
|
||||
const div = html`
|
||||
@@ -21,7 +20,6 @@ module.exports = function(state, emit) {
|
||||
sendNew
|
||||
}>${state.translate('sendYourFilesLink')}</a>
|
||||
</div>
|
||||
${state.promo === 'body' ? fxPromo(state, emit) : ''}
|
||||
</div>
|
||||
`;
|
||||
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
const html = require('choo/html');
|
||||
const progress = require('./progress');
|
||||
const { bytes } = require('../utils');
|
||||
const fxPromo = require('./fxPromo');
|
||||
|
||||
module.exports = function(state, emit) {
|
||||
module.exports = function(state) {
|
||||
const transfer = state.transfer;
|
||||
const div = html`
|
||||
<div id="page-one">
|
||||
@@ -24,7 +23,6 @@ module.exports = function(state, emit) {
|
||||
)}</div>
|
||||
</div>
|
||||
</div>
|
||||
${state.promo === 'body' ? fxPromo(state, emit) : ''}
|
||||
</div>
|
||||
`;
|
||||
|
||||
|
||||
@@ -18,7 +18,9 @@ module.exports = function(file, state, emit) {
|
||||
const remaining = timeLeft(ttl) || state.translate('linkExpiredAlt');
|
||||
const row = html`
|
||||
<tr id="${file.id}">
|
||||
<td class="overflow-col" title="${file.name}">${file.name}</td>
|
||||
<td class="overflow-col" title="${
|
||||
file.name
|
||||
}"><a class="link" href="/share/${file.id}">${file.name}</a></td>
|
||||
<td class="center-col">
|
||||
<img onclick=${copyClick} src="${assets.get(
|
||||
'copy-16.svg'
|
||||
|
||||
@@ -18,6 +18,9 @@ module.exports = function(state) {
|
||||
<a href="https://www.mozilla.org/privacy/websites/#cookies">${state.translate(
|
||||
'footerLinkCookies'
|
||||
)}</a>
|
||||
<a href="https://www.mozilla.org/about/legal/report-infringement/">${state.translate(
|
||||
'reportIPInfringement'
|
||||
)}</a>
|
||||
</div>
|
||||
<div class="social-links">
|
||||
<a href="https://github.com/mozilla/send" role="presentation"><img class="github" src="${assets.get(
|
||||
|
||||
@@ -19,8 +19,10 @@ module.exports = function(state, emit) {
|
||||
emit('exit', evt);
|
||||
}
|
||||
|
||||
const classes = state.promo === 'blue' ? 'banner banner-blue' : 'banner';
|
||||
|
||||
return html`
|
||||
<div class="banner">
|
||||
<div class="${classes}">
|
||||
<div>
|
||||
<img
|
||||
src="${assets.get('firefox_logo-only.svg')}"
|
||||
|
||||
@@ -1,5 +1,16 @@
|
||||
const html = require('choo/html');
|
||||
const assets = require('../../common/assets');
|
||||
/*
|
||||
The current weback config uses package.json to generate
|
||||
version.json for /__version__ meaning `require` returns the
|
||||
string 'version.json' in the frontend context but the json
|
||||
on the server.
|
||||
|
||||
We want `version` to be constant at build time so this file
|
||||
has a custom loader (/build/version_loader.js) just to replace
|
||||
string with the value from package.json. 🤢
|
||||
*/
|
||||
const version = require('../../package.json').version || 'VERSION';
|
||||
|
||||
module.exports = function(state) {
|
||||
return html`<header class="header">
|
||||
@@ -14,8 +25,9 @@ module.exports = function(state) {
|
||||
<div>${state.translate('siteSubtitle')}</div>
|
||||
</div>
|
||||
</div>
|
||||
<a href="https://qsurvey.mozilla.com/s3/txp-firefox-send" rel="noreferrer noopener" class="feedback" target="_blank">${state.translate(
|
||||
'siteFeedback'
|
||||
)}</a>
|
||||
<a href="https://qsurvey.mozilla.com/s3/txp-firefox-send?ver=${version}"
|
||||
rel="noreferrer noopener"
|
||||
class="feedback"
|
||||
target="_blank">${state.translate('siteFeedback')}</a>
|
||||
</header>`;
|
||||
};
|
||||
|
||||
@@ -3,7 +3,6 @@ const assets = require('../../common/assets');
|
||||
const notFound = require('./notFound');
|
||||
const downloadPassword = require('./downloadPassword');
|
||||
const { bytes } = require('../utils');
|
||||
const fxPromo = require('./fxPromo');
|
||||
|
||||
function getFileFromDOM() {
|
||||
const el = document.getElementById('dl-file');
|
||||
@@ -62,7 +61,6 @@ module.exports = function(state, emit) {
|
||||
</div>
|
||||
<a class="send-new" href="/">${state.translate('sendYourFilesLink')}</a>
|
||||
</div>
|
||||
${state.promo === 'body' ? fxPromo(state, emit) : ''}
|
||||
</div>
|
||||
`;
|
||||
|
||||
|
||||
56
app/templates/selectbox.js
Normal file
56
app/templates/selectbox.js
Normal file
@@ -0,0 +1,56 @@
|
||||
const html = require('choo/html');
|
||||
|
||||
module.exports = function(selected, options, translate, changed) {
|
||||
const id = `select-${Math.random()}`;
|
||||
let x = selected;
|
||||
|
||||
function close() {
|
||||
const ul = document.getElementById(id);
|
||||
const body = document.querySelector('body');
|
||||
ul.classList.remove('active');
|
||||
body.removeEventListener('click', close);
|
||||
}
|
||||
|
||||
function toggle(event) {
|
||||
event.stopPropagation();
|
||||
const ul = document.getElementById(id);
|
||||
if (ul.classList.contains('active')) {
|
||||
close();
|
||||
} else {
|
||||
ul.classList.add('active');
|
||||
const body = document.querySelector('body');
|
||||
body.addEventListener('click', close);
|
||||
}
|
||||
}
|
||||
|
||||
function choose(event) {
|
||||
event.stopPropagation();
|
||||
const target = event.target;
|
||||
const value = +target.dataset.value;
|
||||
target.parentNode.previousSibling.firstElementChild.textContent = translate(
|
||||
value
|
||||
);
|
||||
if (x !== value) {
|
||||
x = value;
|
||||
changed(value);
|
||||
}
|
||||
close();
|
||||
}
|
||||
return html`
|
||||
<div class="selectbox">
|
||||
<div onclick=${toggle}>
|
||||
<span class="link">${translate(selected)}</span>
|
||||
<svg width="32" height="32">
|
||||
<polygon points="8 18 17 28 26 18" fill="#0094fb"/>
|
||||
</svg>
|
||||
</div>
|
||||
<ul id="${id}" class="selectOptions">
|
||||
${options.map(
|
||||
i =>
|
||||
html`<li class="selectOption" onclick=${choose} data-value="${i}">${
|
||||
i
|
||||
}</li>`
|
||||
)}
|
||||
</ul>
|
||||
</div>`;
|
||||
};
|
||||
@@ -2,6 +2,7 @@ const html = require('choo/html');
|
||||
const assets = require('../../common/assets');
|
||||
const notFound = require('./notFound');
|
||||
const uploadPassword = require('./uploadPassword');
|
||||
const selectbox = require('./selectbox');
|
||||
const { allowedCopy, delay, fadeOut } = require('../utils');
|
||||
|
||||
function passwordComplete(state, password) {
|
||||
@@ -14,6 +15,24 @@ function passwordComplete(state, password) {
|
||||
return el;
|
||||
}
|
||||
|
||||
function expireInfo(file, translate, emit) {
|
||||
const el = html([
|
||||
`<div>${translate('expireInfo', {
|
||||
downloadCount: '<select></select>',
|
||||
timespan: translate('timespanHours', { num: 24 })
|
||||
})}</div>`
|
||||
]);
|
||||
const select = el.querySelector('select');
|
||||
const options = [1, 2, 3, 4, 5, 20];
|
||||
const t = num => translate('downloadCount', { num });
|
||||
const changed = value => emit('changeLimit', { file, value });
|
||||
select.parentNode.replaceChild(
|
||||
selectbox(file.dlimit || 1, options, t, changed),
|
||||
select
|
||||
);
|
||||
return el;
|
||||
}
|
||||
|
||||
module.exports = function(state, emit) {
|
||||
const file = state.storage.getFileById(state.params.id);
|
||||
if (!file) {
|
||||
@@ -27,7 +46,7 @@ module.exports = function(state, emit) {
|
||||
: uploadPassword(state, emit);
|
||||
const div = html`
|
||||
<div id="share-link" class="fadeIn">
|
||||
<div class="title">${state.translate('uploadSuccessTimingHeader')}</div>
|
||||
<div class="title">${expireInfo(file, state.translate, emit)}</div>
|
||||
<div id="share-window">
|
||||
<div id="copy-text">
|
||||
${state.translate('copyUrlFormLabelWithName', {
|
||||
|
||||
@@ -29,7 +29,7 @@ module.exports = function(state) {
|
||||
<div class="description"><a href="https://github.com/mozilla/send/blob/master/docs/faq.md#why-is-my-browser-not-supported">${state.translate(
|
||||
'notSupportedLink'
|
||||
)}</a></div>
|
||||
<a id="dl-firefox" href="https://www.mozilla.org/firefox/new/?scene=2">
|
||||
<a id="dl-firefox" href="https://www.mozilla.org/firefox/new/?utm_campaign=send-acquisition&utm_medium=referral&utm_source=send.firefox.com">
|
||||
<img src="${assets.get(
|
||||
'firefox_logo-only.svg'
|
||||
)}" class="firefox-logo" alt="Firefox"/>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
const html = require('choo/html');
|
||||
const assets = require('../../common/assets');
|
||||
const fileList = require('./fileList');
|
||||
const fxPromo = require('./fxPromo');
|
||||
const { fadeOut } = require('../utils');
|
||||
|
||||
module.exports = function(state, emit) {
|
||||
@@ -36,7 +35,6 @@ module.exports = function(state, emit) {
|
||||
title="${state.translate('uploadPageBrowseButton1')}">
|
||||
${state.translate('uploadPageBrowseButton1')}</label>
|
||||
</div>
|
||||
${state.promo === 'body' ? fxPromo(state, emit) : ''}
|
||||
${fileList(state, emit)}
|
||||
</div>
|
||||
`;
|
||||
|
||||
@@ -236,6 +236,10 @@ a {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.upload-window.ondrag * {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.link {
|
||||
color: #0094fb;
|
||||
text-decoration: none;
|
||||
@@ -600,6 +604,7 @@ tbody {
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
font-size: 15px;
|
||||
padding-bottom: 4px;
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
white-space: nowrap;
|
||||
@@ -839,7 +844,11 @@ tbody {
|
||||
border: 1px solid #0297f8;
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
|
||||
/* Force flat button look */
|
||||
-webkit-appearance: none;
|
||||
font-size: 15px;
|
||||
padding-bottom: 3px;
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
white-space: nowrap;
|
||||
@@ -933,12 +942,11 @@ tbody {
|
||||
#addPasswordWrapper label {
|
||||
line-height: 20px;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
opacity: 0.6;
|
||||
color: #737373;
|
||||
}
|
||||
|
||||
#addPassword:checked + label {
|
||||
opacity: 1;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
#addPasswordWrapper label::before {
|
||||
@@ -980,6 +988,62 @@ tbody {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.banner-blue {
|
||||
background-color: #0098f7;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.banner-blue a {
|
||||
color: #fff;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.banner-blue a:hover {
|
||||
color: #eee;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.selectbox {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.selectSelected {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.selectOptions {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.selectOptions.active {
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
padding: 0;
|
||||
margin: 40px 0;
|
||||
background-color: white;
|
||||
border: 1px solid rgba(12, 12, 13, 0.3);
|
||||
border-radius: 4px;
|
||||
box-shadow: 1px 2px 4px rgba(12, 12, 13, 0.3);
|
||||
}
|
||||
|
||||
.selectOption {
|
||||
color: #737373;
|
||||
font-size: 12pt;
|
||||
list-style: none;
|
||||
user-select: none;
|
||||
white-space: nowrap;
|
||||
padding: 0 60px;
|
||||
border-bottom: 1px solid rgba(12, 12, 13, 0.3);
|
||||
}
|
||||
|
||||
.selectOption:hover {
|
||||
background-color: #f4f4f4;
|
||||
}
|
||||
|
||||
@media (max-device-width: 992px), (max-width: 992px) {
|
||||
.popup .popuptext {
|
||||
left: auto;
|
||||
|
||||
@@ -1,26 +1,45 @@
|
||||
const { MessageContext } = require('fluent');
|
||||
const fs = require('fs');
|
||||
|
||||
function toJSON(map) {
|
||||
return JSON.stringify(Array.from(map));
|
||||
}
|
||||
|
||||
function merge(m1, m2) {
|
||||
const result = new Map(m1);
|
||||
for (const [k, v] of m2) {
|
||||
result.set(k, v);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
module.exports = function(source) {
|
||||
const localeExp = this.options.locale || /([^/]+)\/[^/]+\.ftl$/;
|
||||
const result = localeExp.exec(this.resourcePath);
|
||||
const locale = result && result[1];
|
||||
// pre-parse the ftl
|
||||
const context = new MessageContext(locale);
|
||||
context.addMessages(source);
|
||||
if (!locale) {
|
||||
throw new Error(`couldn't find locale in: ${this.resourcePath}`);
|
||||
}
|
||||
// load default language and "merge" contexts
|
||||
// TODO: make this configurable
|
||||
const en_ftl = fs.readFileSync(
|
||||
require.resolve('../public/locales/en-US/send.ftl'),
|
||||
'utf8'
|
||||
);
|
||||
const en = new MessageContext('en-US');
|
||||
en.addMessages(en_ftl);
|
||||
// pre-parse the ftl
|
||||
const context = new MessageContext(locale);
|
||||
context.addMessages(source);
|
||||
|
||||
const merged = merge(en._messages, context._messages);
|
||||
return `
|
||||
module.exports = \`
|
||||
if (typeof window === 'undefined') {
|
||||
var fluent = require('fluent');
|
||||
}
|
||||
var ctx = new fluent.MessageContext('${locale}', {useIsolating: false});
|
||||
ctx._messages = new Map(${toJSON(context._messages)});
|
||||
ctx._messages = new Map(${toJSON(merged)});
|
||||
function translate(id, data) {
|
||||
var msg = ctx.getMessage(id);
|
||||
if (typeof(msg) !== 'string' && !msg.val && msg.attrs) {
|
||||
|
||||
5
build/version_loader.js
Normal file
5
build/version_loader.js
Normal file
@@ -0,0 +1,5 @@
|
||||
const version = require('../package.json').version;
|
||||
|
||||
module.exports = function(source) {
|
||||
return source.replace('VERSION', version);
|
||||
};
|
||||
@@ -8,6 +8,5 @@ services:
|
||||
- "1443:1443"
|
||||
environment:
|
||||
- REDIS_HOST=redis
|
||||
- NODE_ENV=production
|
||||
redis:
|
||||
image: redis:alpine
|
||||
|
||||
@@ -27,6 +27,7 @@ Data will be collected with Google Analytics and follow [Test Pilot standards](h
|
||||
- `cm5` - the number of files the user has ever uploaded.
|
||||
- `cm6` - the number of unexpired files the user has uploaded.
|
||||
- `cm7` - the number of files the user has ever downloaded.
|
||||
- `cm8` - the number of downloads permitted by the uploader.
|
||||
|
||||
### Custom Dimensions
|
||||
- `cd1` - the method by which the user initiated an upload. One of `drag`, `click`.
|
||||
@@ -67,6 +68,17 @@ Triggered whenever a user stops uploading a file. Includes:
|
||||
- `cd2`
|
||||
- `cd6`
|
||||
|
||||
#### `download-limit-changed`
|
||||
Triggered whenever the sender changes the download limit. Includes:
|
||||
|
||||
- `ec` - `sender`
|
||||
- `ea` - `download-limit-changed`
|
||||
- `cm1`
|
||||
- `cm5`
|
||||
- `cm6`
|
||||
- `cm7`
|
||||
- `cm8`
|
||||
|
||||
#### `password-added`
|
||||
Triggered whenever a password is added to a file. Includes:
|
||||
|
||||
|
||||
1593
package-lock.json
generated
1593
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
37
package.json
37
package.json
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "firefox-send",
|
||||
"description": "File Sharing Experiment",
|
||||
"version": "2.1.2",
|
||||
"version": "2.2.1",
|
||||
"author": "Mozilla (https://mozilla.org)",
|
||||
"repository": "mozilla/send",
|
||||
"homepage": "https://github.com/mozilla/send/",
|
||||
@@ -43,59 +43,60 @@
|
||||
"node": ">=8.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"autoprefixer": "^7.1.6",
|
||||
"autoprefixer": "^7.2.3",
|
||||
"babel-core": "^6.26.0",
|
||||
"babel-loader": "^7.1.2",
|
||||
"babel-plugin-yo-yoify": "^1.0.1",
|
||||
"babel-plugin-yo-yoify": "^1.0.2",
|
||||
"babel-polyfill": "^6.26.0",
|
||||
"babel-preset-env": "^1.6.1",
|
||||
"babel-preset-es2015": "^6.24.1",
|
||||
"babel-preset-stage-2": "^6.24.1",
|
||||
"base64-js": "^1.2.1",
|
||||
"copy-webpack-plugin": "^4.2.0",
|
||||
"copy-webpack-plugin": "^4.3.0",
|
||||
"cross-env": "^5.1.1",
|
||||
"css-loader": "^0.28.7",
|
||||
"css-mqpacker": "^6.0.1",
|
||||
"cssnano": "^3.10.0",
|
||||
"eslint": "^4.10.0",
|
||||
"eslint": "^4.13.1",
|
||||
"eslint-plugin-mocha": "^4.11.0",
|
||||
"eslint-plugin-node": "^5.2.1",
|
||||
"eslint-plugin-security": "^1.4.0",
|
||||
"expose-loader": "^0.7.3",
|
||||
"expose-loader": "^0.7.4",
|
||||
"extract-loader": "^1.0.1",
|
||||
"file-loader": "^1.1.5",
|
||||
"file-loader": "^1.1.6",
|
||||
"fluent-intl-polyfill": "^0.1.0",
|
||||
"git-rev-sync": "^1.9.1",
|
||||
"github-changes": "^1.1.1",
|
||||
"html-loader": "^0.5.1",
|
||||
"husky": "^0.14.3",
|
||||
"lint-staged": "^4.3.0",
|
||||
"mocha": "^3.5.3",
|
||||
"nanobus": "^4.3.0",
|
||||
"nanobus": "^4.3.1",
|
||||
"npm-run-all": "^4.1.2",
|
||||
"postcss-loader": "^2.0.8",
|
||||
"prettier": "^1.8.2",
|
||||
"postcss-loader": "^2.0.9",
|
||||
"prettier": "^1.9.2",
|
||||
"proxyquire": "^1.8.0",
|
||||
"raven-js": "^3.19.1",
|
||||
"raven-js": "^3.21.0",
|
||||
"redis-mock": "^0.20.0",
|
||||
"require-from-string": "^2.0.1",
|
||||
"rimraf": "^2.6.2",
|
||||
"selenium-webdriver": "^3.6.0",
|
||||
"sinon": "^4.1.2",
|
||||
"sinon": "^4.1.3",
|
||||
"string-hash": "^1.1.3",
|
||||
"stylelint-config-standard": "^17.0.0",
|
||||
"stylelint-no-unsupported-browser-features": "^1.0.1",
|
||||
"supertest": "^3.0.0",
|
||||
"testpilot-ga": "^0.3.0",
|
||||
"val-loader": "^1.0.2",
|
||||
"webpack": "^3.8.1",
|
||||
"val-loader": "^1.1.0",
|
||||
"webpack": "^3.10.0",
|
||||
"webpack-dev-server": "2.9.1",
|
||||
"webpack-manifest-plugin": "^1.3.2",
|
||||
"webpack-unassert-loader": "^1.2.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"aws-sdk": "^2.149.0",
|
||||
"aws-sdk": "^2.171.0",
|
||||
"body-parser": "^1.18.2",
|
||||
"choo": "^6.5.1",
|
||||
"choo": "^6.6.0",
|
||||
"cldr-core": "^32.0.0",
|
||||
"connect-busboy": "0.0.2",
|
||||
"convict": "^4.0.1",
|
||||
@@ -104,8 +105,8 @@
|
||||
"fluent-langneg": "^0.1.0",
|
||||
"helmet": "^3.9.0",
|
||||
"mkdirp": "^0.5.1",
|
||||
"mozlog": "^2.1.1",
|
||||
"raven": "^2.2.1",
|
||||
"mozlog": "^2.2.0",
|
||||
"raven": "^2.3.0",
|
||||
"redis": "^2.8.0"
|
||||
},
|
||||
"availableLanguages": [
|
||||
|
||||
@@ -11,7 +11,10 @@ uploadPageBrowseButton = اختر ملفّا على حاسوبك
|
||||
.title = اختر ملفّا على حاسوبك
|
||||
uploadPageBrowseButton1 = اختر ملفّا لرفعه
|
||||
uploadPageMultipleFilesAlert = رفع عدة ملفات (أو رفع مجلد) ليس مدعوما حاليا.
|
||||
uploadPageBrowseButtonTitle = ارفع ملفًا
|
||||
uploadingPageProgress = يرفع { $filename } ({ $size })
|
||||
importingFile = يستورد…
|
||||
verifyingFile = يتحقق…
|
||||
encryptingFile = يعمّي…
|
||||
decryptingFile = يفك التعمية…
|
||||
notifyUploadDone = انتهى الرفع.
|
||||
@@ -21,8 +24,27 @@ uploadingPageCancel = ألغِ الرفع
|
||||
uploadCancelNotification = أُلغي الرفع.
|
||||
uploadingPageLargeFileMessage = هذا الملف كبير الحجم وسيأخذ رفعه وقتا. انتظر رجاءً.
|
||||
uploadingFileNotification = أعلِمني عندما يكتمل الرفع.
|
||||
uploadSuccessConfirmHeader = جاهز للإرسال
|
||||
uploadSvgAlt
|
||||
.alt = ارفع
|
||||
uploadSuccessTimingHeader = ستنتهي صلاحية الرابط الذي يشير إلى الملف في حال: نُزِّل لأول مرة، أو مرّ ٢٤ ساعة على رفعه.
|
||||
expireInfo = ستنتهي صلاحية رابط الملف بعد { $downloadCount } أو { $timespan }.
|
||||
downloadCount = { $num ->
|
||||
[zero] لا تنزيلات
|
||||
[one] تنزيل واحد
|
||||
[two] تنزيلين
|
||||
[few] { $num } تنزيلات
|
||||
[many] { $num } تنزيلًا
|
||||
*[other] { $num } تنزيل
|
||||
}
|
||||
timespanHours = { $num ->
|
||||
[zero] أقل من ساعة
|
||||
[one] ساعة
|
||||
[two] ساعتين
|
||||
[few] { $num } ساعات
|
||||
[many] { $num } ساعة
|
||||
*[other] { $num } ساعة
|
||||
}
|
||||
copyUrlFormLabelWithName = انسخ الرابط وشاركه لإرسال الملف: { $filename }
|
||||
copyUrlFormButton = انسخ إلى الحافظة
|
||||
.title = انسخ إلى الحافظة
|
||||
@@ -35,8 +57,10 @@ sendAnotherFileLink = أرسل ملفّا آخر
|
||||
downloadAltText
|
||||
.alt = نزّل
|
||||
downloadFileName = نزّل { $filename }
|
||||
downloadFileSize = ({ $size })
|
||||
unlockInputLabel = أدخل كلمة السر
|
||||
unlockInputPlaceholder = كلمة السر
|
||||
unlockButtonLabel = افتح القفل
|
||||
downloadFileTitle = نزِّل الملف المعمّى
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
downloadMessage = يُرسل إليك صديقك ملفا عبر «فَيَرفُكس سِنْد»، وهي خدمة تتيح لك مشاركة الملفات عبر رابط آمن وخاص ومعمّى، حيث تنتهي صلاحياتها تلقائيا لتضمن عدم بقاء ما ترسله إلى الأبد.
|
||||
@@ -49,6 +73,7 @@ downloadFinish = اكتمل التنزيل
|
||||
fileSizeProgress = ({ $partialSize } من أصل { $totalSize })
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
sendYourFilesLink = جرِّب «فَيَرفُكس سِنْد»
|
||||
downloadingPageProgress = ينزّل { $filename } ({ $size })
|
||||
downloadingPageMessage = رجاء أبقِ هذا اللسان مفتوحا حتى نجلب الملف ونفك تعميته.
|
||||
errorAltText
|
||||
.alt = خطأ أثناء الرفع
|
||||
@@ -56,14 +81,21 @@ errorPageHeader = حدث خطب ما.
|
||||
errorPageMessage = حدث خطب ما أثناء رفع الملف.
|
||||
errorPageLink = أرسل ملفا آخر
|
||||
fileTooBig = حجم الملف كبير للغاية لرفعه. يجب أن يكون أصغر من { $size }.
|
||||
linkExpiredAlt = انتهت صلاحية الرابط
|
||||
expiredPageHeader = انتهت صلاحية هذا الرابط أو لم يكن موجودا في المقام الأول!
|
||||
notSupportedHeader = متصفحك غير مدعوم.
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
notSupportedDetail = للأسف فإن متصفحك لا يدعم تقنية الوِب التي يعتمد عليها «فَيَرفُكس سِنْد». عليك تجربة متصفح آخر، ونحن ننصحك بِفَيَرفُكس!
|
||||
notSupportedLink = لماذا متصفحي غير مدعوم؟
|
||||
notSupportedOutdatedDetail = للأسف فإن إصدارة فَيَرفُكس هذه لا تدعم تقنية الوِب التي يعتمد عليها «فَيَرفُكس سِنْد». عليك تحديث متصفحك.
|
||||
updateFirefox = حدّث فَيَرفُكس
|
||||
downloadFirefoxButtonSub = تنزيل مجاني
|
||||
uploadedFile = ملف
|
||||
copyFileList = انسخ الرابط
|
||||
// expiryFileList is used as a column header
|
||||
expiryFileList = ينتهي في
|
||||
deleteFileList = احذف
|
||||
nevermindButton = لا بأس
|
||||
legalHeader = الشروط والخصوصية
|
||||
deletePopupText = أأحذف هذا الملف؟
|
||||
deletePopupYes = نعم
|
||||
@@ -72,9 +104,15 @@ deleteButtonHover
|
||||
.title = احذف
|
||||
copyUrlHover
|
||||
.title = انسخ الرابط
|
||||
footerLinkLegal = القانونية
|
||||
// Test Pilot is a proper name and should not be localized.
|
||||
footerLinkAbout = حول الاختبار التجريبي
|
||||
footerLinkPrivacy = الخصوصية
|
||||
footerLinkTerms = الشروط
|
||||
footerLinkCookies = الكعكات
|
||||
requirePasswordCheckbox = اطلب كلمة سر لتنزيل هذا الملف
|
||||
addPasswordButton = أضِف كلمة سر
|
||||
passwordTryAgain = كلمة السر خاطئة. أعِد المحاولة.
|
||||
// This label is followed by the password needed to download a file
|
||||
passwordResult = كلمة السر: { $password }
|
||||
reportIPInfringement = أبلغ عن انتهاك للملكية الفكرية
|
||||
|
||||
@@ -86,4 +86,3 @@ footerLinkTerms = Şərtlər
|
||||
footerLinkCookies = Çərəzlər
|
||||
requirePasswordCheckbox = Bu faylı endirmək üçün parol tələb et
|
||||
addPasswordButton = Parol əlavə et
|
||||
incorrectPassword = Xətalı parol. Təkrar yoxlayın.
|
||||
|
||||
@@ -25,6 +25,12 @@ uploadingFileNotification = Obavijesti me kada otpremanje bude gotovo.
|
||||
uploadSuccessConfirmHeader = Spremno za slanje
|
||||
uploadSvgAlt = Otpremi
|
||||
uploadSuccessTimingHeader = Veza prema vašoj datoteci će isteći nakon prvog preuzimanja ili za 24 sata.
|
||||
expireInfo = Link za vašu datoteku će isteći nakon { $downloadCount } ili { $timespan }.
|
||||
downloadCount = { $num ->
|
||||
[one] 1 preuzimanja
|
||||
[few] { $num } preuzimanja
|
||||
*[other] { $num } preuzimanja
|
||||
}
|
||||
copyUrlFormLabelWithName = Iskopirajte i podijelite vezu da biste poslali datoteku: { $filename }
|
||||
copyUrlFormButton = Kopiraj u međuspremnik
|
||||
copiedUrl = Kopirano!
|
||||
@@ -89,3 +95,4 @@ addPasswordButton = Dodaj lozinku
|
||||
passwordTryAgain = Netačna lozinka. Pokušajte ponovo.
|
||||
// This label is followed by the password needed to download a file
|
||||
passwordResult = Lozinka: { $password }
|
||||
reportIPInfringement = Prijavite IP prekršaj
|
||||
|
||||
@@ -25,6 +25,17 @@ uploadingFileNotification = Upozornit, až bude nahrávání dokončeno.
|
||||
uploadSuccessConfirmHeader = Připraveno k odeslání
|
||||
uploadSvgAlt = Nahrát
|
||||
uploadSuccessTimingHeader = Platnost odkazu na váš soubor vyprší po jeho prvním stažení, nebo po 24 hodinách.
|
||||
expireInfo = Platnost odkazu na váš soubor vyprší po { $downloadCount } nebo { $timespan }.
|
||||
downloadCount = { $num ->
|
||||
[one] jednom stažení
|
||||
[few] { $num } staženích
|
||||
*[other] { $num } staženích
|
||||
}
|
||||
timespanHours = { $num ->
|
||||
[one] hodina
|
||||
[few] hodiny
|
||||
*[other] hodin
|
||||
}
|
||||
copyUrlFormLabelWithName = Zkopírujte a sdílejte odkaz na váš soubor: { $filename }
|
||||
copyUrlFormButton = Zkopírovat do schránky
|
||||
copiedUrl = Zkopírováno!
|
||||
@@ -89,3 +100,4 @@ addPasswordButton = Přidat heslo
|
||||
passwordTryAgain = Špatné heslo. Zkuste to znovu.
|
||||
// This label is followed by the password needed to download a file
|
||||
passwordResult = Heslo: { $password }
|
||||
reportIPInfringement = Nahlásit porušení autorských práv
|
||||
|
||||
@@ -25,6 +25,19 @@ uploadingFileNotification = Dweud pan fydd y llwytho wedi gorffen.
|
||||
uploadSuccessConfirmHeader = Yn Barod i Anfon
|
||||
uploadSvgAlt = Llwytho i Fyny
|
||||
uploadSuccessTimingHeader = Bydd y ddolen i'ch ffeil y dod i ben ar ôl 1 llwytho neu o fewn 24 awr.
|
||||
expireInfo = Bydd y ddolen i'ch ffeil yn dod i ben ym mhen { $downloadCount } neu { $timespan }.
|
||||
downloadCount = { $num ->
|
||||
[one] Llwyth i lawr
|
||||
[two] Lwyth i lawr
|
||||
[few] Llwyth i lawr
|
||||
*[other] Llwyth i lawr
|
||||
}
|
||||
timespanHours = { $num ->
|
||||
[one] awr
|
||||
[two] awr
|
||||
[few] awr
|
||||
*[other] awr
|
||||
}
|
||||
copyUrlFormLabelWithName = Copïo a rhannu'r ddolen i anfon eich ffeil: { $filename }
|
||||
copyUrlFormButton = Copïo i'r clipfwrdd
|
||||
copiedUrl = Wedi eu copïo!
|
||||
@@ -89,3 +102,4 @@ addPasswordButton = Ychwanegu Cyfrinair
|
||||
passwordTryAgain = Cyfrinair anghywir. Ceisiwch eto.
|
||||
// This label is followed by the password needed to download a file
|
||||
passwordResult = Cyfrinair: { $password }
|
||||
reportIPInfringement = Adrodd ar Gamddefnydd o'r IP
|
||||
|
||||
0
public/locales/da/send.ftl
Normal file
0
public/locales/da/send.ftl
Normal file
@@ -25,6 +25,15 @@ uploadingFileNotification = Mich benachrichtigen, wenn der Upload abgeschlossen
|
||||
uploadSuccessConfirmHeader = Bereit zum Senden
|
||||
uploadSvgAlt = Hochladen
|
||||
uploadSuccessTimingHeader = Der Link zu Ihrer Datei läuft nach einem Download oder in 24 Stunden ab.
|
||||
expireInfo = Der Link zu Ihrer Datei läuft nach { $downloadCount } oder { $timespan } ab.
|
||||
downloadCount = { $num ->
|
||||
[one] einem Download
|
||||
*[other] { $num } Downloads
|
||||
}
|
||||
timespanHours = { $num ->
|
||||
[one] einer Stunde
|
||||
*[other] { $num } Stunden
|
||||
}
|
||||
copyUrlFormLabelWithName = Kopieren und teilen Sie den Link, um Ihre Datei zu senden: { $filename }
|
||||
copyUrlFormButton = In Zwischenablage kopieren
|
||||
copiedUrl = Kopiert!
|
||||
@@ -89,3 +98,4 @@ addPasswordButton = Passwort hinzufügen
|
||||
passwordTryAgain = Falsches Passwort. Versuchen Sie es erneut.
|
||||
// This label is followed by the password needed to download a file
|
||||
passwordResult = Passwort: { $password }
|
||||
reportIPInfringement = IP-Verletzung melden
|
||||
|
||||
@@ -25,6 +25,19 @@ uploadingFileNotification = K wěsći daś, gaž nagraśe jo dokóńcone.
|
||||
uploadSuccessConfirmHeader = Gótowy za słanje
|
||||
uploadSvgAlt = Nagraś
|
||||
uploadSuccessTimingHeader = Wótkaz k wašej dataji pó 1 ześěgnjenju abo 24 góźinach spadnjo.
|
||||
expireInfo = Wótkaz k wašej dataji pó { $downloadCount } abo { $timespan } spadnjo.
|
||||
downloadCount = { $num ->
|
||||
[one] 1 ześěgnjenje
|
||||
[two] { $num } ześěgnjeni
|
||||
[few] { $num } ześěgnjenja
|
||||
*[other] { $num } ześěgnjenjow
|
||||
}
|
||||
timespanHours = { $num ->
|
||||
[one] 1 góźina
|
||||
[two] { $num } góźinje
|
||||
[few] { $num } góźiny
|
||||
*[other] { $num } góźin
|
||||
}
|
||||
copyUrlFormLabelWithName = Kopěrujśo a źělśo wótkaz, aby swóju dataju pósłał: { $filename }
|
||||
copyUrlFormButton = Do mjazywótkłada kopěrowaś
|
||||
copiedUrl = Kopěrowany!
|
||||
@@ -89,3 +102,4 @@ addPasswordButton = Gronidło pśidaś
|
||||
passwordTryAgain = Wopacne gronidło. Wopytajśo hyšći raz.
|
||||
// This label is followed by the password needed to download a file
|
||||
passwordResult = Gronidło: { $password }
|
||||
reportIPInfringement = Pśekśiwjenje IP k wěsći daś
|
||||
|
||||
@@ -25,6 +25,10 @@ uploadingFileNotification = Ειδοποίηση όταν ολοκληρωθεί
|
||||
uploadSuccessConfirmHeader = Έτοιμο για αποστολή
|
||||
uploadSvgAlt = Μεταφόρτωση
|
||||
uploadSuccessTimingHeader = Ο σύνδεσμος του αρχείου σας θα λήξει έπειτα από 1 λήψη ή 24 ώρες.
|
||||
timespanHours = { $num ->
|
||||
[one] 1 ώρα
|
||||
*[other] { $num } ώρες
|
||||
}
|
||||
copyUrlFormLabelWithName = Αντιγράψτε και μοιραστείτε τον σύνδεσμο για αποστολή του αρχείου σας : { $filename }
|
||||
copyUrlFormButton = Αντιγραφή στο πρόχειρο
|
||||
copiedUrl = Αντιγράφτηκε!
|
||||
@@ -86,4 +90,6 @@ footerLinkTerms = Όροι
|
||||
footerLinkCookies = Cookies
|
||||
requirePasswordCheckbox = Απαίτηση κωδικού πρόσβασης για λήψη του αρχείου
|
||||
addPasswordButton = Προσθήκη κωδικού πρόσβασης
|
||||
incorrectPassword = Λάθος κωδικός πρόσβασης. Προσπάθεια ξανά;
|
||||
passwordTryAgain = Λάθος κωδικός πρόσβασης. Δοκιμάστε ξανά.
|
||||
// This label is followed by the password needed to download a file
|
||||
passwordResult = Κωδικός πρόσβασης: { $password }
|
||||
|
||||
@@ -25,6 +25,15 @@ uploadingFileNotification = Notify me when the upload is complete.
|
||||
uploadSuccessConfirmHeader = Ready to Send
|
||||
uploadSvgAlt = Upload
|
||||
uploadSuccessTimingHeader = The link to your file will expire after 1 download or in 24 hours.
|
||||
expireInfo = The link to your file will expire after { $downloadCount } or { $timespan }.
|
||||
downloadCount = { $num ->
|
||||
[one] 1 download
|
||||
*[other] { $num } downloads
|
||||
}
|
||||
timespanHours = { $num ->
|
||||
[one] 1 hour
|
||||
*[other] { $num } hours
|
||||
}
|
||||
copyUrlFormLabelWithName = Copy and share the link to send your file: { $filename }
|
||||
copyUrlFormButton = Copy to clipboard
|
||||
copiedUrl = Copied!
|
||||
@@ -88,4 +97,5 @@ requirePasswordCheckbox = Require a password to download this file
|
||||
addPasswordButton = Add password
|
||||
passwordTryAgain = Incorrect password. Try again.
|
||||
// This label is followed by the password needed to download a file
|
||||
passwordResult = Password: { $password }
|
||||
passwordResult = Password: { $password }
|
||||
reportIPInfringement = Report IP Infringement
|
||||
@@ -25,6 +25,15 @@ uploadingFileNotification = Notificarme cuando la subida se complete.
|
||||
uploadSuccessConfirmHeader = Listo para enviar
|
||||
uploadSvgAlt = Subir
|
||||
uploadSuccessTimingHeader = El enlace al archivo expirará después de 1 descarga o en 24 horas.
|
||||
expireInfo = El enlace a tu archivo expirará después de { $downloadCount } o { $timespan }.
|
||||
downloadCount = { $num ->
|
||||
[one] 1 descarga
|
||||
*[other] { $num } descargas
|
||||
}
|
||||
timespanHours = { $num ->
|
||||
[one] 1 hora
|
||||
*[other] { $num } horas
|
||||
}
|
||||
copyUrlFormLabelWithName = Copiá y compartí el enlace para enviar tu archivo: { $filename }
|
||||
copyUrlFormButton = Copiar al portapapeles
|
||||
copiedUrl = ¡Copiado!
|
||||
@@ -89,3 +98,4 @@ addPasswordButton = Agregar contraseña
|
||||
passwordTryAgain = Contraseña incorrecta. Intentá nuevamente.
|
||||
// This label is followed by the password needed to download a file
|
||||
passwordResult = Contraseña: { $password }
|
||||
reportIPInfringement = Informar violación de propiedad intelectual
|
||||
|
||||
@@ -25,6 +25,15 @@ uploadingFileNotification = Notificarme cuando la subida sea completada.
|
||||
uploadSuccessConfirmHeader = Listo para enviar
|
||||
uploadSvgAlt = Subir
|
||||
uploadSuccessTimingHeader = El enlace a tu archivo expirará tras 1 descarga o en 24 horas.
|
||||
expireInfo = El enlace a tu archivo expirará después de { $downloadCount } o { $timespan }.
|
||||
downloadCount = { $num ->
|
||||
[one] 1 descarga
|
||||
*[other] { $num } descargas
|
||||
}
|
||||
timespanHours = { $num ->
|
||||
[one] 1 hora
|
||||
*[other] { $num } horas
|
||||
}
|
||||
copyUrlFormLabelWithName = Copia y comparte el enlace para enviar tu archivo: { $filename }
|
||||
copyUrlFormButton = Copiar al portapapeles
|
||||
copiedUrl = ¡Copiado!
|
||||
@@ -89,3 +98,4 @@ addPasswordButton = Añadir contraseña
|
||||
passwordTryAgain = Contraseña incorrecta. Vuelve a intentarlo.
|
||||
// This label is followed by the password needed to download a file
|
||||
passwordResult = Contraseña: { $password }
|
||||
reportIPInfringement = Reportar infracción de PI
|
||||
|
||||
@@ -25,6 +25,15 @@ uploadingFileNotification = Notificarme cuando se complete la subida.
|
||||
uploadSuccessConfirmHeader = Listo para enviar
|
||||
uploadSvgAlt = Subir
|
||||
uploadSuccessTimingHeader = El enlace al archivo caducará tras descargarlo una vez o en 24 horas.
|
||||
expireInfo = El enlace al archivo expirará tras { $downloadCount } o { $timespan }.
|
||||
downloadCount = { $num ->
|
||||
[one] 1 descarga
|
||||
*[other] { $num } descargas
|
||||
}
|
||||
timespanHours = { $num ->
|
||||
[one] 1 hora
|
||||
*[other] { $num } horas
|
||||
}
|
||||
copyUrlFormLabelWithName = Copiar y compartir el enlace para enviar tu archivo: { $filename }
|
||||
copyUrlFormButton = Copiar en el portapapeles
|
||||
copiedUrl = ¡Copiado!
|
||||
@@ -89,3 +98,4 @@ addPasswordButton = Añadir contraseña
|
||||
passwordTryAgain = Contraseña incorrecta. Inténtelo de nuevo.
|
||||
// This label is followed by the password needed to download a file
|
||||
passwordResult = Contraseña: { $password }
|
||||
reportIPInfringement = Denunciar vulneración de propiedad intelectual
|
||||
|
||||
@@ -25,6 +25,14 @@ uploadingFileNotification = Avísame cuando la subida del archivo esté completa
|
||||
uploadSuccessConfirmHeader = Listo para enviar
|
||||
uploadSvgAlt = Subir
|
||||
uploadSuccessTimingHeader = El enlace a tu archivo expirará después de una descarga o en 24 horas.
|
||||
expireInfo = El enlace a tu archivo expirará después de { $downloadCount } o { $timespan }.
|
||||
downloadCount = { $num ->
|
||||
*[one] 1 descarga
|
||||
}
|
||||
timespanHours = { $num ->
|
||||
[one] 1 hora
|
||||
*[other] { $num } horas
|
||||
}
|
||||
copyUrlFormLabelWithName = Copiar y compartir el enlace para enviar tu archivo: ($filename)
|
||||
copyUrlFormButton = Copiar a portapapeles
|
||||
copiedUrl = ¡Copiado!
|
||||
@@ -89,3 +97,4 @@ addPasswordButton = Agregar contraseña
|
||||
passwordTryAgain = Contraseña incorrecta. Intenta de nuevo.
|
||||
// This label is followed by the password needed to download a file
|
||||
passwordResult = Contraseña: { $password }
|
||||
reportIPInfringement = Denunciar una infracción de PI
|
||||
|
||||
@@ -25,6 +25,13 @@ uploadingFileNotification = هر وقت بارگذاری تمام شد به من
|
||||
uploadSuccessConfirmHeader = آماده برای ارسال
|
||||
uploadSvgAlt = بارگذاری
|
||||
uploadSuccessTimingHeader = پیوند به پرونده شما بعد از ۱ بار دانلود یا ۲۴ ساعت حذف خواهد شد.
|
||||
expireInfo = این پیوند به فایل شما پس از { $downloadCount } یا { $timespan } منقضی خواهد شد.
|
||||
downloadCount = { $num ->
|
||||
*[other] ۱ بارگذاری
|
||||
}
|
||||
timespanHours = { $num ->
|
||||
*[other] ۱ ساعت
|
||||
}
|
||||
copyUrlFormLabelWithName = برای ارسال پرونده پیوند آن را رونوشت و به اشتراک بگذارید: { $filename }
|
||||
copyUrlFormButton = رونوشت به کلیپبورد
|
||||
copiedUrl = رونوشت شد!
|
||||
@@ -87,3 +94,6 @@ footerLinkCookies = کوکیها
|
||||
requirePasswordCheckbox = دریافت این پرونده نیاز به گذرواژه دارد
|
||||
addPasswordButton = افزودن گذرواژه
|
||||
passwordTryAgain = کلمه عبور اشتباه است. مجدد تلاش کنید.
|
||||
// This label is followed by the password needed to download a file
|
||||
passwordResult = گذرواژه: { $password }
|
||||
reportIPInfringement = گزارش تخلف IP
|
||||
|
||||
@@ -25,6 +25,15 @@ uploadingFileNotification = M’envoyer une notification lorsque l’envoi est t
|
||||
uploadSuccessConfirmHeader = Paré à l’envoi
|
||||
uploadSvgAlt = Envoyer
|
||||
uploadSuccessTimingHeader = Le lien vers votre fichier expirera après le premier téléchargement ou au bout de 24 heures.
|
||||
expireInfo = Le lien vers votre fichier expirera après { $downloadCount } ou { $timespan }.
|
||||
downloadCount = { $num ->
|
||||
[one] 1 téléchargement
|
||||
*[other] { $num } téléchargements
|
||||
}
|
||||
timespanHours = { $num ->
|
||||
[one] 1 heure
|
||||
*[other] { $num } heures
|
||||
}
|
||||
copyUrlFormLabelWithName = Copiez et partagez le lien pour envoyer votre fichier : { $filename }
|
||||
copyUrlFormButton = Copier dans le presse-papiers
|
||||
copiedUrl = Lien copié !
|
||||
@@ -34,7 +43,7 @@ sendAnotherFileLink = Envoyer un autre fichier
|
||||
downloadAltText = Télécharger
|
||||
downloadFileName = Télécharger { $filename }
|
||||
downloadFileSize = ({ $size })
|
||||
unlockInputLabel = Saisissez un mot de passe
|
||||
unlockInputLabel = Saisissez le mot de passe
|
||||
unlockInputPlaceholder = Mot de passe
|
||||
unlockButtonLabel = Déverrouiller
|
||||
downloadFileTitle = Télécharger le fichier chiffré
|
||||
@@ -89,3 +98,4 @@ addPasswordButton = Ajouter un mot de passe
|
||||
passwordTryAgain = Mot de passe incorrect. Veuillez réessayer.
|
||||
// This label is followed by the password needed to download a file
|
||||
passwordResult = Mot de passe : { $password }
|
||||
reportIPInfringement = Signaler une violation de la p.i.
|
||||
|
||||
@@ -25,6 +25,15 @@ uploadingFileNotification = Jou in melding as de oplaad foltôge is.
|
||||
uploadSuccessConfirmHeader = Ree om te ferstjoeren
|
||||
uploadSvgAlt = Oplaad
|
||||
uploadSuccessTimingHeader = De keppeling nei jo bestân sil nei 1 download ferrinne of nei 24 oeren.
|
||||
expireInfo = De keppeling nei jo bestân sil nei { $downloadCount } of { $timespan } ferrinne.
|
||||
downloadCount = { $num ->
|
||||
[one] 1 download
|
||||
*[other] { $num } downloads
|
||||
}
|
||||
timespanHours = { $num ->
|
||||
[one] 1 oer
|
||||
*[other] { $num } oeren
|
||||
}
|
||||
copyUrlFormLabelWithName = Kopiearje en diel de keppeling om jo bestân te ferstjoeren: { $filename }
|
||||
copyUrlFormButton = Nei klamboerd kopiearje
|
||||
copiedUrl = Kopiearre!
|
||||
@@ -89,3 +98,4 @@ addPasswordButton = Wachtwurd tafoegje
|
||||
passwordTryAgain = Net krekt wachtwurd. Probearje it opnij.
|
||||
// This label is followed by the password needed to download a file
|
||||
passwordResult = Wachtwurd: { $password }
|
||||
reportIPInfringement = IP-ynbrek melde
|
||||
|
||||
@@ -25,6 +25,19 @@ uploadingFileNotification = Zdźělić, hdyž nahraće je dokónčene.
|
||||
uploadSuccessConfirmHeader = Hotowy za słanje
|
||||
uploadSvgAlt = Nahrać
|
||||
uploadSuccessTimingHeader = Wotkaz k wašej dataji po 1 sćehnjenju abo 24 hodźinach spadnje.
|
||||
expireInfo = Wotkaz k wašej dataji po { $downloadCount } abo { $timespan } spadnje.
|
||||
downloadCount = { $num ->
|
||||
[one] 1 sćehnjenje
|
||||
[two] { $num } sćehnjeni
|
||||
[few] { $num } sćehnjenja
|
||||
*[other] { $num } sćehnjenjow
|
||||
}
|
||||
timespanHours = { $num ->
|
||||
[one] 1 hodźina
|
||||
[two] { $num } hodźinje
|
||||
[few] { $num } hodźiny
|
||||
*[other] { $num } hodźin
|
||||
}
|
||||
copyUrlFormLabelWithName = Kopěrujće a dźělće wotkaz, zo byšće swoju dataju pósłał: { $filename }
|
||||
copyUrlFormButton = Do mjezyskłada kopěrować
|
||||
copiedUrl = Kopěrowany!
|
||||
@@ -89,3 +102,4 @@ addPasswordButton = Hesło přidać
|
||||
passwordTryAgain = Wopačne hesło. Prošu spytajće hišće raz.
|
||||
// This label is followed by the password needed to download a file
|
||||
passwordResult = Hesło: { $password }
|
||||
reportIPInfringement = Zranjenje IP zdźělić
|
||||
|
||||
@@ -25,6 +25,15 @@ uploadingFileNotification = Értesítsen, ha a feltöltés elkészült.
|
||||
uploadSuccessConfirmHeader = Küldésre kész
|
||||
uploadSvgAlt = Feltöltés
|
||||
uploadSuccessTimingHeader = A fájl hivatkozása lejár 1 letöltés vagy 24 óra múlva.
|
||||
expireInfo = A fájlhoz tartozó hivatkozás { $downloadCount } vagy { $timespan } múlva lejár.
|
||||
downloadCount = { $num ->
|
||||
[one] 1 letöltés
|
||||
*[other] { $num } letöltés
|
||||
}
|
||||
timespanHours = { $num ->
|
||||
[one] 1 óra
|
||||
*[other] { $num } óra
|
||||
}
|
||||
copyUrlFormLabelWithName = Másolja és ossza meg a hivatkozást a fájl küldéséhez: { $filename }
|
||||
copyUrlFormButton = Vágólapra másolás
|
||||
copiedUrl = Másolva!
|
||||
@@ -89,3 +98,4 @@ addPasswordButton = Jelszó hozzáadása
|
||||
passwordTryAgain = Helytelen jelszó. Próbálja meg újra.
|
||||
// This label is followed by the password needed to download a file
|
||||
passwordResult = Jelszó: { $password }
|
||||
reportIPInfringement = Szellemi tulajdon megsértésének bejelentése
|
||||
|
||||
@@ -86,4 +86,3 @@ footerLinkTerms = Ketentuan
|
||||
footerLinkCookies = Kuki
|
||||
requirePasswordCheckbox = Membutuhkan sandi untuk mengunduh berkas ini
|
||||
addPasswordButton = Tambahkan Sandi
|
||||
incorrectPassword = Sandi salah. Coba lagi?
|
||||
|
||||
@@ -25,6 +25,15 @@ uploadingFileNotification = Invia una notifica quando il caricamento è completa
|
||||
uploadSuccessConfirmHeader = Pronto per l’invio
|
||||
uploadSvgAlt = Carica
|
||||
uploadSuccessTimingHeader = Il link al file scadrà dopo 1 download o in 24 ore.
|
||||
expireInfo = Il link a questo file scadrà dopo { $downloadCount } o { $timespan }.
|
||||
downloadCount = { $num ->
|
||||
[one] 1 download
|
||||
*[other] { $num } download
|
||||
}
|
||||
timespanHours = { $num ->
|
||||
[one] 1 ora
|
||||
*[other] { $num } ore
|
||||
}
|
||||
copyUrlFormLabelWithName = Copia e condividi il link per inviare il tuo file: { $filename }
|
||||
copyUrlFormButton = Copia negli appunti
|
||||
copiedUrl = Copiato
|
||||
@@ -89,3 +98,4 @@ addPasswordButton = Aggiungi password
|
||||
passwordTryAgain = Password errata, riprovare.
|
||||
// This label is followed by the password needed to download a file
|
||||
passwordResult = Password: { $password }
|
||||
reportIPInfringement = Segnala violazione della proprietà intellettuale
|
||||
|
||||
@@ -25,6 +25,13 @@ uploadingFileNotification = アップロード完了時に通知を受け取る
|
||||
uploadSuccessConfirmHeader = 送信準備完了
|
||||
uploadSvgAlt = アップロード
|
||||
uploadSuccessTimingHeader = ファイルへのリンクは、1 回ダウンロードされた後、もしくは 24 時間以内に期限切れとなります。
|
||||
expireInfo = このファイルへのリンクは { $downloadCount } あるいは { $timespan } 後に期限切れとなります。
|
||||
downloadCount = { $num ->
|
||||
*[other] { $num } 回のダウンロード
|
||||
}
|
||||
timespanHours = { $num ->
|
||||
*[other] { $num } 時間
|
||||
}
|
||||
copyUrlFormLabelWithName = ファイルを送信するにはこのリンクをコピー、共有してください: { $filename }
|
||||
copyUrlFormButton = クリップボードへコピー
|
||||
copiedUrl = コピー完了!
|
||||
@@ -89,3 +96,4 @@ addPasswordButton = パスワードを追加
|
||||
passwordTryAgain = パスワードが正しくありません。再度入力してください。
|
||||
// This label is followed by the password needed to download a file
|
||||
passwordResult = パスワード: { $password }
|
||||
reportIPInfringement = 知的財産侵害報告
|
||||
|
||||
@@ -25,6 +25,13 @@ uploadingFileNotification = შეტყობინება, ატვირ
|
||||
uploadSuccessConfirmHeader = მზადაა გასაგზავნად
|
||||
uploadSvgAlt = ატვირთვა
|
||||
uploadSuccessTimingHeader = ფაილს ვადა გაუვა 1 ჩამოტვირთვის, ან 24 საათის მერე.
|
||||
expireInfo = ფაილის ბმულს, ვადა გაუვა { $downloadCount }, ან { $timespan } მერე.
|
||||
downloadCount = { $num ->
|
||||
*[other] { $num } ჩამოტვირთვა
|
||||
}
|
||||
timespanHours = { $num ->
|
||||
*[other] { $num } საათი
|
||||
}
|
||||
copyUrlFormLabelWithName = დააკოპირეთ და გააზიარეთ ბმული, ფაილის გასაგზავნად: { $filename }
|
||||
copyUrlFormButton = დაკოპირება
|
||||
copiedUrl = დაკოპირდა!
|
||||
@@ -32,7 +39,7 @@ deleteFileButton = ფაილის წაშლა
|
||||
sendAnotherFileLink = სხვა ფაილის გაგზავნა
|
||||
// Alternative text used on the download link/button (indicates an action).
|
||||
downloadAltText = ჩამოტვირთვა
|
||||
downloadFileName = { $filename } ჩამოტვირთვა
|
||||
downloadFileName = { $filename } ჩამოტვირთვა
|
||||
downloadFileSize = ({ $size })
|
||||
unlockInputLabel = შეიყვანეთ პაროლი
|
||||
unlockInputPlaceholder = პაროლი
|
||||
@@ -89,3 +96,4 @@ addPasswordButton = პაროლის დამატება
|
||||
passwordTryAgain = პაროლი არასწორია. სცადეთ ხელახლა.
|
||||
// This label is followed by the password needed to download a file
|
||||
passwordResult = პაროლი: { $password }
|
||||
reportIPInfringement = მოხსენება დარღვევაზე
|
||||
|
||||
@@ -25,6 +25,15 @@ uploadingFileNotification = Lɣu-yid ticki yemmed usali.
|
||||
uploadSuccessConfirmHeader = Ihegga i walluy
|
||||
uploadSvgAlt = Sali
|
||||
uploadSuccessTimingHeader = Aseɣwen ar ufaylu-ik ad yemmet ticki yuder-d neɣ deffir n 24 n yisragen.
|
||||
expireInfo = Aseɣwen icudden ar ufaylu-inek ad yemmet send { $downloadCount } naɣ { $timespan }.
|
||||
downloadCount = { $num ->
|
||||
[one] 1 usider
|
||||
*[other] { $num } isidar
|
||||
}
|
||||
timespanHours = { $num ->
|
||||
[one] 1 usrag
|
||||
*[other] { $num } isragen
|
||||
}
|
||||
copyUrlFormLabelWithName = Nɣel sakin Bḍu aseɣwen akken ad tazneḍ afaylu-ik: { $filename }
|
||||
copyUrlFormButton = Sers ɣef afus
|
||||
copiedUrl = Yenɣel!
|
||||
@@ -87,3 +96,6 @@ footerLinkCookies = Inagan n tuqqna
|
||||
requirePasswordCheckbox = YEsra awal uffir akken ad isider afaylu-agi
|
||||
addPasswordButton = rnu awal uffir
|
||||
passwordTryAgain = Yir awal uffir. Ɛreḍ tikelt nniḍen.
|
||||
// This label is followed by the password needed to download a file
|
||||
passwordResult = Awal uffir: { $password }
|
||||
reportIPInfringement = Neqqes akukel n IP
|
||||
|
||||
@@ -26,6 +26,9 @@ uploadingFileNotification = 업로드가 완료되면 알림을 표시해 주세
|
||||
uploadSuccessConfirmHeader = 보낼 준비 완료
|
||||
uploadSvgAlt = 업로드
|
||||
uploadSuccessTimingHeader = 이 파일의 링크는 한 번의 다운로드 후 또는 24시간이 지난 뒤에 만료됩니다.
|
||||
expireInfo = 이 파일의 링크는 { $downloadCount }나 { $timespan } 후에 만료됩니다.
|
||||
downloadCount = 1 다운로드
|
||||
timespanHours = 1 시간
|
||||
copyUrlFormLabelWithName = 파일을 보내기 위해 이 링크를 복사하고 공유하세요: { $filename }
|
||||
copyUrlFormButton = 클립보드에 복사
|
||||
copiedUrl = 복사 완료!
|
||||
@@ -90,3 +93,4 @@ addPasswordButton = 비밀번호 추가
|
||||
passwordTryAgain = 비밀번호가 맞지 않습니다. 다시 시도해 주세요.
|
||||
// This label is followed by the password needed to download a file
|
||||
passwordResult = 비밀번호: { $password }
|
||||
reportIPInfringement = 지적 재산권 침해 신고
|
||||
|
||||
@@ -25,6 +25,13 @@ uploadingFileNotification = Maklumkan saya apabila muat naik selesai.
|
||||
uploadSuccessConfirmHeader = Sedia untuk Hantar
|
||||
uploadSvgAlt = Muat naik
|
||||
uploadSuccessTimingHeader = Pautan ke fail anda akan luput selepas 1 muat turun atau dalam 24 jam.
|
||||
expireInfo = Pautan ke fail anda akan luput selepas { $downloadCount } atau { $timespan }.
|
||||
downloadCount = { $num ->
|
||||
*[other] { $num } muat turun
|
||||
}
|
||||
timespanHours = { $num ->
|
||||
*[other] { $num } jam
|
||||
}
|
||||
copyUrlFormLabelWithName = Salin dan kongsi pautan untuk menghantar fail anda: { $filename }
|
||||
copyUrlFormButton = Salin ke Klipbod
|
||||
copiedUrl = Disalin!
|
||||
@@ -89,3 +96,4 @@ addPasswordButton = Tambah Kata laluan
|
||||
passwordTryAgain = Kata laluan tidak betul. Cuba lagi.
|
||||
// This label is followed by the password needed to download a file
|
||||
passwordResult = Kata laluan: { $password }
|
||||
reportIPInfringement = Lapor Pencerobohan IP
|
||||
|
||||
@@ -25,6 +25,15 @@ uploadingFileNotification = Varsle meg når opplastingen er ferdig.
|
||||
uploadSuccessConfirmHeader = Klar til å sende
|
||||
uploadSvgAlt = Last opp
|
||||
uploadSuccessTimingHeader = Lenken til filen din utløper etter 1 nedlasting eller om 24 timer.
|
||||
expireInfo = Lenken til filen din vil gå ut etter { $downloadCount } eller { $timespan }.
|
||||
downloadCount = { $num ->
|
||||
[one] 1 nedlasting
|
||||
*[other] { $num } nedlastinger
|
||||
}
|
||||
timespanHours = { $num ->
|
||||
[one] 1 time
|
||||
*[other] { $num } timer
|
||||
}
|
||||
copyUrlFormLabelWithName = Kopier og del linken for å sende filen: { $filename }
|
||||
copyUrlFormButton = Kopier til utklippstavle
|
||||
copiedUrl = Kopiert!
|
||||
@@ -89,3 +98,4 @@ addPasswordButton = Legg til passord
|
||||
passwordTryAgain = Feil passord. Prøv igjen.
|
||||
// This label is followed by the password needed to download a file
|
||||
passwordResult = Passord: { $password }
|
||||
reportIPInfringement = Rapporter brudd på åndsverk
|
||||
|
||||
@@ -25,6 +25,15 @@ uploadingFileNotification = Mij waarschuwen zodra het uploaden is voltooid
|
||||
uploadSuccessConfirmHeader = Gereed voor verzending
|
||||
uploadSvgAlt = Uploaden
|
||||
uploadSuccessTimingHeader = De koppeling naar uw bestand zal na 1 download of 24 uur verlopen.
|
||||
expireInfo = De koppeling naar uw bestand zal na { $downloadCount } of { $timespan } verlopen.
|
||||
downloadCount = { $num ->
|
||||
[one] 1 download
|
||||
*[other] { $num } downloads
|
||||
}
|
||||
timespanHours = { $num ->
|
||||
[one] 1 uur
|
||||
*[other] { $num } uur
|
||||
}
|
||||
copyUrlFormLabelWithName = Kopieer en deel de koppeling om uw bestand te verzenden: { $filename }
|
||||
copyUrlFormButton = Kopiëren naar klembord
|
||||
copiedUrl = Gekopieerd!
|
||||
@@ -89,3 +98,4 @@ addPasswordButton = Wachtwoord toevoegen
|
||||
passwordTryAgain = Onjuist wachtwoord. Probeer het opnieuw.
|
||||
// This label is followed by the password needed to download a file
|
||||
passwordResult = Wachtwoord: { $password }
|
||||
reportIPInfringement = IE-inbreuk melden
|
||||
|
||||
@@ -25,6 +25,15 @@ uploadingFileNotification = Varsle meg når opplastinga er ferdig.
|
||||
uploadSuccessConfirmHeader = Klår til å senda
|
||||
uploadSvgAlt = Last opp
|
||||
uploadSuccessTimingHeader = Lenka til fila di går ut etter 1 nedlasting eller om 24 timar.
|
||||
expireInfo = Lenka til fila di vil gå ut etter { $downloadCount } eller { $timespan }.
|
||||
downloadCount = { $num ->
|
||||
[one] 1 nedlasting
|
||||
*[other] { $num } nedlastingar
|
||||
}
|
||||
timespanHours = { $num ->
|
||||
[one] 1 time
|
||||
*[other] { $num } timar
|
||||
}
|
||||
copyUrlFormLabelWithName = Kopier og del lenka for å sende fila: { $filename }
|
||||
copyUrlFormButton = Kopier til utklippstavla
|
||||
copiedUrl = Kopiert!
|
||||
@@ -89,3 +98,4 @@ addPasswordButton = Legg til passord
|
||||
passwordTryAgain = Feil passord. Prøv på nytt.
|
||||
// This label is followed by the password needed to download a file
|
||||
passwordResult = Passord: { $password }
|
||||
reportIPInfringement = Rapporter brot på åndsverk
|
||||
|
||||
@@ -25,6 +25,15 @@ uploadingFileNotification = Me avise quando completar o envio.
|
||||
uploadSuccessConfirmHeader = Pronto para enviar
|
||||
uploadSvgAlt = Enviado
|
||||
uploadSuccessTimingHeader = O link para o seu arquivo expirará após 1 download ou em 24 horas.
|
||||
expireInfo = O link para o seu arquivo expirará após { $downloadCount } ou { $timepan }.
|
||||
downloadCount = { $num ->
|
||||
[one] 1 download
|
||||
*[other] { $num } downloads
|
||||
}
|
||||
timespanHours = { $num ->
|
||||
[one] 1 hora
|
||||
*[other] { $num } horas
|
||||
}
|
||||
copyUrlFormLabelWithName = Copie e compartilhe o link para enviar o seu arquivo: { $filename }
|
||||
copyUrlFormButton = Copiar para área de transferência
|
||||
copiedUrl = Copiado!
|
||||
@@ -89,3 +98,4 @@ addPasswordButton = Adicionar senha
|
||||
passwordTryAgain = Senha incorreta. Tente novamente.
|
||||
// This label is followed by the password needed to download a file
|
||||
passwordResult = Senha: { $password }
|
||||
reportIPInfringement = Reportar violação de IP
|
||||
|
||||
@@ -24,31 +24,37 @@ uploadingPageLargeFileMessage = Este ficheiro é grande e pode demorar um pouco
|
||||
uploadingFileNotification = Notificar-me quando o carregamento estiver completo.
|
||||
uploadSuccessConfirmHeader = Pronto para enviar
|
||||
uploadSvgAlt = Carregar
|
||||
uploadSuccessTimingHeader = A ligação para o seu ficheiro irá expirar depois de 1 descarga ou em 24 horas.
|
||||
uploadSuccessTimingHeader = A ligação para o seu ficheiro irá expirar depois de 1 transferência ou em 24 horas.
|
||||
expireInfo = A ligação para o seu ficheiro irá expirar depois de { $downloadCount } or { $timespan }.
|
||||
downloadCount = { $num ->
|
||||
[one] 1 transferência
|
||||
*[other] { $num } transferências
|
||||
}
|
||||
timespanHours = 1 hora
|
||||
copyUrlFormLabelWithName = Copie e partilhe a ligação para enviar o seu ficheiro: { $filename }
|
||||
copyUrlFormButton = Copiar para a área de transferência
|
||||
copiedUrl = Copiado!
|
||||
deleteFileButton = Apagar ficheiro
|
||||
sendAnotherFileLink = Enviar outro ficheiro
|
||||
// Alternative text used on the download link/button (indicates an action).
|
||||
downloadAltText = Descarregar
|
||||
downloadFileName = Descarregar { $filename }
|
||||
downloadAltText = Transferir
|
||||
downloadFileName = Transferir { $filename }
|
||||
downloadFileSize = ({ $size })
|
||||
unlockInputLabel = Digitar palavra-passe
|
||||
unlockInputPlaceholder = Palavra-passe
|
||||
unlockButtonLabel = Desbloquear
|
||||
downloadFileTitle = Descarregar ficheiro encriptado
|
||||
downloadFileTitle = Transferir ficheiro encriptado
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
downloadMessage = O seu amigo está a enviar-lhe um ficheiro com o Firefox Send, um serviço que lhe permite partilhar ficheiro com uma ligação segura, privada e encriptada que expira automaticamente para garantir que as suas coisas não fiquem online para sempre.
|
||||
// Text and title used on the download link/button (indicates an action).
|
||||
downloadButtonLabel = Descarregar
|
||||
downloadNotification = A sua descarga foi completada.
|
||||
downloadFinish = Descarga completada
|
||||
downloadButtonLabel = Transferir
|
||||
downloadNotification = A sua transferência foi concluída.
|
||||
downloadFinish = Transferência concluída
|
||||
// This message is displayed when uploading or downloading a file, e.g. "(1,3 MB of 10 MB)".
|
||||
fileSizeProgress = ({ $partialSize } de { $totalSize })
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
sendYourFilesLink = Tentar o Firefox Send
|
||||
downloadingPageProgress = A descarregar { $filename } ({ $size })
|
||||
sendYourFilesLink = Experimentar o Firefox Send
|
||||
downloadingPageProgress = A transferir { $filename } ({ $size })
|
||||
downloadingPageMessage = Por favor deixe este separador aberto enquanto obtemos o seu ficheiro e o desencriptamos.
|
||||
errorAltText = Erro ao carregar
|
||||
errorPageHeader = Algo correu mal.
|
||||
@@ -63,7 +69,7 @@ notSupportedDetail = Infelizmente este navegador não suporta a tecnologia web q
|
||||
notSupportedLink = Porque é que o meu navegador não é suportado?
|
||||
notSupportedOutdatedDetail = Infelizmente esta versão do Firefox não suporta a tecnologia web que faz o Firefox Send funcionar. Precisa de atualizar o seu navegador.
|
||||
updateFirefox = Atualizar o Firefox
|
||||
downloadFirefoxButtonSub = Descarga gratuita
|
||||
downloadFirefoxButtonSub = Transferência gratuita
|
||||
uploadedFile = Ficheiro
|
||||
copyFileList = Copiar URL
|
||||
// expiryFileList is used as a column header
|
||||
@@ -72,7 +78,7 @@ deleteFileList = Apagar
|
||||
nevermindButton = Esquecer
|
||||
legalHeader = Termos e privacidade
|
||||
legalNoticeTestPilot = O Firefox Send é atualmente uma experiência do Test Pilot, e sujeita aos <a>Termos de serviço</a> e <a>Aviso de privacidade</a> do Test Pilot. Pode saber mais acerca desta experiência e a sua recolha de dados <a>aqui</a>.
|
||||
legalNoticeMozilla = A utilização do website do Firefox Send está também sujeita ao <a>Aviso de privacidade dos websites</a> e <a>Termos de serviço dos websites</a> da Mozilla.
|
||||
legalNoticeMozilla = A utilização do website do Firefox Send está também sujeita ao <a>Aviso de privacidade dos websites</a> e <a>Termos de utilização dos websites</a> da Mozilla.
|
||||
deletePopupText = Apagar este ficheiro?
|
||||
deletePopupYes = Sim
|
||||
deletePopupCancel = Cancelar
|
||||
@@ -84,8 +90,9 @@ footerLinkAbout = Acerca do Test Pilot
|
||||
footerLinkPrivacy = Privacidade
|
||||
footerLinkTerms = Termos
|
||||
footerLinkCookies = Cookies
|
||||
requirePasswordCheckbox = Requerer uma palavra-passe para descarregar este ficheiro
|
||||
requirePasswordCheckbox = Requerer uma palavra-passe para transferir este ficheiro
|
||||
addPasswordButton = Adicionar palavra-passe
|
||||
passwordTryAgain = Palavra-passe incorreta. Tente novamente.
|
||||
// This label is followed by the password needed to download a file
|
||||
passwordResult = Palavra-passe: { $password }
|
||||
reportIPInfringement = Reportar violação de PI
|
||||
|
||||
@@ -3,8 +3,10 @@ title = Firefox Send
|
||||
siteSubtitle = un experiment web
|
||||
siteFeedback = Feedback
|
||||
uploadPageHeader = Partajare de fișiere privată și criptată
|
||||
uploadPageExplainer = Trimite fișiere printr-un link sigur, privat și criptat care expiră automat pentru ca informațiile să rămână în siguranță.
|
||||
uploadPageLearnMore = Află mai multe
|
||||
uploadPageDropMessage = Aruncă fișierul aici pentru a începe încărcarea.
|
||||
uploadPageSizeMessage = Pentru a lucra mai ușor, recomandăm să păstrezi fișierul sub 1GB
|
||||
uploadPageBrowseButton = Alege un fișier din calculator.
|
||||
uploadPageBrowseButton1 = Selectează un fișier pentru încărcare
|
||||
uploadPageMultipleFilesAlert = Încărcarea mai multor fișiere deodată sau a dosarelor nu este suportată.
|
||||
@@ -23,6 +25,14 @@ uploadingFileNotification = Notifică-mă când încărcarea este încheiată.
|
||||
uploadSuccessConfirmHeader = Pregătit pentru trimitere
|
||||
uploadSvgAlt = Încarcă
|
||||
uploadSuccessTimingHeader = Linkul către fișierul tău va expira după 1 descărcare sau în 24 de ore.
|
||||
expireInfo = Linkul la fișier va expira după { $downloadCount } sau { $timespan }.
|
||||
downloadCount =
|
||||
timespanHours = { $num ->
|
||||
[one] 1 oră
|
||||
[few] ore
|
||||
*[other] de ore
|
||||
}
|
||||
copyUrlFormLabelWithName = Copiază și împărtășește linkul de la fișierul de trimis: { $filename }
|
||||
copyUrlFormButton = Copiază în clipboard
|
||||
copiedUrl = Copiat!
|
||||
deleteFileButton = Șterge fișierul
|
||||
@@ -35,6 +45,8 @@ unlockInputLabel = Introdu parola
|
||||
unlockInputPlaceholder = Parolă
|
||||
unlockButtonLabel = Deblochează
|
||||
downloadFileTitle = Descarcă fișierul criptat
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
downloadMessage = Un prieten îți trimite un fișier prin Firefox Send, un serviciu care îți permite să împărtășești un fișier printr-un link sigur, privat și criptat care expiră automat pentru a păstra informațiile tale online doar temporar.
|
||||
// Text and title used on the download link/button (indicates an action).
|
||||
downloadButtonLabel = Descarcă
|
||||
downloadNotification = Descărcarea s-a încheiat.
|
||||
@@ -44,6 +56,7 @@ fileSizeProgress = ({ $partialSize } din { $totalSize })
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
sendYourFilesLink = Încearcă Firefox Send
|
||||
downloadingPageProgress = Se descarcă { $filename } ({ $size })
|
||||
downloadingPageMessage = Te rugăm să păstrezi această file deschisă în timp ce preluăm fișierul și îl decriptăm.
|
||||
errorAltText = Eroare la încărcare
|
||||
errorPageHeader = Ceva a mers prost!
|
||||
errorPageMessage = A apărut o eroare la încărcarea fișierului.
|
||||
@@ -52,7 +65,10 @@ fileTooBig = Acest fișier este prea mare. Trebuie să fie sub { $size }.
|
||||
linkExpiredAlt = Link expirat
|
||||
expiredPageHeader = Acest link a expirat sau nu a existat de la bun început!
|
||||
notSupportedHeader = Browserul tău nu este suportat.
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
notSupportedDetail = Din păcate acest browser nu suportă tehnologii web precum Firefox Send. Trebuie să încerci alt browser. Îți recomandăm Firefox!
|
||||
notSupportedLink = De ce browserul meu nu este suportat?
|
||||
notSupportedOutdatedDetail = Din păcate această versiune de Firefox nu suportă tehnologiile web din spatele Firefox Sent. Îți recomandăm să actualizezi browserul.
|
||||
updateFirefox = Actualizează Firefox
|
||||
downloadFirefoxButtonSub = Descărcare gratuită
|
||||
uploadedFile = Fișier
|
||||
@@ -62,6 +78,8 @@ expiryFileList = Expiră în
|
||||
deleteFileList = Șterge
|
||||
nevermindButton = Uită
|
||||
legalHeader = Termeni de utilizare și politica de confidențialitate
|
||||
legalNoticeTestPilot = Firefox Send este momentan un experiment Test Pilot și supus <a>Termenilor de utilizare</a> Test Pilot și a <a>Politicii de confidențialitate</a>. Poți afla mai multe despre acest experiment <a>aici</a>.
|
||||
legalNoticeMozilla = Folosirea site-ului Firefox Send mai este supusă <a>Politicii de confidențialitate pentru site-uri web</a> și a <a>Termenilor de folosire a site-urilor web</a>.
|
||||
deletePopupText = Ștergi aceast fișier?
|
||||
deletePopupYes = Da
|
||||
deletePopupCancel = Renunță
|
||||
@@ -73,4 +91,9 @@ footerLinkAbout = Despre Test Pilot
|
||||
footerLinkPrivacy = Confidențialitate
|
||||
footerLinkTerms = Termeni
|
||||
footerLinkCookies = Cookie-uri
|
||||
requirePasswordCheckbox = Este necesară o parolă pentru a descărca acest fișier
|
||||
addPasswordButton = Adaugă parolă
|
||||
passwordTryAgain = Parola este incorectă. Încearcă din nou.
|
||||
// This label is followed by the password needed to download a file
|
||||
passwordResult = Parola: { $password }
|
||||
reportIPInfringement = Raportează încălcarea proprietății intelectuale
|
||||
|
||||
@@ -25,6 +25,17 @@ uploadingFileNotification = Оповестить меня, когда загру
|
||||
uploadSuccessConfirmHeader = Готов к отправке
|
||||
uploadSvgAlt = Загрузить
|
||||
uploadSuccessTimingHeader = Ссылка на ваш файл станет недоступна после 1 загрузки файла или через 24 часа.
|
||||
expireInfo = Ссылка на ваш файл станет недоступна после { $downloadCount } файла или через { $timespan }.
|
||||
downloadCount = { $num ->
|
||||
[one] { $number } загрузки
|
||||
[few] { $number } загрузок
|
||||
*[other] { $number } загрузок
|
||||
}
|
||||
timespanHours = { $num ->
|
||||
[one] { $number } час
|
||||
[few] { $number } часа
|
||||
*[other] { $number } часов
|
||||
}
|
||||
copyUrlFormLabelWithName = Скопировать и поделиться ссылкой на отправку вашего файла: { $filename }
|
||||
copyUrlFormButton = Скопировать в буфер обмена
|
||||
copiedUrl = Скопировано!
|
||||
@@ -89,3 +100,4 @@ addPasswordButton = Добавить пароль
|
||||
passwordTryAgain = Неверный пароль. Попробуйте снова.
|
||||
// This label is followed by the password needed to download a file
|
||||
passwordResult = Пароль: { $password }
|
||||
reportIPInfringement = Сообщить о нарушении прав на интеллектуальную собственность
|
||||
|
||||
@@ -25,6 +25,17 @@ uploadingFileNotification = Upozorniť ma na ukončenie nahrávania
|
||||
uploadSuccessConfirmHeader = Pripravené na odoslanie
|
||||
uploadSvgAlt = Nahrať
|
||||
uploadSuccessTimingHeader = Platnosť odkazu vyprší po 1 prevzatí alebo po uplynutí 24 hodín.
|
||||
expireInfo = Platnosť odkazu na váš súbor vyprší po { $downloadCount } alebo po { $timespan }.
|
||||
downloadCount = { $num ->
|
||||
[one] 1 prevzatí
|
||||
[few] { $num } prevzatiach
|
||||
*[other] { $num } prevzatiach
|
||||
}
|
||||
timespanHours = { $num ->
|
||||
[one] 1 hodine
|
||||
[few] { $num } hodinách
|
||||
*[other] { $num } hodinách
|
||||
}
|
||||
copyUrlFormLabelWithName = Skopírovaním a zdieľaním odkazu odošlete váš súbor: { $filename }
|
||||
copyUrlFormButton = Kopírovať do schránky
|
||||
copiedUrl = Skopírované!
|
||||
@@ -89,3 +100,4 @@ addPasswordButton = Pridať heslo
|
||||
passwordTryAgain = Nesprávne heslo. Skúste to znova.
|
||||
// This label is followed by the password needed to download a file
|
||||
passwordResult = Heslo: { $password }
|
||||
reportIPInfringement = Nahlásiť porušenie práv duševného vlastníctva
|
||||
|
||||
@@ -25,6 +25,19 @@ uploadingFileNotification = Obvesti me, ko bo nalaganje končano.
|
||||
uploadSuccessConfirmHeader = Pripravljeno za pošiljanje
|
||||
uploadSvgAlt = Naloži
|
||||
uploadSuccessTimingHeader = Povezava do vaše datoteke bo potekla po enem prenosu ali v 24 urah.
|
||||
expireInfo = Povezava do vaše datoteke bo potekla čez { $downloadCount } ali { $timespan }.
|
||||
downloadCount = { $num ->
|
||||
[one] 1 prenos
|
||||
[two] { $num } prenosa
|
||||
[few] { $num } prenosi
|
||||
*[other] { $num } prenosov
|
||||
}
|
||||
timespanHours = { $num ->
|
||||
[one] 1 ura
|
||||
[two] { $num } uri
|
||||
[few] { $num } ure
|
||||
*[other] { $num } ur
|
||||
}
|
||||
copyUrlFormLabelWithName = Kopirajte in delite to povezavo, da pošljete datoteko: { $filename }
|
||||
copyUrlFormButton = Kopiraj v odložišče
|
||||
copiedUrl = Kopirano!
|
||||
@@ -89,3 +102,4 @@ addPasswordButton = Dodaj geslo
|
||||
passwordTryAgain = Napačno geslo. Poskusite znova.
|
||||
// This label is followed by the password needed to download a file
|
||||
passwordResult = Geslo: { $password }
|
||||
reportIPInfringement = Prijavite kršitev naslova IP
|
||||
|
||||
101
public/locales/sq/send.ftl
Normal file
101
public/locales/sq/send.ftl
Normal file
@@ -0,0 +1,101 @@
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
title = Firefox Send
|
||||
siteSubtitle = eksperiment web
|
||||
siteFeedback = Përshtypje
|
||||
uploadPageHeader = Shkëmbim Privat, i Fshehtëzuar, Kartelash
|
||||
uploadPageExplainer = Dërgoni kartela përmes një lidhjeje të parrezik, private dhe të fshehtëzuar, që skadon automatikisht për të garantuar që gjërat tuaja nuk mbesin në internet përgjithmonë.
|
||||
uploadPageLearnMore = Mësoni më tepër
|
||||
uploadPageDropMessage = Që të fillojë ngarkimi, hidheni kartelën tuaj këtu
|
||||
uploadPageSizeMessage = Për ecurinë më të qëndrueshme, më e mira është t’i mbani kartelat tuaja nën 1GB
|
||||
uploadPageBrowseButton = Përzgjidhni një kartelë nga kompjuteri juaj
|
||||
uploadPageBrowseButton1 = Përzgjidhni një kartelë për ngarkim
|
||||
uploadPageMultipleFilesAlert = Ngarkimi i shumë kartelave njëherësh, ose i një dosjeje, hëpërhë nuk mbulohen.
|
||||
uploadPageBrowseButtonTitle = Ngarkoje kartelën
|
||||
uploadingPageProgress = Po ngarkohet { $filename } ({ $size })
|
||||
importingFile = Po importohet…
|
||||
verifyingFile = Po verifikohet…
|
||||
encryptingFile = Po fshehtëzohet…
|
||||
decryptingFile = Po shfshehtëzohet…
|
||||
notifyUploadDone = Ngarkimi juaj përfundoi.
|
||||
uploadingPageMessage = Do të jeni në gjendje të caktoni parametra skadimi sapo kartela juaj të jetë ngarkuar.
|
||||
uploadingPageCancel = Anuloje ngarkimin
|
||||
uploadCancelNotification = Ngarkimi juaj u anulua.
|
||||
uploadingPageLargeFileMessage = Kjo kartelë është e madhe dhe mund të dojë ca kohë të ngarkohet. Rrini këtu!
|
||||
uploadingFileNotification = Njoftomë kur të jetë plotësuar ngarkimi .
|
||||
uploadSuccessConfirmHeader = Gati për Dërgim
|
||||
uploadSvgAlt = Ngarkoje
|
||||
uploadSuccessTimingHeader = Lidhja për te kartela juaj do të skadojë pas 1 shkarkimi ose pas 24 orësh.
|
||||
expireInfo = Lidhja për te kartela juaj do të skadojë pas { $downloadCount } ose { $timespan }.
|
||||
downloadCount = { $num ->
|
||||
[one] 1 shkarkimi
|
||||
*[other] { $num } shkarkimesh
|
||||
}
|
||||
timespanHours = { $num ->
|
||||
[one] 1 ore
|
||||
*[other] { $num } orësh
|
||||
}
|
||||
copyUrlFormLabelWithName = Kopjojeni dhe jepuani të tjerëve lidhje që të dërgoni kartelën tuaj: { $filename }
|
||||
copyUrlFormButton = Kopjoje te e papastra
|
||||
copiedUrl = U kopjua!
|
||||
deleteFileButton = Fshije kartelën
|
||||
sendAnotherFileLink = Dërgoni një kartelë tjetër
|
||||
// Alternative text used on the download link/button (indicates an action).
|
||||
downloadAltText = Shkarkoje
|
||||
downloadFileName = Shkarkoje { $filename }
|
||||
downloadFileSize = ({ $size })
|
||||
unlockInputLabel = Jepni Fjalëkalimin
|
||||
unlockInputPlaceholder = Fjalëkalim
|
||||
unlockButtonLabel = Zhbllokoje
|
||||
downloadFileTitle = Shkarko Kartelën e Fshehtëzuar
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
downloadMessage = Shoku juaj po ju dërgon një kartelë me Firefox Send, një shërbim që ju lejon të shkëmbeni kartela përmes një lidhjeje të parrezik, private, dhe të fshehtëzuar, që skadon automatikisht, për të garantuar që gjërat tuaja të mos mbeten në internet përgjithmonë.
|
||||
// Text and title used on the download link/button (indicates an action).
|
||||
downloadButtonLabel = Shkarkoje
|
||||
downloadNotification = Shkarkimi juaj u plotësua.
|
||||
downloadFinish = Shkarkim i Plotësuar
|
||||
// This message is displayed when uploading or downloading a file, e.g. "(1,3 MB of 10 MB)".
|
||||
fileSizeProgress = ({ $partialSize } nga { $totalSize }) gjithsej
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
sendYourFilesLink = Provoni Firefox Send
|
||||
downloadingPageProgress = Po shkarkohet { $filename } ({ $size })
|
||||
downloadingPageMessage = Ju lutemi, lëreni hapur këtë skedë ndërkohë që ne sjellim dhe shfshehtëzojmë kartelën tuaj.
|
||||
errorAltText = Gabim ngarkimi
|
||||
errorPageHeader = Diç shkoi ters!
|
||||
errorPageMessage = Pati një gabim gjatë ngarkimit të kartelës.
|
||||
errorPageLink = Dërgoni një kartelë tjetër
|
||||
fileTooBig = Kjo kartelë është shumë e madhe për ngarkim. Do të duhej të ishte më pak se { $size }.
|
||||
linkExpiredAlt = Lidhja skadoi
|
||||
expiredPageHeader = Kjo lidhje ka skaduar ose s’ka ekzistuar kurrë!
|
||||
notSupportedHeader = Shfletuesi juaj nuk mbulohet.
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
notSupportedDetail = Mjerisht, ky shfletues nuk mbulon teknologjinë web mbi të cilën bazohet Firefox Send.Do t’ju duhet të provoni një shfletues tjetër. Ju këshillojmë Firefox-in!
|
||||
notSupportedLink = Pse nuk mbulohet ky shfletues?
|
||||
notSupportedOutdatedDetail = Mjerisht, ky version i Firefox-it nuk e mbulon teknologjinë web mbi të cilën bazohet Firefox Send. Do t’ju duhet të përditësoni shfletuesin tuaj.
|
||||
updateFirefox = Përditësojeni Firefox-in
|
||||
downloadFirefoxButtonSub = Shkarkim Falas
|
||||
uploadedFile = Kartelë
|
||||
copyFileList = Kopjo URL-në
|
||||
// expiryFileList is used as a column header
|
||||
expiryFileList = Skadon Më
|
||||
deleteFileList = Fshije
|
||||
nevermindButton = S’prish punë
|
||||
legalHeader = Kushte & Privatësi
|
||||
legalNoticeTestPilot = Firefox Send është një eksperiment Pilot Testesh dhe subjekt i <a>Kushteve të Shërbimit</a> dhe <a>Shënim Privacësie</a> për Pilot Testesh. <a>Këtu</a> mund të mësoni më tepër mbi këtë eksperiment dhe grumbullimit të të dhënave që ai kryen.
|
||||
legalNoticeMozilla = Përdorimi i sajtit Firefox Send është gjithashtu subjekt i <a>Shënimit Mbi Privatësi Sajtesh</a> të Mozilla-s dhe <a>Kushteve të Përdorimit të Sajtit</a>.
|
||||
deletePopupText = Të fshihet kjo kartelë?
|
||||
deletePopupYes = Po
|
||||
deletePopupCancel = Anuloje
|
||||
deleteButtonHover = Fshije
|
||||
copyUrlHover = Kopjoji URL-në
|
||||
footerLinkLegal = Ligjore
|
||||
// Test Pilot is a proper name and should not be localized.
|
||||
footerLinkAbout = Rreth Pilot Testesh
|
||||
footerLinkPrivacy = Privatësi
|
||||
footerLinkTerms = Kushte
|
||||
footerLinkCookies = Cookies
|
||||
requirePasswordCheckbox = Kërko doemos një fjalëkalim për shkarkim të kësaj kartele
|
||||
addPasswordButton = Shtoni fjalëkalim
|
||||
passwordTryAgain = Fjalëkalim i pasaktë. Riprovoni.
|
||||
// This label is followed by the password needed to download a file
|
||||
passwordResult = Fjalëkalim: { $password }
|
||||
reportIPInfringement = Raportoni Cenim IP-je
|
||||
@@ -25,6 +25,17 @@ uploadingFileNotification = Обавести ме када се отпремањ
|
||||
uploadSuccessConfirmHeader = Спреман за слање
|
||||
uploadSvgAlt = Отпреми
|
||||
uploadSuccessTimingHeader = Веза ка вашој датотеци ће истећи након једног преузимања или након 24 сата.
|
||||
expireInfo = Веза ка вашој датотеци ће истећи након { $downloadCount } или { $timespan }.
|
||||
downloadCount = { $num ->
|
||||
[one] преузимања
|
||||
[few] преузимања
|
||||
*[other] преузимања
|
||||
}
|
||||
timespanHours = { $num ->
|
||||
[one] сата
|
||||
[few] сата
|
||||
*[other] сати
|
||||
}
|
||||
copyUrlFormLabelWithName = Ископирајте и поделите везу да бисте послали вашу датотеку: { $filename }
|
||||
copyUrlFormButton = Копирај у оставу
|
||||
copiedUrl = Ископирано!
|
||||
@@ -89,3 +100,4 @@ addPasswordButton = Додај лозинку
|
||||
passwordTryAgain = Нетачна лозинка. Пробајте поново.
|
||||
// This label is followed by the password needed to download a file
|
||||
passwordResult = Лозинка: { $password }
|
||||
reportIPInfringement = Пријавите IP прекршај
|
||||
|
||||
@@ -25,6 +25,15 @@ uploadingFileNotification = Meddela mig när uppladdningen är klar.
|
||||
uploadSuccessConfirmHeader = Klar för att skicka
|
||||
uploadSvgAlt = Ladda upp
|
||||
uploadSuccessTimingHeader = Länken till din fil upphör att gälla efter 1 nedladdning eller om 24 timmar.
|
||||
expireInfo = Länken till din fil upphör att gälla efter { $downloadCount } eller { $timespan }.
|
||||
downloadCount = { $num ->
|
||||
[one] 1 nedladdning
|
||||
*[other] { $num } nedladdningar
|
||||
}
|
||||
timespanHours = { $num ->
|
||||
[one] 1 timme
|
||||
*[other] { $num } timmar
|
||||
}
|
||||
copyUrlFormLabelWithName = Kopiera och dela länken för att skicka din fil: { $filename }
|
||||
copyUrlFormButton = Kopiera till urklipp
|
||||
copiedUrl = Kopierad!
|
||||
@@ -89,3 +98,4 @@ addPasswordButton = Lägg till lösenord
|
||||
passwordTryAgain = Felaktigt lösenord. Försök igen.
|
||||
// This label is followed by the password needed to download a file
|
||||
passwordResult = Lösenord: { $password }
|
||||
reportIPInfringement = Rapportera IP-överträdelse
|
||||
|
||||
@@ -25,6 +25,14 @@ uploadingFileNotification = Abisuhan ako kapag nakumpleto na ang pag-upload.
|
||||
uploadSuccessConfirmHeader = Handa nang Ipadala
|
||||
uploadSvgAlt = I-upload
|
||||
uploadSuccessTimingHeader = Mag-e-expire ang link sa iyong file pagkatapos ng 1 pag-download o sa loob ng 24 na oras.
|
||||
expireInfo = Mag-e-expire ang link sa iyong file pagkatapos ng { $downloadCount } o { $timespan }.
|
||||
downloadCount = { $num ->
|
||||
[one] 1 pag-download
|
||||
*[other] { $num } na mga pag-download
|
||||
}
|
||||
timespanHours = { $num ->
|
||||
*[one] 1 oras
|
||||
}
|
||||
copyUrlFormLabelWithName = Kopyahin at ibahagi ang link upang ipadala ang iyong file: { $filename }
|
||||
copyUrlFormButton = Kopyahin sa clipboard
|
||||
copiedUrl = Naikopya!
|
||||
@@ -67,7 +75,7 @@ downloadFirefoxButtonSub = Libreng Download
|
||||
uploadedFile = File
|
||||
copyFileList = Kopyahin ang URL
|
||||
// expiryFileList is used as a column header
|
||||
expiryFileList = Magtatapos Sa
|
||||
expiryFileList = Magtatapos Sa
|
||||
deleteFileList = I-delete
|
||||
nevermindButton = Hindi bale
|
||||
legalHeader = Mga Tuntunin at Pagkapribado
|
||||
@@ -89,3 +97,4 @@ addPasswordButton = Magdagdag ng password
|
||||
passwordTryAgain = Maling password. Subukan muli.
|
||||
// This label is followed by the password needed to download a file
|
||||
passwordResult = Password: { $password }
|
||||
reportIPInfringement = Report IP Infringement
|
||||
|
||||
@@ -25,6 +25,11 @@ uploadingFileNotification = Yükleme bitince bana haber ver.
|
||||
uploadSuccessConfirmHeader = Göndermeye hazır
|
||||
uploadSvgAlt = Yükle
|
||||
uploadSuccessTimingHeader = Dosyanız 1 kez indirildikten veya 24 saat geçtikten sonra linkiniz geçersiz olacaktır.
|
||||
expireInfo = Dosyanızın bağlantısı { $downloadCount } sonra veya { $timespan } zaman aşımına uğrayacaktır.
|
||||
downloadCount = { $num } indirme
|
||||
timespanHours = { $num ->
|
||||
*[one] { $num } saat
|
||||
}
|
||||
copyUrlFormLabelWithName = { $filename } dosyanızı başkasına göndermek için aşağıdaki linki kopyalayın.
|
||||
copyUrlFormButton = Panoya kopyala
|
||||
copiedUrl = Kopyalandı!
|
||||
@@ -89,3 +94,4 @@ addPasswordButton = Parola ekle
|
||||
passwordTryAgain = Yanlış parola. Yeniden deneyin.
|
||||
// This label is followed by the password needed to download a file
|
||||
passwordResult = Parola: { $password }
|
||||
reportIPInfringement = Telif hakkı ihlali bildir
|
||||
|
||||
@@ -25,6 +25,17 @@ uploadingFileNotification = Сповістити мене, коли вивант
|
||||
uploadSuccessConfirmHeader = Готовий до надсилання
|
||||
uploadSvgAlt = Вивантажити
|
||||
uploadSuccessTimingHeader = Час дії цього посилання закінчиться після 1 завантаження, або через 24 години.
|
||||
expireInfo = Посилання на ваш файл стане недійсним після { $downloadCount } файла, або через { $timespan }.
|
||||
downloadCount = { $num ->
|
||||
[one] 1 завантаження
|
||||
[few] { $num } завантаження
|
||||
*[other] { $num } завантажень
|
||||
}
|
||||
timespanHours = { $num ->
|
||||
[one] 1 година
|
||||
[few] { $num } години
|
||||
*[other] { $num } годин
|
||||
}
|
||||
copyUrlFormLabelWithName = Скопіювати і поділитися посиланням на ваш файл: { $filename }
|
||||
copyUrlFormButton = Копіювати у буфер обміну
|
||||
copiedUrl = Скопійовано!
|
||||
@@ -34,6 +45,10 @@ sendAnotherFileLink = Надіслати інший файл
|
||||
downloadAltText = Завантаживи
|
||||
downloadFileName = Завантажити { $filename }
|
||||
downloadFileSize = ({ $size })
|
||||
unlockInputLabel = Введіть пароль
|
||||
unlockInputPlaceholder = Пароль
|
||||
unlockButtonLabel = Розблокувати
|
||||
downloadFileTitle = Завантажити зашифрований файл
|
||||
// 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).
|
||||
@@ -80,3 +95,9 @@ footerLinkAbout = Про Test Pilot
|
||||
footerLinkPrivacy = Приватність
|
||||
footerLinkTerms = Умови
|
||||
footerLinkCookies = Куки
|
||||
requirePasswordCheckbox = Вимагати пароль для завантаження цього файлу
|
||||
addPasswordButton = Додати пароль
|
||||
passwordTryAgain = Невірний пароль. Спробуйте знову.
|
||||
// This label is followed by the password needed to download a file
|
||||
passwordResult = Пароль: { $password }
|
||||
reportIPInfringement = Повідомити про порушення прав на інтелектуальну власність
|
||||
|
||||
@@ -25,6 +25,13 @@ uploadingFileNotification = 上传完成后通知我。
|
||||
uploadSuccessConfirmHeader = 准备好发送
|
||||
uploadSvgAlt = 上传
|
||||
uploadSuccessTimingHeader = 您的文件的链接将在首次下载或 24 小时后过期。
|
||||
expireInfo = 指向该文件的链接将在 { $downloadCount } 或 { $timespan } 后过期。
|
||||
downloadCount = { $num ->
|
||||
*[other] { $num } 次下载
|
||||
}
|
||||
timespanHours = { $num ->
|
||||
*[other] { $num } 小时
|
||||
}
|
||||
copyUrlFormLabelWithName = 复制并分享链接以发送您的文件:{ $filename }
|
||||
copyUrlFormButton = 复制到剪贴板
|
||||
copiedUrl = 已复制!
|
||||
@@ -89,3 +96,4 @@ addPasswordButton = 添加密码
|
||||
passwordTryAgain = 密码不正确。请重试。
|
||||
// This label is followed by the password needed to download a file
|
||||
passwordResult = 密码:{ $password }
|
||||
reportIPInfringement = 举报知识产权侵权
|
||||
|
||||
@@ -25,6 +25,13 @@ uploadingFileNotification = 上傳完成時通知我。
|
||||
uploadSuccessConfirmHeader = 準備好傳送
|
||||
uploadSvgAlt = 上傳
|
||||
uploadSuccessTimingHeader = 您的檔案鏈結將會在首次下載,或 24 小時後失效。
|
||||
expireInfo = 檔案鏈結將在 { $downloadCount }或 { $timespan }後失效。
|
||||
downloadCount = { $num ->
|
||||
*[other] { $num } 次下載
|
||||
}
|
||||
timespanHours = { $num ->
|
||||
*[other] { $num } 小時
|
||||
}
|
||||
copyUrlFormLabelWithName = 複製並分享鏈結來傳送您的檔案: { $filename }
|
||||
copyUrlFormButton = 複製到剪貼簿
|
||||
copiedUrl = 已複製!
|
||||
@@ -89,3 +96,4 @@ addPasswordButton = 新增密碼
|
||||
passwordTryAgain = 密碼不正確,請再試一次。
|
||||
// This label is followed by the password needed to download a file
|
||||
passwordResult = 密碼: { $password }
|
||||
reportIPInfringement = 回報智慧財產權濫用情況
|
||||
|
||||
@@ -12,15 +12,15 @@ module.exports = async function(req, res) {
|
||||
return;
|
||||
}
|
||||
|
||||
const delete_token = req.body.delete_token;
|
||||
const ownerToken = req.body.owner_token || req.body.delete_token;
|
||||
|
||||
if (!delete_token) {
|
||||
if (!ownerToken) {
|
||||
res.sendStatus(404);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const err = await storage.delete(id, delete_token);
|
||||
const err = await storage.delete(id, ownerToken);
|
||||
if (!err) {
|
||||
res.sendStatus(200);
|
||||
}
|
||||
|
||||
@@ -19,12 +19,12 @@ module.exports = async function(req, res) {
|
||||
const hmac = crypto.createHmac('sha256', Buffer.from(meta.auth, 'base64'));
|
||||
hmac.update(Buffer.from(meta.nonce, 'base64'));
|
||||
const verifyHash = hmac.digest();
|
||||
const nonce = crypto.randomBytes(16).toString('base64');
|
||||
storage.setField(id, 'nonce', nonce);
|
||||
if (!verifyHash.equals(Buffer.from(auth, 'base64'))) {
|
||||
res.set('WWW-Authenticate', `send-v1 ${nonce}`);
|
||||
res.set('WWW-Authenticate', `send-v1 ${meta.nonce}`);
|
||||
return res.sendStatus(401);
|
||||
}
|
||||
const nonce = crypto.randomBytes(16).toString('base64');
|
||||
storage.setField(id, 'nonce', nonce);
|
||||
const contentLength = await storage.length(id);
|
||||
res.writeHead(200, {
|
||||
'Content-Disposition': 'attachment',
|
||||
@@ -36,10 +36,16 @@ module.exports = async function(req, res) {
|
||||
const file_stream = storage.get(id);
|
||||
|
||||
file_stream.on('end', async () => {
|
||||
const dl = (+meta.dl || 0) + 1;
|
||||
const dlimit = +meta.dlimit || 1;
|
||||
try {
|
||||
await storage.forceDelete(id);
|
||||
if (dl >= dlimit) {
|
||||
await storage.forceDelete(id);
|
||||
} else {
|
||||
await storage.setField(id, 'dl', dl);
|
||||
}
|
||||
} catch (e) {
|
||||
log.info('DeleteError:', id);
|
||||
log.info('StorageError:', id);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -42,26 +42,32 @@ module.exports = function(app) {
|
||||
force: !IS_DEV
|
||||
})
|
||||
);
|
||||
app.use(
|
||||
helmet.contentSecurityPolicy({
|
||||
directives: {
|
||||
defaultSrc: ["'self'"],
|
||||
connectSrc: [
|
||||
"'self'",
|
||||
'https://sentry.prod.mozaws.net',
|
||||
'https://www.google-analytics.com'
|
||||
],
|
||||
imgSrc: ["'self'", 'https://www.google-analytics.com'],
|
||||
scriptSrc: ["'self'"],
|
||||
styleSrc: ["'self'", "'unsafe-inline'", 'https://code.cdn.mozilla.net'],
|
||||
fontSrc: ["'self'", 'https://code.cdn.mozilla.net'],
|
||||
formAction: ["'none'"],
|
||||
frameAncestors: ["'none'"],
|
||||
objectSrc: ["'none'"],
|
||||
reportUri: '/__cspreport__'
|
||||
}
|
||||
})
|
||||
);
|
||||
if (!IS_DEV) {
|
||||
app.use(
|
||||
helmet.contentSecurityPolicy({
|
||||
directives: {
|
||||
defaultSrc: ["'self'"],
|
||||
connectSrc: [
|
||||
"'self'",
|
||||
'https://sentry.prod.mozaws.net',
|
||||
'https://www.google-analytics.com'
|
||||
],
|
||||
imgSrc: ["'self'", 'https://www.google-analytics.com'],
|
||||
scriptSrc: ["'self'"],
|
||||
styleSrc: [
|
||||
"'self'",
|
||||
"'unsafe-inline'",
|
||||
'https://code.cdn.mozilla.net'
|
||||
],
|
||||
fontSrc: ["'self'", 'https://code.cdn.mozilla.net'],
|
||||
formAction: ["'none'"],
|
||||
frameAncestors: ["'none'"],
|
||||
objectSrc: ["'none'"],
|
||||
reportUri: '/__cspreport__'
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
app.use(
|
||||
busboy({
|
||||
limits: {
|
||||
@@ -88,6 +94,7 @@ module.exports = function(app) {
|
||||
app.post('/api/upload', require('./upload'));
|
||||
app.post('/api/delete/:id', require('./delete'));
|
||||
app.post('/api/password/:id', require('./password'));
|
||||
app.post('/api/params/:id', require('./params'));
|
||||
|
||||
app.get('/__version__', function(req, res) {
|
||||
res.sendFile(require.resolve('../../dist/version.json'));
|
||||
|
||||
@@ -17,12 +17,14 @@ module.exports = async function(req, res) {
|
||||
const hmac = crypto.createHmac('sha256', Buffer.from(meta.auth, 'base64'));
|
||||
hmac.update(Buffer.from(meta.nonce, 'base64'));
|
||||
const verifyHash = hmac.digest();
|
||||
if (!verifyHash.equals(Buffer.from(auth, 'base64'))) {
|
||||
res.set('WWW-Authenticate', `send-v1 ${meta.nonce}`);
|
||||
return res.sendStatus(401);
|
||||
}
|
||||
const nonce = crypto.randomBytes(16).toString('base64');
|
||||
storage.setField(id, 'nonce', nonce);
|
||||
res.set('WWW-Authenticate', `send-v1 ${nonce}`);
|
||||
if (!verifyHash.equals(Buffer.from(auth, 'base64'))) {
|
||||
return res.sendStatus(401);
|
||||
}
|
||||
|
||||
const size = await storage.length(id);
|
||||
const ttl = await storage.ttl(id);
|
||||
res.send({
|
||||
|
||||
32
server/routes/params.js
Normal file
32
server/routes/params.js
Normal file
@@ -0,0 +1,32 @@
|
||||
const storage = require('../storage');
|
||||
|
||||
function validateID(route_id) {
|
||||
return route_id.match(/^[0-9a-fA-F]{10}$/) !== null;
|
||||
}
|
||||
|
||||
module.exports = async function(req, res) {
|
||||
const id = req.params.id;
|
||||
if (!validateID(id)) {
|
||||
return res.sendStatus(404);
|
||||
}
|
||||
const ownerToken = req.body.owner_token;
|
||||
if (!ownerToken) {
|
||||
return res.sendStatus(400);
|
||||
}
|
||||
|
||||
const dlimit = req.body.dlimit;
|
||||
if (!dlimit || dlimit > 20) {
|
||||
return res.sendStatus(400);
|
||||
}
|
||||
|
||||
try {
|
||||
const meta = await storage.metadata(id);
|
||||
if (meta.owner !== ownerToken) {
|
||||
return res.sendStatus(400);
|
||||
}
|
||||
storage.setField(id, 'dlimit', dlimit);
|
||||
res.sendStatus(200);
|
||||
} catch (e) {
|
||||
res.sendStatus(404);
|
||||
}
|
||||
};
|
||||
@@ -20,15 +20,16 @@ module.exports = async function(req, res) {
|
||||
const hmac = crypto.createHmac('sha256', Buffer.from(meta.auth, 'base64'));
|
||||
hmac.update(Buffer.from(meta.nonce, 'base64'));
|
||||
const verifyHash = hmac.digest();
|
||||
const nonce = crypto.randomBytes(16).toString('base64');
|
||||
storage.setField(id, 'nonce', nonce);
|
||||
if (!verifyHash.equals(Buffer.from(auth, 'base64'))) {
|
||||
res.set('WWW-Authenticate', `send-v1 ${nonce}`);
|
||||
res.set('WWW-Authenticate', `send-v1 ${meta.nonce}`);
|
||||
return res.sendStatus(401);
|
||||
}
|
||||
} catch (e) {
|
||||
res.sendStatus(404);
|
||||
return res.sendStatus(404);
|
||||
}
|
||||
const nonce = crypto.randomBytes(16).toString('base64');
|
||||
storage.setField(id, 'nonce', nonce);
|
||||
res.set('WWW-Authenticate', `send-v1 ${nonce}`);
|
||||
storage.setField(id, 'auth', req.body.auth);
|
||||
storage.setField(id, 'pwd', 1);
|
||||
res.sendStatus(200);
|
||||
|
||||
@@ -12,9 +12,12 @@ module.exports = function(req, res) {
|
||||
if (!metadata || !auth) {
|
||||
return res.sendStatus(400);
|
||||
}
|
||||
|
||||
const owner = crypto.randomBytes(10).toString('hex');
|
||||
const meta = {
|
||||
delete: crypto.randomBytes(10).toString('hex'),
|
||||
dlimit: 1,
|
||||
dl: 0,
|
||||
owner,
|
||||
delete: owner, // delete is deprecated
|
||||
metadata,
|
||||
pwd: 0,
|
||||
auth: auth.split(' ')[1],
|
||||
@@ -30,7 +33,7 @@ module.exports = function(req, res) {
|
||||
res.set('WWW-Authenticate', `send-v1 ${meta.nonce}`);
|
||||
res.json({
|
||||
url,
|
||||
delete: meta.delete,
|
||||
owner: meta.owner,
|
||||
id: newId
|
||||
});
|
||||
} catch (e) {
|
||||
|
||||
@@ -134,7 +134,7 @@ function localSet(newId, file, meta) {
|
||||
redis_client.hmset(newId, meta);
|
||||
redis_client.expire(newId, config.expire_seconds);
|
||||
log.info('localSet:', 'Upload Finished of ' + newId);
|
||||
resolve(meta.delete);
|
||||
resolve(meta.owner);
|
||||
});
|
||||
|
||||
fstream.on('error', err => {
|
||||
@@ -145,10 +145,10 @@ function localSet(newId, file, meta) {
|
||||
});
|
||||
}
|
||||
|
||||
function localDelete(id, delete_token) {
|
||||
function localDelete(id, ownerToken) {
|
||||
return new Promise((resolve, reject) => {
|
||||
redis_client.hget(id, 'delete', (err, reply) => {
|
||||
if (!reply || delete_token !== reply) {
|
||||
if (!reply || ownerToken !== reply) {
|
||||
reject();
|
||||
} else {
|
||||
redis_client.del(id);
|
||||
@@ -230,10 +230,10 @@ function awsSet(newId, file, meta) {
|
||||
);
|
||||
}
|
||||
|
||||
function awsDelete(id, delete_token) {
|
||||
function awsDelete(id, ownerToken) {
|
||||
return new Promise((resolve, reject) => {
|
||||
redis_client.hget(id, 'delete', (err, reply) => {
|
||||
if (!reply || delete_token !== reply) {
|
||||
if (!reply || ownerToken !== reply) {
|
||||
reject();
|
||||
} else {
|
||||
const params = {
|
||||
|
||||
@@ -4,6 +4,12 @@ const CopyPlugin = require('copy-webpack-plugin');
|
||||
const ManifestPlugin = require('webpack-manifest-plugin');
|
||||
const IS_DEV = process.env.NODE_ENV === 'development';
|
||||
|
||||
const regularJSOptions = {
|
||||
babelrc: false,
|
||||
presets: [['env', { modules: false }], 'stage-2'],
|
||||
plugins: ['yo-yoify']
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
entry: {
|
||||
vendor: ['babel-polyfill', 'fluent'],
|
||||
@@ -31,6 +37,16 @@ module.exports = {
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
include: require.resolve('./app/templates/header'),
|
||||
use: [
|
||||
{
|
||||
loader: 'babel-loader',
|
||||
options: regularJSOptions
|
||||
},
|
||||
'./build/version_loader'
|
||||
]
|
||||
},
|
||||
{
|
||||
include: [path.dirname(require.resolve('fluent'))],
|
||||
use: [
|
||||
@@ -51,13 +67,11 @@ module.exports = {
|
||||
include: [
|
||||
path.resolve(__dirname, 'app'),
|
||||
path.resolve(__dirname, 'common'),
|
||||
path.resolve(__dirname, 'node_modules/testpilot-ga/src')
|
||||
path.resolve(__dirname, 'node_modules/testpilot-ga/src'),
|
||||
path.resolve(__dirname, 'node_modules/fluent-intl-polyfill'),
|
||||
path.resolve(__dirname, 'node_modules/intl-pluralrules')
|
||||
],
|
||||
options: {
|
||||
babelrc: false,
|
||||
presets: [['env', { modules: false }], 'stage-2'],
|
||||
plugins: ['yo-yoify']
|
||||
}
|
||||
options: regularJSOptions
|
||||
},
|
||||
{
|
||||
include: [path.resolve(__dirname, 'node_modules')],
|
||||
|
||||
Reference in New Issue
Block a user