Fix XSS bugs

Thanks to Neil Jomunsi (http://page42.org) to support me on Tipeee :-)
This commit is contained in:
Luc Didry 2016-07-18 14:19:30 +02:00 committed by Luc Didry
parent e7ca848c3c
commit d94c2b7f90
14 changed files with 209 additions and 105 deletions

View File

@ -61,6 +61,10 @@ Please consider contributing, either by [reporting issues](https://git.framasoft
The details on how to contribute are on the [wiki](https://git.framasoft.org/luc/lufi/wikis/contribute).
## Make a donation
You can make a donation to the author on [Tipeee](https://www.tipeee.com/fiat-tux) or on [Liberapay](https://liberapay.com/sky/).
## Other dependencies
Lufi is written in Perl with the [Mojolicious](http://mojolicio.us) framework.

View File

@ -314,9 +314,9 @@ sub startup {
})->name('delays');
# Get mail page
$r->get('/m' => sub {
shift->render(template => 'mail');
})->name('mail');
$r->get('/m')->
to('Mail#render_mail')->
name('mail');
# Submit mail
$r->post('/m')->

View File

@ -1,7 +1,7 @@
# vim:set sw=4 ts=4 sts=4 ft=perl expandtab:
package Lufi::Controller::Files;
use Mojo::Base 'Mojolicious::Controller';
use Mojo::JSON qw(encode_json decode_json true false);
use Mojo::JSON qw(encode_json decode_json to_json true false);
use Mojo::Util qw(slurp spurt encode decode);
use LufiDB;
use Lufi::File;
@ -36,19 +36,40 @@ sub upload {
# Check if stop_upload file is present
if ($c->stop_upload) {
$stop = 1;
$c->send(sprintf('{"success": false, "msg":"'.$c->l('Sorry, uploading is disabled.').'", "sent_delay": %d, "i": %d}', $json->{delay}, $json->{i}));
$c->send(encode_json(
{
success => false,
msg => $c->l('Sorry, uploading is disabled.'),
sent_delay => $json->{delay},
i => $json->{i}
}
));
}
# Check against max_size
elsif (defined $c->config('max_file_size')) {
if ($json->{size} > $c->config('max_file_size')) {
$stop = 1;
$c->send(sprintf('{"success": false, "msg":"'.$c->l('Your file is too big: %1 (maximum size allowed: %2)', format_bytes($json->{size}), format_bytes($c->config('max_file_size'))).'", "sent_delay": %d, "i": %d}', $json->{delay}, $json->{i}));
$c->send(encode_json(
{
success => false,
msg => $c->l('Your file is too big: %1 (maximum size allowed: %2)', format_bytes($json->{size}), format_bytes($c->config('max_file_size'))),
sent_delay => $json->{delay},
i => $json->{i}
}
));
}
}
# Check that we have enough space (multiplying by 2 since it's encrypted, it takes more place that the original file)
elsif ($json->{part} == 0 && ($json->{size} * 2) >= dfportable($c->config('upload_dir'))->{bavail}) {
$stop = 1;
$c->send(sprintf('{"success": false, "msg":"'.$c->l('No enough space available on the server for this file (size: %1).', format_bytes($json->{size})).'", "sent_delay": %d, "i": %d}', $json->{delay}, $json->{i}));
$c->send(encode_json(
{
success => false,
msg => $c->l('No enough space available on the server for this file (size: %1).', format_bytes($json->{size})),
sent_delay => $json->{delay},
i => $json->{i}
}
));
}
unless ($stop) {
@ -123,9 +144,32 @@ sub upload {
$c->provisioning;
$ws->send(sprintf('{"success": true, "i": %d, "j": %d, "parts": %d, "short": "%s", "name": "%s", "size": %d, "del_at_first_view": %s, "created_at": %d, "delay": %d, "token": "%s", "sent_delay": %d, "duration": %d}', $json->{i}, $json->{part}, $json->{total}, $f->short, $f->filename, $f->filesize, (($f->delete_at_first_view) ? 'true' : 'false'), $f->created_at, $f->delete_at_day, $f->mod_token, $json->{delay}, time - $begin));
$ws->send(to_json(
{
success => true,
i => $json->{i},
j => $json->{part},
parts => $json->{total},
short => $f->short,
name => $f->filename,
size => $f->filesize,
del_at_first_view => (($f->delete_at_first_view) ? true : false),
created_at => $f->created_at,
delay => $f->delete_at_day,
token => $f->mod_token,
sent_delay => $json->{delay},
duration => time - $begin
}
));
} else {
$ws->send(sprintf('{"success": false, "msg":"'.$c->l('The server was unable to find the file record to add your file part to. Please, contact the administrator.').'", "sent_delay": %d, "i": %d}', $json->{delay}, $json->{i}));
$ws->send(encode_json(
{
success => false,
msg => $c->l('The server was unable to find the file record to add your file part to. Please, contact the administrator.'),
sent_delay => $json->{delay},
i => $json->{i}
}
));
}
}
}
@ -166,7 +210,12 @@ sub download {
$c->on(
message => sub {
my ($ws, $json) = @_;
$c->send('{"success": false, "msg": "'.$c->l('Error: the file existed but was deleted.').'"}');
$c->send(encode_json(
{
success => false,
msg => $c->l('Error: the file existed but was deleted.')
}
));
}
);
} elsif ($record->complete) {
@ -211,12 +260,22 @@ sub download {
$c->on(
message => sub {
my ($ws, $json) = @_;
$c->send('{"success": false, "msg": "'.$c->l('Error: the file has not been sent entirely.').'"}');
$c->send(encode_json(
{
success => false,
msg => $c->l('Error: the file has not been sent entirely.')
}
));
}
);
}
} else {
$c->send('{"success": false, "msg": "'.$c->l('Error: unable to find the file. Are you sure of your URL?').'"}');
$c->send(encode_json(
{
success => false,
msg => $c->l('Error: unable to find the file. Are you sure of your URL?')
}
));
}
}

View File

@ -2,12 +2,22 @@
package Lufi::Controller::Mail;
use Mojo::Base 'Mojolicious::Controller';
use Email::Valid;
use Mojo::JSON qw(decode_json);
sub render_mail {
my $c = shift;
$c->render(
template => 'mail',
links => decode_json($c->param('links'))
);
}
sub send_mail {
my $c = shift;
my $validation = $c->validation;
return $c->render(text => 'Bad CSRF token!', status => 403) if $validation->csrf_protect->has_error('csrf_token');
return $c->render(text => $c->l('Bad CSRF token!'), status => 403) if $validation->csrf_protect->has_error('csrf_token');
my $emails = $c->param('emails');
@ -36,7 +46,7 @@ sub send_mail {
template => 'mail',
msg => $msg,
values => {
emails => $emails,
emails => $emails,
subject => $c->param('subject'),
body => $c->param('body')
}

View File

@ -29,7 +29,7 @@ msgstr ""
msgid "24 hours"
msgstr ""
#: themes/default/templates/mail.html.ep:79
#: themes/default/templates/mail.html.ep:83
msgid ":"
msgstr ""
@ -46,7 +46,7 @@ msgid "About"
msgstr ""
#: themes/default/templates/about.html.ep:18
msgid "As Lufi is a free software licensed under of the terms of the <a href=\"https://gnu.org/licenses/agpl.html\" class=\"classic\">AGPLv3</a>, you can install it on you own server. Have a look on the <a href=\"https://git.framasoft.org/luc/lufi/wikis/home\" class=\"classic\">Wiki</a> for the procedure."
msgid "As Lufi is a free software licensed under of the terms of the <a href=\"https://gnu.org/licenses/agpl.html\" class=\"classic\">AGPLv3</a>, you can install it on you own server. Have a look on the <a href=\"https://framagit.org/luc/lufi/wikis/home\" class=\"classic\">Wiki</a> for the procedure."
msgstr ""
#. (stash('f')
@ -58,6 +58,10 @@ msgstr ""
msgid "Back to homepage"
msgstr ""
#: lib/Lufi/Controller/Mail.pm:20
msgid "Bad CSRF token!"
msgstr ""
#: themes/default/templates/render.html.ep:40
msgid "Click here to refresh the page and restart the download."
msgstr ""
@ -82,15 +86,15 @@ msgstr ""
msgid "Copy to clipboard"
msgstr ""
#: lib/Lufi/Controller/Files.pm:328
#: lib/Lufi/Controller/Files.pm:396
msgid "Could not delete the file. You are not authenticated."
msgstr ""
#: lib/Lufi/Controller/Files.pm:312
#: lib/Lufi/Controller/Files.pm:380
msgid "Could not find the file. Are you sure of the URL and the token?"
msgstr ""
#: lib/Lufi/Controller/Files.pm:228
#: lib/Lufi/Controller/Files.pm:296
msgid "Could not find the file. Are you sure of the URL?"
msgstr ""
@ -146,15 +150,15 @@ msgstr ""
msgid "Encrypting part XX1 of XX2"
msgstr ""
#: lib/Lufi/Controller/Files.pm:164
#: lib/Lufi/Controller/Files.pm:216
msgid "Error: the file existed but was deleted."
msgstr ""
#: lib/Lufi/Controller/Files.pm:205
#: lib/Lufi/Controller/Files.pm:266
msgid "Error: the file has not been sent entirely."
msgstr ""
#: lib/Lufi/Controller/Files.pm:210
#: lib/Lufi/Controller/Files.pm:276
msgid "Error: unable to find the file. Are you sure of your URL?"
msgstr ""
@ -170,7 +174,7 @@ msgstr ""
msgid "Export localStorage data"
msgstr ""
#: lib/Lufi/Controller/Files.pm:296
#: lib/Lufi/Controller/Files.pm:364
msgid "File deleted"
msgstr ""
@ -183,14 +187,14 @@ msgid "Get the file"
msgstr ""
#: themes/default/templates/about.html.ep:19
msgid "Get the source code on <a href=\"https://git.framasoft.org/luc/lufi\" class=\"classic\">the official repository</a> or on its <a href=\"https://github.com/ldidry/lufi\" class=\"classic\">Github mirror</a>"
msgid "Get the source code on <a href=\"https://framagit.org/luc/lufi\" class=\"classic\">the official repository</a> or on its <a href=\"https://github.com/ldidry/lufi\" class=\"classic\">Github mirror</a>"
msgstr ""
#: themes/default/templates/mail.html.ep:74
#: themes/default/templates/mail.html.ep:78
msgid "Hello,\\n\\nHere's some files I want to share with you:\\n"
msgstr ""
#: themes/default/templates/mail.html.ep:32 themes/default/templates/mail.html.ep:34
#: themes/default/templates/mail.html.ep:34
msgid "Here's some files"
msgstr ""
@ -259,7 +263,7 @@ msgid "My files"
msgstr ""
#. (format_bytes($json->{size})
#: lib/Lufi/Controller/Files.pm:50
#: lib/Lufi/Controller/Files.pm:68
msgid "No enough space available on the server for this file (size: %1)."
msgstr ""
@ -313,7 +317,7 @@ msgid "Sending part XX1 of XX2. Please, be patient, the progress bar can take a
msgstr ""
#. (url_for('/')
#: themes/default/templates/mail.html.ep:87
#: themes/default/templates/mail.html.ep:91
msgid "Share your files in total privacy on %1"
msgstr ""
@ -325,7 +329,7 @@ msgstr ""
msgid "Sorry, the uploading is currently disabled. Please try again later."
msgstr ""
#: lib/Lufi/Controller/Files.pm:38
#: lib/Lufi/Controller/Files.pm:42
msgid "Sorry, uploading is disabled."
msgstr ""
@ -337,15 +341,15 @@ msgstr ""
msgid "The data has been successfully imported."
msgstr ""
#: lib/Lufi/Controller/Mail.pm:32
#: lib/Lufi/Controller/Mail.pm:42
msgid "The email body can't be empty."
msgstr ""
#: lib/Lufi/Controller/Mail.pm:31
#: lib/Lufi/Controller/Mail.pm:41
msgid "The email subject can't be empty."
msgstr ""
#: lib/Lufi/Controller/Files.pm:293
#: lib/Lufi/Controller/Files.pm:361
msgid "The file has already been deleted"
msgstr ""
@ -354,7 +358,7 @@ msgid "The files uploaded on a Lufi instance are encrypted before the upload to
msgstr ""
#. (join(', ', @bad)
#: lib/Lufi/Controller/Mail.pm:27
#: lib/Lufi/Controller/Mail.pm:37
msgid "The following email addresses are not valid: %1"
msgstr ""
@ -362,16 +366,15 @@ msgstr ""
msgid "The link(s) has been copied to your clipboard"
msgstr ""
#: lib/Lufi/Controller/Mail.pm:55
#: lib/Lufi/Controller/Mail.pm:65
msgid "The mail has been sent."
msgstr ""
#. (url_for('/')
#: themes/default/templates/about.html.ep:15
msgid "The original (and only for now) author is <a href=\"https://fiat-tux.fr\" class=\"classic\">Luc Didry</a>. If you want to support him, you can do it via <a href=\"https://flattr.com/submit/auto?user_id=_SKy_&amp;url=%1&amp;title=Lufi&amp;category=software\" class=\"classic\">Flattr</a> or with <a href=\"bitcoin:1CJYU2uGmPKhvithCGntyniTTe2hofpPX3?label=Lufi\" class=\"classic\">Bitcoin</a>."
msgid "The original (and only for now) author is <a href=\"https://fiat-tux.fr\" class=\"classic\">Luc Didry</a>. If you want to support him, you can do it via <a href=\"https://www.tipeee.com/fiat-tux\" class=\"classic\">Tipeee</a> or via <a href=\"https://liberapay.com/sky/\" class=\"classic\">Liberapay</a>."
msgstr ""
#: lib/Lufi/Controller/Files.pm:123
#: lib/Lufi/Controller/Files.pm:168
msgid "The server was unable to find the file record to add your file part to. Please, contact the administrator."
msgstr ""
@ -384,17 +387,17 @@ msgid "Unable to copy the link(s) to your clipboard"
msgstr ""
#. ($short)
#: lib/Lufi/Controller/Files.pm:266
#: lib/Lufi/Controller/Files.pm:334
msgid "Unable to get counter for %1. The file does not exists. It will be removed from your localStorage."
msgstr ""
#. ($short)
#: lib/Lufi/Controller/Files.pm:256
#: lib/Lufi/Controller/Files.pm:324
msgid "Unable to get counter for %1. The token is invalid."
msgstr ""
#. ($short)
#: lib/Lufi/Controller/Files.pm:276
#: lib/Lufi/Controller/Files.pm:344
msgid "Unable to get counter for %1. You are not authenticated."
msgstr ""
@ -446,12 +449,12 @@ msgstr ""
msgid "You have been successfully logged out."
msgstr ""
#: lib/Lufi/Controller/Mail.pm:30
#: lib/Lufi/Controller/Mail.pm:40
msgid "You must give email addresses."
msgstr ""
#. (format_bytes($json->{size})
#: lib/Lufi/Controller/Files.pm:44
#: lib/Lufi/Controller/Files.pm:55
msgid "Your file is too big: %1 (maximum size allowed: %2)"
msgstr ""
@ -465,7 +468,7 @@ msgstr ""
msgid "between %1 and %2, the file will be kept forever."
msgstr ""
#: themes/default/templates/mail.html.ep:81
#: themes/default/templates/mail.html.ep:85
msgid "deadline: "
msgstr ""

View File

@ -31,7 +31,7 @@ msgstr "1 an"
msgid "24 hours"
msgstr "24 heures"
#: themes/default/templates/mail.html.ep:79
#: themes/default/templates/mail.html.ep:83
msgid ":"
msgstr " :"
@ -48,8 +48,8 @@ msgid "About"
msgstr "À propos"
#: themes/default/templates/about.html.ep:18
msgid "As Lufi is a free software licensed under of the terms of the <a href=\"https://gnu.org/licenses/agpl.html\" class=\"classic\">AGPLv3</a>, you can install it on you own server. Have a look on the <a href=\"https://git.framasoft.org/luc/lufi/wikis/home\" class=\"classic\">Wiki</a> for the procedure."
msgstr "Comme Lufi est un logiciel libre soumis aux termes de la license <a href=\"https://gnu.org/licenses/agpl.html\" class=\"classic\">AGPLv3</a>, vous pouvez linstaller sur votre propre serveur. Veuillez consulter le <a href=\"https://git.framasoft.org/luc/lufi/wikis/home\" class=\"classic\">Wiki</a> pour voir la procédure."
msgid "As Lufi is a free software licensed under of the terms of the <a href=\"https://gnu.org/licenses/agpl.html\" class=\"classic\">AGPLv3</a>, you can install it on you own server. Have a look on the <a href=\"https://framagit.org/luc/lufi/wikis/home\" class=\"classic\">Wiki</a> for the procedure."
msgstr "Comme Lufi est un logiciel libre soumis aux termes de la license <a href=\"https://gnu.org/licenses/agpl.html\" class=\"classic\">AGPLv3</a>, vous pouvez linstaller sur votre propre serveur. Veuillez consulter le <a href=\"https://framagit.org/luc/lufi/wikis/home\" class=\"classic\">Wiki</a> pour voir la procédure."
#. (stash('f')
#: themes/default/templates/render.html.ep:44
@ -60,6 +60,10 @@ msgstr "Demande de récupération du fragment de fichier XX1 sur %1"
msgid "Back to homepage"
msgstr "Retour à la page daccueil"
#: lib/Lufi/Controller/Mail.pm:20
msgid "Bad CSRF token!"
msgstr "Mauvais jeton CSRF !"
#: themes/default/templates/render.html.ep:40
msgid "Click here to refresh the page and restart the download."
msgstr "Cliquez ici pour rafraîchir la page et redémarrer le téléchargement."
@ -84,15 +88,15 @@ msgstr "Copier tous les liens dans le presse-papier"
msgid "Copy to clipboard"
msgstr "Copier dans le presse-papier"
#: lib/Lufi/Controller/Files.pm:328
#: lib/Lufi/Controller/Files.pm:396
msgid "Could not delete the file. You are not authenticated."
msgstr "Impossible de supprimer le fichier. Vous n'êtes pas connecté·e."
msgstr "Impossible de supprimer le fichier. Vous nêtes pas connecté·e."
#: lib/Lufi/Controller/Files.pm:312
#: lib/Lufi/Controller/Files.pm:380
msgid "Could not find the file. Are you sure of the URL and the token?"
msgstr "Impossible de retrouver le fichier. Êtes-vous sûr(e) que lURL et le jeton sont les bons ?"
#: lib/Lufi/Controller/Files.pm:228
#: lib/Lufi/Controller/Files.pm:296
msgid "Could not find the file. Are you sure of the URL?"
msgstr "Impossible de retrouver le fichier. Êtes-vous sûr(e) que lURL est la bonne ?"
@ -126,7 +130,7 @@ msgstr "Lien de téléchargement"
#: themes/default/templates/about.html.ep:10
msgid "Drag and drop files in the appropriate area or use the traditional way to send files and the files will be chunked, encrypted and sent to the server. You will get two links per file: a download link, that you give to the people you want to share the file with and a deletion link, allowing you to delete the file whenever you want."
msgstr "Faites glisser des fichiers dans la zone prévue à cet effet ou sélectionnez un fichier de façon classique et les fichiers seront découpés en morceaux, chiffrés et envoyés au serveur. Vous récupérerez deux liens par fichier : un lien de téléchargement et un lien pour supprimer le fichier quand vous le souhaitez."
msgstr "Faites glisser des fichiers dans la zone prévue à cet effet ou sélectionnez un fichier de façon classique et les fichiers seront découpés en morceaux, chiffrés et envoyés au serveur. Vous récupérerez deux liens par fichier : un lien de téléchargement et un lien pour supprimer le fichier quand vous le souhaitez."
#: themes/default/templates/index.html.ep:69
msgid "Drop files here"
@ -148,15 +152,15 @@ msgstr "Mails"
msgid "Encrypting part XX1 of XX2"
msgstr "Chiffrement du fragment XX1 sur XX2"
#: lib/Lufi/Controller/Files.pm:164
#: lib/Lufi/Controller/Files.pm:216
msgid "Error: the file existed but was deleted."
msgstr "Erreur : le fichier existait mais a été supprimé"
#: lib/Lufi/Controller/Files.pm:205
#: lib/Lufi/Controller/Files.pm:266
msgid "Error: the file has not been sent entirely."
msgstr "Erreur : le fichier na pas été envoyé dans son intégralité"
#: lib/Lufi/Controller/Files.pm:210
#: lib/Lufi/Controller/Files.pm:276
msgid "Error: unable to find the file. Are you sure of your URL?"
msgstr "Erreur : impossible de retrouver le fichier. Êtes-vous sûr(e) de lURL ?"
@ -172,7 +176,7 @@ msgstr "Expire le"
msgid "Export localStorage data"
msgstr "Exporter les données localStorage"
#: lib/Lufi/Controller/Files.pm:296
#: lib/Lufi/Controller/Files.pm:364
msgid "File deleted"
msgstr "Fichier supprimé"
@ -182,17 +186,17 @@ msgstr "Nom du fichier"
#: themes/default/templates/render.html.ep:43
msgid "Get the file"
msgstr "Récupérez le fichier"
msgstr "Récupérer le fichier"
#: themes/default/templates/about.html.ep:19
msgid "Get the source code on <a href=\"https://git.framasoft.org/luc/lufi\" class=\"classic\">the official repository</a> or on its <a href=\"https://github.com/ldidry/lufi\" class=\"classic\">Github mirror</a>"
msgstr "Récupérez le code source sur <a href=\"https://git.framasoft.org/luc/lufi\" class=\"classic\">le dépôt officiel</a> ou sur son <a href=\"https://github.com/ldidry/lufi\" class=\"classic\">miroir Github</a>."
msgid "Get the source code on <a href=\"https://framagit.org/luc/lufi\" class=\"classic\">the official repository</a> or on its <a href=\"https://github.com/ldidry/lufi\" class=\"classic\">Github mirror</a>"
msgstr "Récupérez le code source sur <a href=\"https://framagit.org/luc/lufi\" class=\"classic\">le dépôt officiel</a> ou sur son <a href=\"https://github.com/ldidry/lufi\" class=\"classic\">miroir Github</a>."
#: themes/default/templates/mail.html.ep:74
#: themes/default/templates/mail.html.ep:78
msgid "Hello,\\n\\nHere's some files I want to share with you:\\n"
msgstr "Bonjour,\\n\\nVoici quelques fichiers que je souhaite partager avec toi :\\n"
#: themes/default/templates/mail.html.ep:32 themes/default/templates/mail.html.ep:34
#: themes/default/templates/mail.html.ep:34
msgid "Here's some files"
msgstr "Voici quelques fichiers"
@ -261,9 +265,9 @@ msgid "My files"
msgstr "Mes fichiers"
#. (format_bytes($json->{size})
#: lib/Lufi/Controller/Files.pm:50
#: lib/Lufi/Controller/Files.pm:68
msgid "No enough space available on the server for this file (size: %1)."
msgstr "Espace disque insuffisant sur le serveur pour ce fichier (taille du fichier: %1)."
msgstr "Espace disque insuffisant sur le serveur pour ce fichier (taille du fichier : %1)."
#: themes/default/templates/files.html.ep:42 themes/default/templates/index.html.ep:104
msgid "No expiration delay"
@ -280,11 +284,11 @@ msgstr "Mot de passe"
#. (config('contact')
#: themes/default/templates/about.html.ep:13
msgid "Please contact the administrator: %1"
msgstr "Veuillez contacter ladministrateur : %1"
msgstr "Veuillez contacter ladministrateur : %1"
#: themes/default/templates/render.html.ep:25
msgid "Please wait while we are getting your file. We first need to download and decrypt all parts before you can get it."
msgstr "Veuillez patientez pendant que la récupération de votre fichier. Nous devons d'abord récupérer et déchiffrer tous les fragments avant que vous puissiez le télécharger."
msgstr "Veuillez patientez pendant la récupération de votre fichier. Nous devons dabord récupérer et déchiffrer tous les fragments avant que vous puissiez le télécharger."
#: themes/default/templates/about.html.ep:5
msgid "Privacy"
@ -312,10 +316,10 @@ msgstr "Envoyer avec votre propre logiciel de mail"
#: themes/default/templates/index.html.ep:105
msgid "Sending part XX1 of XX2. Please, be patient, the progress bar can take a while to move."
msgstr "Envoi du fragment XX1 sur XX2. Veuillez patienter, la barre de progression peut mettre du temps avant d'avancer."
msgstr "Envoi du fragment XX1 sur XX2. Veuillez patienter, la barre de progression peut mettre du temps avant davancer."
#. (url_for('/')
#: themes/default/templates/mail.html.ep:87
#: themes/default/templates/mail.html.ep:91
msgid "Share your files in total privacy on %1"
msgstr "Partagez vos fichiers en toute confidentialité sur %1"
@ -327,36 +331,36 @@ msgstr "Connexion"
msgid "Sorry, the uploading is currently disabled. Please try again later."
msgstr "Désolé, lenvoi de fichier est actuellement désactivé. Veuillez réessayer plus tard."
#: lib/Lufi/Controller/Files.pm:38
#: lib/Lufi/Controller/Files.pm:42
msgid "Sorry, uploading is disabled."
msgstr "Désolé, lenvoi de fichier est désactivé."
#: themes/default/templates/about.html.ep:7
msgid "The administrator can only see the file's name, its size and its mimetype (what kind of file it is: video, text, etc)."
msgstr "Ladministrateur ne peut voir que le nom du fichier, sa taille et son type mime (son type de fichier : vidéo, text, etc)."
msgstr "Ladministrateur ne peut voir que le nom du fichier, sa taille et son type mime (son type de fichier : vidéo, texte, etc)."
#: themes/default/templates/files.html.ep:43
msgid "The data has been successfully imported."
msgstr "Les données ont été importées avec succès."
#: lib/Lufi/Controller/Mail.pm:32
#: lib/Lufi/Controller/Mail.pm:42
msgid "The email body can't be empty."
msgstr "Le corps du mail ne peut être vide."
#: lib/Lufi/Controller/Mail.pm:31
#: lib/Lufi/Controller/Mail.pm:41
msgid "The email subject can't be empty."
msgstr "Le sujet du mail ne peut être vide."
#: lib/Lufi/Controller/Files.pm:293
#: lib/Lufi/Controller/Files.pm:361
msgid "The file has already been deleted"
msgstr "Le fichier a déjà été supprimé"
#: themes/default/templates/about.html.ep:6
msgid "The files uploaded on a Lufi instance are encrypted before the upload to the server: the administrator of the server can not see the file's content."
msgstr "Les fichiers envoyés sur une instance de Lufi sont chiffrés avant lenvoi au serveur : ladministrateur du serveur ne peut pas voir le contenu de vos fichiers."
msgstr "Les fichiers envoyés sur une instance de Lufi sont chiffrés avant lenvoi au serveur : ladministrateur du serveur ne peut pas voir le contenu de vos fichiers."
#. (join(', ', @bad)
#: lib/Lufi/Controller/Mail.pm:27
#: lib/Lufi/Controller/Mail.pm:37
msgid "The following email addresses are not valid: %1"
msgstr "Les adresses mail suivantes ne sont pas valides : %1"
@ -364,18 +368,17 @@ msgstr "Les adresses mail suivantes ne sont pas valides : %1"
msgid "The link(s) has been copied to your clipboard"
msgstr "Le(s) lien(s) a/ont été copié dans votre presse-papier"
#: lib/Lufi/Controller/Mail.pm:55
#: lib/Lufi/Controller/Mail.pm:65
msgid "The mail has been sent."
msgstr "Le mail a été envoyé."
#. (url_for('/')
#: themes/default/templates/about.html.ep:15
msgid "The original (and only for now) author is <a href=\"https://fiat-tux.fr\" class=\"classic\">Luc Didry</a>. If you want to support him, you can do it via <a href=\"https://flattr.com/submit/auto?user_id=_SKy_&amp;url=%1&amp;title=Lufi&amp;category=software\" class=\"classic\">Flattr</a> or with <a href=\"bitcoin:1CJYU2uGmPKhvithCGntyniTTe2hofpPX3?label=Lufi\" class=\"classic\">Bitcoin</a>."
msgstr "Lauteur originel (et pour linstant, le seul) est <a href=\"https://fiat-tux.fr\" class=\"classic\">Luc Didry</a>. Si vous avez envie de le supporter, vous pouvez le faire via <a href=\"https://flattr.com/submit/auto?user_id=_SKy_&amp;url=%1&amp;title=Lufi&amp;category=software\" class=\"classic\">Flattr</a> ou en <a href=\"bitcoin:1CJYU2uGmPKhvithCGntyniTTe2hofpPX3?label=Lufi\" class=\"classic\">Bitcoin</a>."
msgid "The original (and only for now) author is <a href=\"https://fiat-tux.fr\" class=\"classic\">Luc Didry</a>. If you want to support him, you can do it via <a href=\"https://www.tipeee.com/fiat-tux\" class=\"classic\">Tipeee</a> or via <a href=\"https://liberapay.com/sky/\" class=\"classic\">Liberapay</a>."
msgstr "Lauteur originel (et pour linstant, le seul) est <a href=\"https://fiat-tux.fr\" class=\"classic\">Luc Didry</a>. Si vous avez envie de le supporter, vous pouvez le faire via <a href=\"https://www.tipeee.com/fiat-tux\" class=\"classic\">Tipeee</a> ou via <a href=\"https://liberapay.com/sky/\" class=\"classic\">Liberapay</a>."
#: lib/Lufi/Controller/Files.pm:123
#: lib/Lufi/Controller/Files.pm:168
msgid "The server was unable to find the file record to add your file part to. Please, contact the administrator."
msgstr "Le serveur a été incapable de retrouver lenregistrement du fichier auquel ajouter votre fragment de fichier. Veuillez contacter l'administrateur."
msgstr "Le serveur a été incapable de retrouver lenregistrement du fichier auquel ajouter votre fragment de fichier. Veuillez contacter ladministrateur."
#: themes/default/templates/delays.html.ep:10
msgid "This server sets limitations according to the file size. The expiration delay of your file will be the minimum between what you choose and the following limitations:"
@ -386,19 +389,19 @@ msgid "Unable to copy the link(s) to your clipboard"
msgstr "Impossible de copier le(s) lien(s) dans votre presse-papier"
#. ($short)
#: lib/Lufi/Controller/Files.pm:266
#: lib/Lufi/Controller/Files.pm:334
msgid "Unable to get counter for %1. The file does not exists. It will be removed from your localStorage."
msgstr "Impossible de récupérer le compteur pour %1. Le fichier nexiste pas. Il va être supprimé de votre localStorage."
#. ($short)
#: lib/Lufi/Controller/Files.pm:256
#: lib/Lufi/Controller/Files.pm:324
msgid "Unable to get counter for %1. The token is invalid."
msgstr "Impossible de récupérer le compteur pour %1. Le jeton est invalide."
#. ($short)
#: lib/Lufi/Controller/Files.pm:276
#: lib/Lufi/Controller/Files.pm:344
msgid "Unable to get counter for %1. You are not authenticated."
msgstr "Impossible de récupérer le compteur pour %1. Vous n'êtes pas connecté·e."
msgstr "Impossible de récupérer le compteur pour %1. Vous nêtes pas connecté·e."
#: themes/default/templates/layouts/default.html.ep:35 themes/default/templates/layouts/default.html.ep:47
msgid "Upload files"
@ -448,12 +451,12 @@ msgstr "Vous essayez de quitter la page. Lenvoi sera annulé. Êtes-vous sûr
msgid "You have been successfully logged out."
msgstr "Vous avez été déconnecté·e avec succès."
#: lib/Lufi/Controller/Mail.pm:30
#: lib/Lufi/Controller/Mail.pm:40
msgid "You must give email addresses."
msgstr "Vous devez envoyer des adresses mail."
#. (format_bytes($json->{size})
#: lib/Lufi/Controller/Files.pm:44
#: lib/Lufi/Controller/Files.pm:55
msgid "Your file is too big: %1 (maximum size allowed: %2)"
msgstr "Votre fichier est trop volumineux : %1 (la taille maximum autorisée est %2)"
@ -467,7 +470,7 @@ msgstr "entre %1 et %2, le fichier sera conservé %3 jour(s) ;"
msgid "between %1 and %2, the file will be kept forever."
msgstr "entre %1 et %2, le fichier sera conservé indéfiniment ;"
#: themes/default/templates/mail.html.ep:81
#: themes/default/templates/mail.html.ep:85
msgid "deadline: "
msgstr "dernier délai pour télécharger : "

View File

@ -83,3 +83,6 @@ a.classic:focus {
boxShadow: 'none';
background: 'transparent';
}
.hiddendiv.common {
min-height: 170px;
}

View File

@ -0,0 +1,16 @@
// vim:set sw=4 ts=4 sts=4 ft=javascript expandtab:
// Escape HTML chars
var entityMap = {
"&": "&amp;",
"<": "&lt;",
">": "&gt;",
'"': '&quot;',
"'": '&#39;',
"/": '&#x2F;'
};
function escapeHtml(string) {
return String(string).replace(/[&<>"'\/]/g, function (s) {
return entityMap[s];
});
}

View File

@ -91,10 +91,10 @@ function spawnWebsocket(pa) {
var pbd = $('#pbd');
pbd.attr('class', 'center-align');
var blobURL = URL.createObjectURL(blob);
var innerHTML = [ '<p><a href="', blobURL, '" class="btn btn-primary" download="', data.name, '">', i18n.download, '</a></p>'];
var innerHTML = ['<p><a href="', blobURL, '" class="btn btn-primary" download="', escapeHtml(data.name), '">', i18n.download, '</a></p>'];
if (data.type.match(/^image\//) !== null) {
innerHTML.push('<img id="render-image" class="responsive-img" alt="', data.name, '" src="', blobURL, '">');
innerHTML.push('<img id="render-image" class="responsive-img" alt="', escapeHtml(data.name), '" src="', blobURL, '">');
} else if (data.type.match(/^video\//) !== null) {
innerHTML.push('<video class="responsive-video" controls>',
'<source src="', blobURL, '" type="', data.type, '">',

View File

@ -1,3 +1,4 @@
// vim:set sw=4 ts=4 sts=4 ft=javascript expandtab:
// Add item to localStorage
function addItem(item) {
var files = localStorage.getItem('files');
@ -126,7 +127,7 @@ function populateFilesTable() {
var tr = $('<tr>');
tr.html([ '<td class="left-align">',
element.name,
escapeHtml(element.name),
'</td>',
'<td class="center-align">',
'<a href="', element.url, '" class="classic"><i class="small mdi-file-file-download"></i></a>',

View File

@ -3,7 +3,7 @@
window.fc = 0;
// Set websocket
window.ws = spawnWebsocket(0, function() {return null;});
// Use slice of 10MB
// Use slice of 2MB
window.sliceLength = 2000000;
// Copy a link to clipboard
@ -117,7 +117,7 @@ function handleFiles(f) {
del_at_first_view.attr('disabled', 'disabled');
if (go) {
uploadFile(0, delay.val(), del_at_first_view.attr('data-checked'));
uploadFile(0, delay.val(), del_at_first_view.is(':checked'));
}
}
@ -136,7 +136,7 @@ function uploadFile(i, delay, del_at_first_view) {
// Get the file and properties
var file = window.fileList[i];
var name = file.name;
var name = escapeHtml(file.name);
var parts = Math.ceil(file.size/window.sliceLength);
if (parts === 0) {
parts = 1;
@ -152,12 +152,12 @@ function uploadFile(i, delay, del_at_first_view) {
'<i class="right mdi-navigation-close small"></i>',
'</a>',
'<div class="card-content">',
'<span class="card-title" id="name-', window.fc, '">', file.name, '</span>',
'<span class="card-title" id="name-', window.fc, '">', name, '</span>',
'<p id="parts-', window.fc, '"></p>',
'</div>',
'<div class="progress">',
'<div id="progress-', window.fc, '" style="width: 0%;" data-key="', randomkey, '" data-name="', file.name, '" aria-valuemax="100" aria-valuemin="0" aria-valuenow="0" role="progressbar" class="determinate">',
'<span class="sr-only">', file.name, '0%</span>',
'<div id="progress-', window.fc, '" style="width: 0%;" data-key="', randomkey, '" data-name="', name, '" aria-valuemax="100" aria-valuemin="0" aria-valuenow="0" role="progressbar" class="determinate">',
'<span class="sr-only">', name, '0%</span>',
'</div>',
'</div>',
'<div>'].join(''));
@ -268,7 +268,7 @@ function updateProgressBar(data) {
'<a href="', url, '" target="_blank">',
'<i class="mdi-file-file-download small" title="', i18n.dlText, '"></i>',
'</a>',
'<a href="#" onclick="copyToClipboard(\''+url+'\');" title="', i18n.cpText, '">',
'<a href="#" onclick="copyToClipboard(\'', url, '\');" title="', i18n.cpText, '">',
'<i class="mdi-content-content-copy small"></i>',
'</a>',
'</span>',

View File

@ -12,11 +12,11 @@
<h3><%= l('How to report an illegal file?') %></h3>
<p><%= l('Please contact the administrator: %1', config('contact')) %></p>
<h3><%= l('Who wrote this software?') %></h3>
<p><%== l('The original (and only for now) author is <a href="https://fiat-tux.fr" class="classic">Luc Didry</a>. If you want to support him, you can do it via <a href="https://flattr.com/submit/auto?user_id=_SKy_&amp;url=%1&amp;title=Lufi&amp;category=software" class="classic">Flattr</a> or with <a href="bitcoin:1CJYU2uGmPKhvithCGntyniTTe2hofpPX3?label=Lufi" class="classic">Bitcoin</a>.', url_for('/')->to_abs()) %><br>
<p><%== l('The original (and only for now) author is <a href="https://fiat-tux.fr" class="classic">Luc Didry</a>. If you want to support him, you can do it via <a href="https://www.tipeee.com/fiat-tux" class="classic">Tipeee</a> or via <a href="https://liberapay.com/sky/" class="classic">Liberapay</a>.') %><br>
<%== l('A thank you with a photo of kitten on <a href="https://framasphere.org/people/b13eb6b0beac0131e7e32a0000053625" class="classic">Diaspora*</a> or <a href="https://twitter.com/framasky" class="classic">Twitter</a> is cool too ;-)') %></p>
<h3><%= l('How to install the software on my server?') %></h3>
<p><%== l('As Lufi is a free software licensed under of the terms of the <a href="https://gnu.org/licenses/agpl.html" class="classic">AGPLv3</a>, you can install it on you own server. Have a look on the <a href="https://git.framasoft.org/luc/lufi/wikis/home" class="classic">Wiki</a> for the procedure.') %><br>
<%== l('Get the source code on <a href="https://git.framasoft.org/luc/lufi" class="classic">the official repository</a> or on its <a href="https://github.com/ldidry/lufi" class="classic">Github mirror</a>') %>
<p><%== l('As Lufi is a free software licensed under of the terms of the <a href="https://gnu.org/licenses/agpl.html" class="classic">AGPLv3</a>, you can install it on you own server. Have a look on the <a href="https://framagit.org/luc/lufi/wikis/home" class="classic">Wiki</a> for the procedure.') %><br>
<%== l('Get the source code on <a href="https://framagit.org/luc/lufi" class="classic">the official repository</a> or on its <a href="https://github.com/ldidry/lufi" class="classic">Github mirror</a>') %>
</p>
<%= link_to url_for('/') => ( class => "btn waves-effect waves-light cyan" ) => begin %><%= l('Back to homepage') %><% end%>
</div>

View File

@ -58,6 +58,7 @@
</nav>
<div class="container">
%= javascript '/js/jquery-2.1.1.min.js'
%= javascript '/js/lufi-common.js'
<%= content %>
</div>
% if (defined(config('piwik_img'))) {

View File

@ -21,7 +21,7 @@
<div class="input-field">
<label for="emails"><%= l('Comma-separated email addresses') %></label>
% if (defined(stash('values'))) {
<input type="text" class="validate" id="emails" name="emails" placeholder="<%= l('Emails') %>" value="<%== stash('values')->{emails} %>">
<input type="text" class="validate" id="emails" name="emails" placeholder="<%= l('Emails') %>" value="<%= stash('values')->{emails} %>">
% } else {
<input type="text" class="validate" id="emails" name="emails" placeholder="<%= l('Emails') %>">
% }
@ -29,7 +29,7 @@
<div class="input-field">
<label for="subject"><%= l('Email subject') %></label>
% if (defined(stash('values'))) {
<input type="text" class="validate" id="subject" name="subject" value="<%= l('Here\'s some files') %>" value="<%== stash('values')->{subject} %>">
<input type="text" class="validate" id="subject" name="subject" value="<%= stash('values')->{subject} %>">
% } else {
<input type="text" class="validate" id="subject" name="subject" value="<%= l('Here\'s some files') %>">
% }
@ -38,7 +38,7 @@
<label for="body"><%= l('Email body') %></label>
<textarea class="materialize-textarea" id="body" name="body" rows="10">
% if (defined(stash('values'))) {
<%== stash('values')->{body} %>
<%= stash('values')->{body} %>
% }
</textarea>
</div>
@ -70,11 +70,15 @@
btn.href = 'mailto:'+encodeURIComponent(emails.value)+'?subject='+encodeURIComponent(subject.value)+'&body='+encodeURIComponent(body.value);
}
function populateBody() {
var links = JSON.parse('<%== $self->param('links') %>');
var text = "<%== l('Hello,\n\nHere\'s some files I want to share with you:\n') %>";
var links = [
% for my $link (@{$links}) {
'<%= $link %>',
% }
];
var text = "<%= l('Hello,\n\nHere\'s some files I want to share with you:\n') %>";
links.forEach(function(name, index, array) {
var item = findItem(name);
if (item !== null) {
if (item !== null && item !== undefined) {
var limit = (item.delay === 0) ? null : moment.unix(item.delay * 86400 + item.created_at).locale(window.navigator.language).format('LLLL');
text = text+'- '+item.name+'<%= l(':') %> '+item.url;
if (limit !== null) {