VERO/templates/upload.php
2026-03-04 10:12:09 +01:00

303 lines
9.5 KiB
PHP
Executable File

<?php
// upload.php - Version für AJAX
$ini_array = parse_ini_file("config.ini", true);
$baseURL = $ini_array['base']['URL'];
session_start();
if(! isset($_SESSION["loggedin"]) || $_SESSION["loggedin"] === false){
header("location: " .$baseURL ."/redirecttologin.php");
}
date_default_timezone_set('Europe/Berlin');
// CORS-Headers für AJAX-Requests (falls nötig)
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST');
header('Access-Control-Allow-Headers: Content-Type');
header('Content-Type: application/json; charset=utf-8');
// Fehlerbehandlung für bessere AJAX-Antworten
set_error_handler('custom_error_handler');
set_exception_handler('custom_exception_handler');
// Konfiguration
$max_file_size = 10 * 1024 * 1024; // 10MB
$allowed_types = array('application/pdf');
$upload_dir = '../uploads/';
// Upload-Ordner erstellen
if (!is_dir($upload_dir)) {
if (!mkdir($upload_dir, 0755, true)) {
send_json_response(false, 'Upload-Ordner konnte nicht erstellt werden.');
}
}
// Globale Variablen
$uploaded_files = array();
$errors = array();
$start_time = microtime(true);
// Hauptverarbeitung
try {
process_ajax_upload();
} catch (Exception $e) {
send_json_response(false, 'Server-Fehler: ' . $e->getMessage());
}
// ==================== FUNKTIONEN ====================
function process_ajax_upload() {
global $uploaded_files, $errors;
// Prüfe HTTP-Methode
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
send_json_response(false, 'Nur POST-Requests erlaubt.');
}
// Prüfe ob Dateien gesendet wurden
if (empty($_FILES)) {
send_json_response(false, 'Keine Dateien empfangen.');
}
// Memory Limit erhöhen für große Uploads
ini_set('memory_limit', '256M');
// Alle Dateien verarbeiten
foreach ($_FILES as $file_key => $file) {
if ($file['error'] === UPLOAD_ERR_OK) {
process_single_file($file_key, $file);
} else if ($file['error'] !== UPLOAD_ERR_NO_FILE) {
$errors[] = get_upload_error_message($file['error']) . " (Datei: $file_key)";
}
}
// Antwort senden
send_upload_response();
}
function process_single_file($file_key, $file) {
global $uploaded_files, $errors, $max_file_size, $allowed_types, $upload_dir;
$file_number = str_replace('pdf_file_', '', $file_key);
$document_type = get_post_value('doc_type_' . $file_number);
// Detaillierte Validierung
$validation_result = validate_uploaded_file($file, $file_number, $document_type);
if (!$validation_result['valid']) {
$errors = array_merge($errors, $validation_result['errors']);
return;
}
// Eindeutigen Dateinamen generieren
$safe_filename = create_unique_filename($file['name'], $file_number);
$target_path = $upload_dir . $safe_filename;
// Datei verschieben mit Fehlerbehandlung
if (move_uploaded_file($file['tmp_name'], $target_path)) {
$file_info = array(
'original_name' => $file['name'],
'saved_name' => $safe_filename,
'document_type' => $document_type,
'file_number' => intval($file_number),
'size' => $file['size'],
'path' => $target_path,
'upload_time' => date('Y-m-d H:i:s'),
'mime_type' => $file['type']
);
$uploaded_files[] = $file_info;
// Logging
log_upload_activity($file_info);
// Optional: Datei-Metadaten in Datenbank speichern
// save_file_to_database($file_info);
} else {
$errors[] = "Datei $file_number konnte nicht gespeichert werden (Berechtigung prüfen)";
}
}
function validate_uploaded_file($file, $file_number, $document_type) {
global $max_file_size, $allowed_types;
$validation_errors = array();
/* foreach($file as $key => $ele){
$validation_errors[] = $key .": " .$ele ."<br>";
}
*/
// PDF-Datei Passwort geschützt?
$command = "pdfinfo " . $file['tmp_name'] . " 2>&1";
$output = shell_exec($command);
// $validation_errors[] = "pdfinfo: " .$output;
if (strpos($output, 'Incorrect password') !== false ||
strpos($output, 'Command Line Error') !== false) {
$validation_errors[] = "Datei '" .$file['name'] ."' ist mit einem Passwort geschützt. Verarbeitung nicht möglich.";
}
// Dokumentenart prüfen
if (empty($document_type)) {
$validation_errors[] = "Dokumentenart für Datei $file_number fehlt";
}
// Dateigröße prüfen
if ($file['size'] > $max_file_size) {
$max_mb = round($max_file_size / (1024 * 1024 * 10));
$file_mb = round($file['size'] / (1024 * 1024 * 10), 2);
$validation_errors[] = "Datei $file_number zu groß: {$file_mb}MB (max. {$max_mb}MB)";
}
// MIME-Type prüfen
if (!in_array($file['type'], $allowed_types)) {
$validation_errors[] = "Datei $file_number hat ungültigen MIME-Type: {$file['type']}";
}
// Dateiendung prüfen
$file_extension = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
if ($file_extension !== 'pdf') {
$validation_errors[] = "Datei $file_number hat keine .pdf Endung";
}
// Dateiinhalt zusätzlich prüfen (PDF-Header)
if (!is_valid_pdf_file($file['tmp_name'])) {
$validation_errors[] = "Datei $file_number ist keine gültige PDF-Datei";
}
return array(
'valid' => empty($validation_errors),
'errors' => $validation_errors
);
}
function is_valid_pdf_file($file_path) {
// PDF-Header prüfen
$handle = fopen($file_path, 'rb');
if (!$handle) return false;
$header = fread($handle, 4);
fclose($handle);
return $header === '%PDF';
}
function create_unique_filename($original_name, $file_number) {
$name_info = pathinfo($original_name);
$base_name = preg_replace('/[^a-zA-Z0-9._-]/', '_', $name_info['filename']);
$extension = $name_info['extension'];
// Zeitstempel und zusätzliche Eindeutigkeit
$timestamp = date('YmdHis');
$random = substr(md5(uniqid(rand(), true)), 0, 6);
return $base_name . '_' . $timestamp . '_' . $file_number . '_' . $random . '.' . $extension;
}
function log_upload_activity($file_info) {
$log_entry = array(
'timestamp' => $file_info['upload_time'],
'original_name' => $file_info['original_name'],
'saved_name' => $file_info['saved_name'],
'document_type' => $file_info['document_type'],
'size' => $file_info['size'],
'ip_address' => get_client_ip()
);
$log_file = '../uploads/upload_log.json';
// Bestehende Logs laden
$existing_logs = array();
if (file_exists($log_file)) {
$existing_logs = json_decode(file_get_contents($log_file), true) ?: array();
}
// Neuen Eintrag hinzufügen
$existing_logs[] = $log_entry;
// Logs speichern
file_put_contents($log_file, json_encode($existing_logs, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));
}
function get_client_ip() {
$ip_keys = array('HTTP_X_FORWARDED_FOR', 'HTTP_X_REAL_IP', 'HTTP_CLIENT_IP', 'REMOTE_ADDR');
foreach ($ip_keys as $key) {
if (!empty($_SERVER[$key])) {
$ip = $_SERVER[$key];
if (strpos($ip, ',') !== false) {
$ip = trim(explode(',', $ip)[0]);
}
if (filter_var($ip, FILTER_VALIDATE_IP)) {
return $ip;
}
}
}
return 'unknown';
}
function get_post_value($key) {
return isset($_POST[$key]) ? trim($_POST[$key]) : '';
}
function get_upload_error_message($error_code) {
$messages = array(
UPLOAD_ERR_INI_SIZE => 'Datei überschreitet upload_max_filesize',
UPLOAD_ERR_FORM_SIZE => 'Datei überschreitet MAX_FILE_SIZE',
UPLOAD_ERR_PARTIAL => 'Datei wurde nur teilweise hochgeladen',
UPLOAD_ERR_NO_FILE => 'Keine Datei hochgeladen',
UPLOAD_ERR_NO_TMP_DIR => 'Temporärer Ordner fehlt',
UPLOAD_ERR_CANT_WRITE => 'Fehler beim Schreiben',
UPLOAD_ERR_EXTENSION => 'Upload durch Extension blockiert'
);
return isset($messages[$error_code]) ? $messages[$error_code] : "Unbekannter Fehler ($error_code)";
}
function send_upload_response() {
global $uploaded_files, $errors, $start_time;
$execution_time = round(microtime(true) - $start_time, 2);
$response = array(
'success' => empty($errors),
'message' => empty($errors)
? count($uploaded_files) . ' Datei(en) erfolgreich hochgeladen'
// : 'Upload mit ' . count($errors) . ' Fehler(n) abgeschlossen',
: '',
'files' => $uploaded_files,
'errors' => $errors,
'execution_time' => $execution_time . 's',
'timestamp' => date('Y-m-d H:i:s')
);
send_json_response($response['success'], $response['message'], $response);
}
function send_json_response($success, $message, $additional_data = array()) {
$response = array_merge(array(
'success' => $success,
'message' => $message,
'timestamp' => date('Y-m-d H:i:s')
), $additional_data);
echo json_encode($response, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
exit;
}
function custom_error_handler($severity, $message, $file, $line) {
if (!(error_reporting() & $severity)) return;
send_json_response(false, "PHP Fehler: $message in $file:$line");
}
function custom_exception_handler($exception) {
send_json_response(false, "Exception: " . $exception->getMessage());
}
?>