Merge pull request 'Secured PDF and DJVU file handling and thumbnailing' (#118) from secure-file-handling into config

Reviewed-on: leftypol/leftypol#118
This commit is contained in:
Zankaria 2025-04-21 09:45:48 -05:00
commit 6763f7b416
3 changed files with 38 additions and 10 deletions

View file

@ -18,6 +18,8 @@ RUN apk add --no-cache \
graphicsmagick \
gifsicle \
ffmpeg \
djvulibre \
ghostscript \
bind-tools \
gettext \
gettext-dev \

View file

@ -1298,6 +1298,7 @@
$config['error']['pendingappeal'] = _('There is already a pending appeal for this ban.');
$config['error']['invalidpassword'] = _('Wrong password…');
$config['error']['invalidimg'] = _('Invalid image.');
$config['error']['invalidfile'] = _('Invalid file.');
$config['error']['unknownext'] = _('Unknown file extension.');
$config['error']['filesize'] = _('Maximum file size: %maxsz% bytes<br>Your file\'s size: %filesz% bytes');
$config['error']['maxsize'] = _('The file was too big.');
@ -2068,9 +2069,16 @@
// Enable auto IP note generation of moderator deleted posts
$config['autotagging'] = false;
// Enable PDF file thumbnail generation
// Enable PDF thumbnail generation.
// Requires a working installation of ghostscript and imagemagick.
// Imagemagick support of PDF files is not required.
$config['pdf_file_thumbnail'] = false;
// Enable djvu thumbnail generation.
// Requires djvulibre's tools and imagemagick.
// Imagemagick support of djvu files is not required.
$config['djvu_file_thumbnail'] = false;
// Enable TXT file thumbnail
$config['txt_file_thumbnail'] = false;

View file

@ -1447,17 +1447,35 @@ function handle_post(Context $ctx)
}
$image->destroy();
} else {
if (
($file['extension'] == "pdf" && $config['pdf_file_thumbnail']) ||
($file['extension'] == "djvu" && $config['djvu_file_thumbnail'])
) {
$path = $file['thumb'];
$error = shell_exec_error('convert -size ' . $config['thumb_width'] . 'x' . $config['thumb_height'] . ' -thumbnail ' . $config['thumb_width'] . 'x' . $config['thumb_height'] . ' -background white -alpha remove ' .
escapeshellarg($file['tmp_name'] . '[0]') . ' ' .
escapeshellarg($file['thumb']));
$mime = \mime_content_type($file['tmp_name']);
$pdf = $file['extension'] === "pdf" && $config['pdf_file_thumbnail'];
$djvu = $file['extension'] === "djvu" && $config['djvu_file_thumbnail'];
if ($pdf || $djvu) {
$e_thumb_path = \escapeshellarg($file['thumb']);
$e_file_path = \escapeshellarg($file['tmp_name']);
$thumb_width = $config['thumb_width'];
$thumb_height = $config['thumb_height'];
// Generates a PPM image and pipes it directly into convert for resizing + type conversion.
if ($pdf && $mime === 'application/pdf') {
$error = shell_exec_error("gs -dSAFER -dBATCH -dNOPAUSE -dQUIET \
-sDEVICE=ppmraw -r100 -dFirstPage=1 -dLastPage=1 -sOutputFile=- $e_file_path \
| convert -thumbnail {$thumb_width}x{$thumb_height} ppm:- $e_thumb_path");
} elseif ($djvu && $mime === 'image/vnd.djvu') {
$error = shell_exec_error("ddjvu -format=ppm -page 1 $e_file_path \
| convert -thumbnail {$thumb_width}x{$thumb_height} ppm:- $e_thumb_path");
} else {
// Mime check failed.
error($config['error']['invalidfile']);
}
if ($error) {
$path = sprintf($config['file_thumb'], isset($config['file_icons'][$file['extension']]) ? $config['file_icons'][$file['extension']] : $config['file_icons']['default']);
$log = $ctx->get(LogDriver::class);
$log->log(LogDriver::ERROR, 'Could not render thumbnail for PDF/DJVU file, using static fallback.');
$path = \sprintf($config['file_thumb'], isset($config['file_icons'][$file['extension']]) ? $config['file_icons'][$file['extension']] : $config['file_icons']['default']);
} else {
$path = $file['thumb'];
}
$file['thumb'] = basename($file['thumb']);