From d94c2b7f90beb8dde84dffc1dc3f4f20ae9ea13f Mon Sep 17 00:00:00 2001 From: Luc Didry Date: Mon, 18 Jul 2016 14:19:30 +0200 Subject: [PATCH] Fix XSS bugs Thanks to Neil Jomunsi (http://page42.org) to support me on Tipeee :-) --- README.md | 4 + lib/Lufi.pm | 6 +- lib/Lufi/Controller/Files.pm | 77 ++++++++++++++-- lib/Lufi/Controller/Mail.pm | 14 ++- themes/default/lib/Lufi/I18N/en.po | 61 +++++++------ themes/default/lib/Lufi/I18N/fr.po | 89 ++++++++++--------- themes/default/public/css/lufi.css | 3 + themes/default/public/js/lufi-common.js | 16 ++++ themes/default/public/js/lufi-down.js | 4 +- themes/default/public/js/lufi-files.js | 3 +- themes/default/public/js/lufi-up.js | 14 +-- themes/default/templates/about.html.ep | 6 +- .../default/templates/layouts/default.html.ep | 1 + themes/default/templates/mail.html.ep | 16 ++-- 14 files changed, 209 insertions(+), 105 deletions(-) create mode 100644 themes/default/public/js/lufi-common.js diff --git a/README.md b/README.md index 084e5a9..4433e65 100644 --- a/README.md +++ b/README.md @@ -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. diff --git a/lib/Lufi.pm b/lib/Lufi.pm index a36d0dc..a27b00f 100644 --- a/lib/Lufi.pm +++ b/lib/Lufi.pm @@ -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')-> diff --git a/lib/Lufi/Controller/Files.pm b/lib/Lufi/Controller/Files.pm index 65ae95a..077bb52 100644 --- a/lib/Lufi/Controller/Files.pm +++ b/lib/Lufi/Controller/Files.pm @@ -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?') + } + )); } } diff --git a/lib/Lufi/Controller/Mail.pm b/lib/Lufi/Controller/Mail.pm index 5c7a11c..b004919 100644 --- a/lib/Lufi/Controller/Mail.pm +++ b/lib/Lufi/Controller/Mail.pm @@ -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') } diff --git a/themes/default/lib/Lufi/I18N/en.po b/themes/default/lib/Lufi/I18N/en.po index d8f7d79..9d6f9f5 100644 --- a/themes/default/lib/Lufi/I18N/en.po +++ b/themes/default/lib/Lufi/I18N/en.po @@ -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 AGPLv3, you can install it on you own server. Have a look on the Wiki for the procedure." +msgid "As Lufi is a free software licensed under of the terms of the AGPLv3, you can install it on you own server. Have a look on the Wiki 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 the official repository or on its Github mirror" +msgid "Get the source code on the official repository or on its Github mirror" 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 Luc Didry. If you want to support him, you can do it via Flattr or with Bitcoin." +msgid "The original (and only for now) author is Luc Didry. If you want to support him, you can do it via Tipeee or via Liberapay." 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 "" diff --git a/themes/default/lib/Lufi/I18N/fr.po b/themes/default/lib/Lufi/I18N/fr.po index fbc3e90..4ac13c0 100644 --- a/themes/default/lib/Lufi/I18N/fr.po +++ b/themes/default/lib/Lufi/I18N/fr.po @@ -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 AGPLv3, you can install it on you own server. Have a look on the Wiki for the procedure." -msgstr "Comme Lufi est un logiciel libre soumis aux termes de la license AGPLv3, vous pouvez l’installer sur votre propre serveur. Veuillez consulter le Wiki pour voir la procédure." +msgid "As Lufi is a free software licensed under of the terms of the AGPLv3, you can install it on you own server. Have a look on the Wiki for the procedure." +msgstr "Comme Lufi est un logiciel libre soumis aux termes de la license AGPLv3, vous pouvez l’installer sur votre propre serveur. Veuillez consulter le Wiki 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 d’accueil" +#: 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 l’URL 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 l’URL 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 n’a 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 l’URL ?" @@ -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 the official repository or on its Github mirror" -msgstr "Récupérez le code source sur le dépôt officiel ou sur son miroir Github." +msgid "Get the source code on the official repository or on its Github mirror" +msgstr "Récupérez le code source sur le dépôt officiel ou sur son miroir Github." -#: 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 l’administrateur : %1" +msgstr "Veuillez contacter l’administrateur : %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 d’abord 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 d’avancer." #. (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é, l’envoi 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é, l’envoi 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 "L’administrateur ne peut voir que le nom du fichier, sa taille et son type mime (son type de fichier : vidéo, text, etc)." +msgstr "L’administrateur 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 l’envoi au serveur : l’administrateur 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 l’envoi au serveur : l’administrateur 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 Luc Didry. If you want to support him, you can do it via Flattr or with Bitcoin." -msgstr "L’auteur originel (et pour l’instant, le seul) est Luc Didry. Si vous avez envie de le supporter, vous pouvez le faire via Flattr ou en Bitcoin." +msgid "The original (and only for now) author is Luc Didry. If you want to support him, you can do it via Tipeee or via Liberapay." +msgstr "L’auteur originel (et pour l’instant, le seul) est Luc Didry. Si vous avez envie de le supporter, vous pouvez le faire via Tipeee ou via Liberapay." -#: 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 l’enregistrement du fichier auquel ajouter votre fragment de fichier. Veuillez contacter l'administrateur." +msgstr "Le serveur a été incapable de retrouver l’enregistrement du fichier auquel ajouter votre fragment de fichier. Veuillez contacter l’administrateur." #: 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 n’existe 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. L’envoi 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 : " diff --git a/themes/default/public/css/lufi.css b/themes/default/public/css/lufi.css index cfc0f78..f935440 100644 --- a/themes/default/public/css/lufi.css +++ b/themes/default/public/css/lufi.css @@ -83,3 +83,6 @@ a.classic:focus { boxShadow: 'none'; background: 'transparent'; } +.hiddendiv.common { + min-height: 170px; +} diff --git a/themes/default/public/js/lufi-common.js b/themes/default/public/js/lufi-common.js new file mode 100644 index 0000000..b862513 --- /dev/null +++ b/themes/default/public/js/lufi-common.js @@ -0,0 +1,16 @@ +// vim:set sw=4 ts=4 sts=4 ft=javascript expandtab: +// Escape HTML chars +var entityMap = { + "&": "&", + "<": "<", + ">": ">", + '"': '"', + "'": ''', + "/": '/' +}; + +function escapeHtml(string) { + return String(string).replace(/[&<>"'\/]/g, function (s) { + return entityMap[s]; + }); +} diff --git a/themes/default/public/js/lufi-down.js b/themes/default/public/js/lufi-down.js index a99cc83..62405e1 100644 --- a/themes/default/public/js/lufi-down.js +++ b/themes/default/public/js/lufi-down.js @@ -91,10 +91,10 @@ function spawnWebsocket(pa) { var pbd = $('#pbd'); pbd.attr('class', 'center-align'); var blobURL = URL.createObjectURL(blob); - var innerHTML = [ '

', i18n.download, '

']; + var innerHTML = ['

', i18n.download, '

']; if (data.type.match(/^image\//) !== null) { - innerHTML.push('', data.name, ''); + innerHTML.push('', escapeHtml(data.name), ''); } else if (data.type.match(/^video\//) !== null) { innerHTML.push('