0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) { $i--; $j--; } if (!$res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1))."/main.inc.php")) $res = @include substr($tmp, 0, ($i + 1))."/main.inc.php"; if (!$res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php")) $res = @include dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php"; if (!$res && file_exists("../../main.inc.php")) $res = @include "../../main.inc.php"; if (!$res && file_exists("../../../main.inc.php")) $res = @include "../../../main.inc.php"; if (!$res) die("Include of main fails"); require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; require_once __DIR__.'/../class/upload_token.class.php'; header('Content-Type: application/json; charset=utf-8'); function fail($msg, $code = 400) { http_response_code($code); echo json_encode(array('success' => false, 'error' => $msg)); exit; } // Token validieren $token = (string) ($_REQUEST['token'] ?? ''); $tok = BerichtUploadToken::fetchValid($db, $token); if (!$tok) { fail('Token ungültig oder abgelaufen', 403); } // Upload-Ziel ermitteln $upload_dir = $tok->getUploadDir(); if (!$upload_dir) { fail('Objekt nicht gefunden', 404); } // Seiten prüfen if (empty($_FILES['pages']) || !is_array($_FILES['pages']['tmp_name'])) { fail('Keine Seiten hochgeladen'); } $pages = $_FILES['pages']; $page_count = count($pages['tmp_name']); if ($page_count === 0) { fail('Keine Seiten hochgeladen'); } // Temp-Verzeichnis für Verarbeitung $tmpdir = sys_get_temp_dir().'/bericht_scan_'.uniqid(); if (!mkdir($tmpdir, 0755, true)) { fail('Temp-Verzeichnis konnte nicht erstellt werden'); } $cleanup = function() use ($tmpdir) { // Temp-Dateien aufräumen array_map('unlink', glob($tmpdir.'/*')); @rmdir($tmpdir); }; // Seiten speichern und optimieren $image_files = array(); for ($i = 0; $i < $page_count; $i++) { if (empty($pages['tmp_name'][$i])) continue; $ext = strtolower(pathinfo($pages['name'][$i], PATHINFO_EXTENSION)); if (!in_array($ext, array('jpg', 'jpeg', 'png'))) { $cleanup(); fail('Nur JPG/PNG erlaubt'); } // Seite nummeriert speichern $page_file = sprintf('%s/page_%03d.jpg', $tmpdir, $i + 1); // Mit ImageMagick optimieren (Kontrast, Größe) $tmp_file = $pages['tmp_name'][$i]; // Prüfen ob convert (ImageMagick) verfügbar ist $convert_bin = '/usr/bin/convert'; if (!file_exists($convert_bin)) { $convert_bin = trim(shell_exec('which convert 2>/dev/null')); } if ($convert_bin && file_exists($convert_bin)) { // Bild optimieren: Kontrast erhöhen, Größe begrenzen, als JPG speichern $cmd = escapeshellcmd($convert_bin).' ' .escapeshellarg($tmp_file) .' -resize 2400x2400\> ' // Max 2400px, Seitenverhältnis beibehalten .' -normalize ' // Kontrast optimieren .' -quality 92 ' .escapeshellarg($page_file).' 2>&1'; exec($cmd, $output, $ret); if ($ret !== 0 || !file_exists($page_file)) { // Fallback: einfach kopieren copy($tmp_file, $page_file); } } else { // Kein ImageMagick: einfach kopieren copy($tmp_file, $page_file); } if (file_exists($page_file)) { $image_files[] = $page_file; } } if (empty($image_files)) { $cleanup(); fail('Keine gültigen Seiten verarbeitet'); } // Ziel-Dateiname if (!is_dir($upload_dir)) dol_mkdir($upload_dir); $timestamp = dol_print_date(dol_now(), '%Y%m%d_%H%M%S'); $pdf_filename = 'scan_'.$timestamp.'_'.uniqid().'.pdf'; $pdf_path = $upload_dir.'/'.$pdf_filename; // PDF erstellen $pdf_created = false; // Methode 1: ocrmypdf (bevorzugt - erzeugt durchsuchbares PDF) $ocrmypdf_bin = getDolGlobalString('BERICHT_OCRMYPDF_BIN', '/usr/bin/ocrmypdf'); if (!file_exists($ocrmypdf_bin)) { $ocrmypdf_bin = trim(shell_exec('which ocrmypdf 2>/dev/null')); } if ($ocrmypdf_bin && file_exists($ocrmypdf_bin)) { // Erst Bilder zu PDF zusammenfügen mit img2pdf oder convert $img2pdf_bin = trim(shell_exec('which img2pdf 2>/dev/null')); $temp_pdf = $tmpdir.'/temp.pdf'; if ($img2pdf_bin && file_exists($img2pdf_bin)) { // img2pdf ist schneller und verlustfrei $cmd = escapeshellcmd($img2pdf_bin).' -o '.escapeshellarg($temp_pdf); foreach ($image_files as $f) { $cmd .= ' '.escapeshellarg($f); } exec($cmd.' 2>&1', $output, $ret); } elseif ($convert_bin && file_exists($convert_bin)) { // Fallback: ImageMagick convert $cmd = escapeshellcmd($convert_bin); foreach ($image_files as $f) { $cmd .= ' '.escapeshellarg($f); } $cmd .= ' '.escapeshellarg($temp_pdf); exec($cmd.' 2>&1', $output, $ret); } if (file_exists($temp_pdf)) { // OCR mit ocrmypdf $lang = getDolGlobalString('BERICHT_OCR_LANG', 'deu+eng'); $cmd = escapeshellcmd($ocrmypdf_bin) .' -l '.escapeshellarg($lang) .' --rotate-pages ' // Automatische Rotation .' --deskew ' // Schräglage korrigieren .' --clean ' // Hintergrund bereinigen .' --optimize 1 ' // Leichte Optimierung .' '.escapeshellarg($temp_pdf) .' '.escapeshellarg($pdf_path) .' 2>&1'; exec($cmd, $output, $ret); if ($ret === 0 && file_exists($pdf_path)) { $pdf_created = true; } } } // Methode 2: Fallback mit ImageMagick (kein OCR) if (!$pdf_created && $convert_bin && file_exists($convert_bin)) { $cmd = escapeshellcmd($convert_bin); foreach ($image_files as $f) { $cmd .= ' '.escapeshellarg($f); } $cmd .= ' -quality 92 '.escapeshellarg($pdf_path).' 2>&1'; exec($cmd, $output, $ret); if ($ret === 0 && file_exists($pdf_path)) { $pdf_created = true; } } // Methode 3: Fallback mit TCPDF (PHP-only) if (!$pdf_created) { // TCPDF sollte in Dolibarr verfügbar sein if (file_exists(DOL_DOCUMENT_ROOT.'/includes/tecnickcom/tcpdf/tcpdf.php')) { require_once DOL_DOCUMENT_ROOT.'/includes/tecnickcom/tcpdf/tcpdf.php'; $pdf = new TCPDF('P', 'mm', 'A4', true, 'UTF-8', false); $pdf->SetCreator('Dolibarr Bericht-Modul'); $pdf->SetAuthor('Dokumenten-Scanner'); $pdf->SetTitle('Gescanntes Dokument'); $pdf->SetMargins(0, 0, 0); $pdf->SetAutoPageBreak(false); $pdf->setPrintHeader(false); $pdf->setPrintFooter(false); foreach ($image_files as $img) { $pdf->AddPage(); $size = getimagesize($img); if ($size) { $w = $size[0]; $h = $size[1]; // Bild auf A4 skalieren (210x297mm) $ratio = min(210 / ($w * 0.264583), 297 / ($h * 0.264583)); $pdf->Image($img, 0, 0, $w * 0.264583 * $ratio, $h * 0.264583 * $ratio); } } $pdf->Output($pdf_path, 'F'); if (file_exists($pdf_path)) { $pdf_created = true; } } } // Aufräumen $cleanup(); if (!$pdf_created) { fail('PDF konnte nicht erstellt werden. Bitte prüfen Sie die Server-Konfiguration (ImageMagick/ocrmypdf).'); } // Token-Counter erhöhen $tok->incrementCount(); // Erfolg echo json_encode(array( 'success' => true, 'filename' => $pdf_filename, 'pages' => count($image_files), 'ocr' => ($ocrmypdf_bin && file_exists($ocrmypdf_bin)) ? true : false, ));