mirror of
https://github.com/Part-DB/Part-DB-server.git
synced 2026-07-15 13:51:39 +00:00
Refactored size checks for attachments and check base64 upload length
This commit is contained in:
parent
a356b94c34
commit
76a36386fc
5 changed files with 33 additions and 68 deletions
|
|
@ -74,7 +74,7 @@ class ToolsController extends AbstractController
|
||||||
'detailed_error_pages' => $this->getParameter('partdb.error_pages.show_help'),
|
'detailed_error_pages' => $this->getParameter('partdb.error_pages.show_help'),
|
||||||
'error_page_admin_email' => $this->getParameter('partdb.error_pages.admin_email'),
|
'error_page_admin_email' => $this->getParameter('partdb.error_pages.admin_email'),
|
||||||
'configured_max_file_size' => $settings->system->attachments->maxFileSize,
|
'configured_max_file_size' => $settings->system->attachments->maxFileSize,
|
||||||
'effective_max_file_size' => $attachmentSubmitHandler->getMaximumAllowedUploadSize(),
|
'effective_max_file_size' => $attachmentSubmitHandler->getMaximumEffectiveUploadSize(),
|
||||||
'saml_enabled' => $this->getParameter('partdb.saml.enabled'),
|
'saml_enabled' => $this->getParameter('partdb.saml.enabled'),
|
||||||
|
|
||||||
//PHP section
|
//PHP section
|
||||||
|
|
|
||||||
|
|
@ -209,7 +209,7 @@ class AttachmentFormType extends AbstractType
|
||||||
|
|
||||||
public function finishView(FormView $view, FormInterface $form, array $options): void
|
public function finishView(FormView $view, FormInterface $form, array $options): void
|
||||||
{
|
{
|
||||||
$view->vars['max_upload_size'] = $this->submitHandler->getMaximumAllowedUploadSize();
|
$view->vars['max_upload_size'] = $this->submitHandler->getMaximumEffectiveUploadSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getBlockPrefix(): string
|
public function getBlockPrefix(): string
|
||||||
|
|
|
||||||
|
|
@ -218,6 +218,14 @@ class AttachmentSubmitHandler
|
||||||
|
|
||||||
//If no file was uploaded, but we have base64 encoded data, create a file from it
|
//If no file was uploaded, but we have base64 encoded data, create a file from it
|
||||||
if (!$file && $upload->data !== null) {
|
if (!$file && $upload->data !== null) {
|
||||||
|
if (strlen($upload->data) > $this->getMaximumUserConfiguredUploadSize() * 4 / 3) { //Base64 encoding increases the size of the data by 4/3, so we have to check for that
|
||||||
|
throw new RuntimeException(
|
||||||
|
sprintf(
|
||||||
|
'The given base64 data is too big! Maximum size is %.1f MB!',
|
||||||
|
$this->getMaximumUserConfiguredUploadSize() / 1000 / 1000
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
$file = new UploadedBase64EncodedFile(new Base64EncodedFile($upload->data), $upload->filename ?? 'base64');
|
$file = new UploadedBase64EncodedFile(new Base64EncodedFile($upload->data), $upload->filename ?? 'base64');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -226,6 +234,15 @@ class AttachmentSubmitHandler
|
||||||
|
|
||||||
//When a file is given then upload it, otherwise check if we need to download the URL
|
//When a file is given then upload it, otherwise check if we need to download the URL
|
||||||
if ($file instanceof UploadedFile) {
|
if ($file instanceof UploadedFile) {
|
||||||
|
//Check the file size, to avoid uploading too big files.
|
||||||
|
//The file is not necessarily validated as it can also come from an Base64 source
|
||||||
|
if ($file->getSize() > $this->getMaximumUserConfiguredUploadSize()) {
|
||||||
|
throw new RuntimeException(
|
||||||
|
sprintf(
|
||||||
|
'The uploaded file is too big! Maximum size is %.1f MB!',
|
||||||
|
$this->getMaximumUserConfiguredUploadSize() / 1000 / 1000
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
$this->upload($attachment, $file, $secure_attachment);
|
$this->upload($attachment, $file, $secure_attachment);
|
||||||
} elseif ($upload->downloadUrl && $attachment->hasExternal()) {
|
} elseif ($upload->downloadUrl && $attachment->hasExternal()) {
|
||||||
|
|
@ -402,7 +419,7 @@ class AttachmentSubmitHandler
|
||||||
$fileHandler = fopen($tmp_path, 'wb');
|
$fileHandler = fopen($tmp_path, 'wb');
|
||||||
|
|
||||||
$bytesDownloaded = 0;
|
$bytesDownloaded = 0;
|
||||||
$maxSize = $this->attachmentsSettings->getMaxFileSizeInMegabytes() * 1024 * 1024; //Convert to bytes
|
$maxSize = $this->getMaximumUserConfiguredUploadSize(); //We use the maximum user configured size here, PHPs limits dont apply
|
||||||
|
|
||||||
//Write the downloaded data to file
|
//Write the downloaded data to file
|
||||||
foreach ($this->httpClient->stream($response) as $chunk) {
|
foreach ($this->httpClient->stream($response) as $chunk) {
|
||||||
|
|
@ -418,8 +435,8 @@ class AttachmentSubmitHandler
|
||||||
|
|
||||||
throw new AttachmentDownloadException(
|
throw new AttachmentDownloadException(
|
||||||
sprintf(
|
sprintf(
|
||||||
'The downloaded file is too big! Maximum size is %d MB!',
|
'The downloaded file is too big! Maximum size is %.1f MB!',
|
||||||
$this->settings->getMaxFileSizeInMegabytes()
|
$maxSize / 1000 / 1000
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -527,10 +544,10 @@ class AttachmentSubmitHandler
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns the maximum allowed upload size in bytes.
|
* Returns the maximum effective upload size in bytes.
|
||||||
* This is the minimum value of Part-DB max_file_size, and php.ini's post_max_size and upload_max_filesize.
|
* This is the minimum value of Part-DB max_file_size, and php.ini's post_max_size and upload_max_filesize.
|
||||||
*/
|
*/
|
||||||
public function getMaximumAllowedUploadSize(): int
|
public function getMaximumEffectiveUploadSize(): int
|
||||||
{
|
{
|
||||||
if ($this->max_upload_size_bytes) {
|
if ($this->max_upload_size_bytes) {
|
||||||
return $this->max_upload_size_bytes;
|
return $this->max_upload_size_bytes;
|
||||||
|
|
@ -545,6 +562,15 @@ class AttachmentSubmitHandler
|
||||||
return $this->max_upload_size_bytes;
|
return $this->max_upload_size_bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the maximum user configured upload size in bytes.
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getMaximumUserConfiguredUploadSize(): int
|
||||||
|
{
|
||||||
|
return $this->parseFileSizeString($this->settings->maxFileSize);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sanitizes the given SVG file, if the attachment is an internal SVG file.
|
* Sanitizes the given SVG file, if the attachment is an internal SVG file.
|
||||||
* @param Attachment $attachment
|
* @param Attachment $attachment
|
||||||
|
|
|
||||||
|
|
@ -65,18 +65,4 @@ class AttachmentsSettings
|
||||||
envVar: "bool:ATTACHMENT_SHOW_HTML_FILES", envVarMode: EnvVarMode::OVERWRITE
|
envVar: "bool:ATTACHMENT_SHOW_HTML_FILES", envVarMode: EnvVarMode::OVERWRITE
|
||||||
)]
|
)]
|
||||||
public bool $showHTMLAttachments = false;
|
public bool $showHTMLAttachments = false;
|
||||||
|
|
||||||
public function getMaxFileSizeInMegabytes(): int
|
|
||||||
{
|
|
||||||
$size = $this->maxFileSize;
|
|
||||||
$unit = strtoupper(substr($size, -1));
|
|
||||||
$value = (int) rtrim($size, 'KMG');
|
|
||||||
|
|
||||||
return match ($unit) {
|
|
||||||
'K' => (int) ceil($value / 1024),
|
|
||||||
'M' => $value,
|
|
||||||
'G' => $value * 1024,
|
|
||||||
default => $value, // No unit specified, assume megabytes
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,47 +0,0 @@
|
||||||
<?php
|
|
||||||
/*
|
|
||||||
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
|
|
||||||
*
|
|
||||||
* Copyright (C) 2019 - 2026 Jan Böhmer (https://github.com/jbtronics)
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published
|
|
||||||
* by the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace App\Tests\Settings\SystemSettings;
|
|
||||||
|
|
||||||
use App\Settings\SystemSettings\AttachmentsSettings;
|
|
||||||
use App\Tests\SettingsTestHelper;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
class AttachmentsSettingsTest extends TestCase
|
|
||||||
{
|
|
||||||
|
|
||||||
public function testGetMaxFileSizeInMegabytes(): void
|
|
||||||
{
|
|
||||||
$settings = SettingsTestHelper::createSettingsDummy(AttachmentsSettings::class);
|
|
||||||
|
|
||||||
$settings->maxFileSize = '100M';
|
|
||||||
$this->assertEquals(100, $settings->getMaxFileSizeInMegabytes());
|
|
||||||
|
|
||||||
$settings->maxFileSize = '1G';
|
|
||||||
$this->assertEquals(1024, $settings->getMaxFileSizeInMegabytes());
|
|
||||||
|
|
||||||
//We round up to the next megabyte if the file size is smaller than 1 MB
|
|
||||||
$settings->maxFileSize = '500K';
|
|
||||||
$this->assertEquals(1, $settings->getMaxFileSizeInMegabytes());
|
|
||||||
|
|
||||||
$settings->maxFileSize = '13.5M';
|
|
||||||
$this->assertEquals(13, $settings->getMaxFileSizeInMegabytes());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue