fixed sanitizeFilename for backend\API,

added new API call attachmentDownload,
fixed attachment URL to call attachmentDownload,
refactoring Report.vue for <script setup>
This commit is contained in:
2025-10-16 01:40:44 +02:00
parent ed3d202488
commit 3e9056f4a6
4 changed files with 225 additions and 169 deletions

View File

@ -187,7 +187,7 @@ class API extends APIlite
if (!is_array($data)) return false;
$base64 = preg_replace('/^data:.*?;base64,/', '', $data['base64']);
$base64_data = base64_decode($base64);
$filename = 'report_' . $report_id . '_' . time() . '_' . sanitizeFilename($data['filename']);
$filename = 'report_' . $report_id . '_' . time() . '_' . $this->sanitizeFilename($data['filename']);
file_put_contents(UPLOAD_DIR_ATTACHMENTS . $filename, $base64_data);
$attachment_content = $filename;
}
@ -201,6 +201,26 @@ class API extends APIlite
return $suc !== false;
}
private function sanitizeFilename($filename, $allowedExtensions = [])
{
// Rozdelenie názvu a prípony
$pathInfo = pathinfo($filename);
$name = $pathInfo['filename'] ?? 'file';
$extension = strtolower($pathInfo['extension'] ?? '');
// Odstránenie nebezpečných znakov z názvu
$name = preg_replace('/[^a-zA-Z0-9_-]/', '_', $name);
$name = substr($name, 0, 100); // voliteľné obmedzenie dĺžky
// Validácia prípony, ak je zoznam povolený
if (
$allowedExtensions
&& count($allowedExtensions) > 0
&& !in_array($extension, $allowedExtensions)
) {
$extension = 'bin'; // fallback ak prípona nie je povolená
}
return $name . '.' . $extension;
}
/**
* Update report attachment
*
@ -236,7 +256,7 @@ class API extends APIlite
->toArray();
if (is_array($all)) foreach ($all as $key => $row) {
if ($all[$key]['attachment_type'] == 'file') {
$all[$key]['attachment_content'] = UPLOAD_URL_ATTACHMENTS . $all[$key]['attachment_content'];
$all[$key]['attachment_content'] = '?action=attachmentDownload&filename=' . $all[$key]['attachment_content'];
}
}
return $all;
@ -254,4 +274,28 @@ class API extends APIlite
$suc = $attachments->attachment($attachment_id, null);
return $suc !== false;
}
/**
* Download report attachment
*
* @param string $filename
*
* @return void
*/
public function attachmentDownload(string $filename): void {
$filename = $this->sanitizeFilename($filename);
$filename = UPLOAD_DIR_ATTACHMENTS . $filename;
if (file_exists($filename)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="' . basename($filename) . '"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($filename));
readfile($filename);
exit;
}
}
}