Files
awo-hamburg-intranet/module/knowledgecenter_update/Ajax/endpoints/upload_inline_image.php
Moritz Weinmann 743476f64a Module tasks + knowledgecenter_update aus Kundenprojekt übernehmen (bereinigt)
Beide Module wurden aus einem anderen Kundenprojekt kopiert und bereinigt:

Knowledgecenter:
- Bild-Cache (1.985 Dateien) geleert, Ordnerstruktur mit .gitkeep behalten
- Files-Gallery-Lizenzschlüssel entfernt (config.php)
- Kundenspezifische Kategorien gelöscht: Teil I/II/III QM-Struktur,
  nummerierte QM-Kapitel, Gremien (Präsidium/Finanzausschuss/Landesausschuss),
  Sitzungsservice-Serie, Protokoll-Abteilungen, Testeinträge
- 56 generische Kategorien bleiben (Downloads, Onboarding, Personalthemen …)

Tasks:
- Alle Betriebsdaten gelöscht (114 Tasks, 914 Submissions, 579 Assignments)
- Task-Definitionen und Verlinkungen geleert
- Kategoriestruktur bleibt (Allgemein, IT, Personal, Buchhaltung …)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-22 09:20:02 +02:00

152 lines
4.6 KiB
PHP

<?php
/**
* Inline-Image-Upload für Quill im Wiki-Editor.
* Wird vom imageHandler in post_cardform.php aufgerufen.
*
* Erwartet (multipart/form-data POST):
* - file : Hochgeladenes Bild (jpg/png/gif/webp, <= 5 MB)
* - post_id : int > 0 (knowledgecenter_posts.id)
*
* Antwort (JSON):
* { "success": true, "url": "/userdata/knowledgecenter_update/posts/<hash>/inline/<sha>.<ext>" }
* { "success": false, "error": "..." } (HTTP 4xx/5xx)
*/
session_start();
$currDir = __DIR__;
$rootDir = dirname(dirname(dirname(dirname($currDir))));
$mysydeDir = $rootDir . '/mysyde';
require_once($rootDir . '/vendor/autoload.php');
require_once($mysydeDir . '/frontend/frontend_functions.inc.php');
$envDir = $rootDir . '/config';
$envFilePath = $envDir . '/.env';
if (is_dir($envDir) && file_exists($envFilePath) && is_file($envFilePath) && is_readable($envFilePath)) {
$dotenv = new \Dotenv\Dotenv($envDir);
$dotenv->load();
}
require_once($mysydeDir . '/common/common_functions.inc.php');
$connEnv = (local_environment()) ? $mysydeDir . '/dc.config.php' : $mysydeDir . '/dc-server.config.php';
require_once($connEnv);
db_connect();
require_once($rootDir . '/module/intranet/intranet_functions.inc.php');
header('Content-Type: application/json');
function respond_error($msg, $code = 400)
{
http_response_code($code);
echo json_encode(['success' => false, 'error' => $msg]);
exit;
}
if (empty($_SESSION['login_id'])) {
respond_error('Nicht angemeldet.', 401);
}
$loginId = (int) $_SESSION['login_id'];
$q = mysqli_query($GLOBALS['mysql_con'], "SELECT id, master_mandant_id FROM main_contact WHERE id = $loginId LIMIT 1");
if (!$q || !($contactRow = mysqli_fetch_assoc($q))) {
respond_error('Benutzer nicht gefunden.', 401);
}
$contactId = (int) $contactRow['id'];
$masterMandantId = (int) $contactRow['master_mandant_id'];
if (get_permission_state('r-wiki', $masterMandantId, $contactId) != 1) {
respond_error('Keine Berechtigung (r-wiki).', 403);
}
$postId = isset($_POST['post_id']) ? (int) $_POST['post_id'] : 0;
if ($postId <= 0) {
respond_error('Ungültige post_id.');
}
$verifyQ = mysqli_query($GLOBALS['mysql_con'], "SELECT id FROM knowledgecenter_posts WHERE id = $postId LIMIT 1");
if (!$verifyQ || mysqli_num_rows($verifyQ) === 0) {
respond_error('Beitrag existiert nicht.', 404);
}
if (!isset($_FILES['file']) || !is_array($_FILES['file'])) {
respond_error('Keine Datei empfangen.');
}
$file = $_FILES['file'];
if ($file['error'] !== UPLOAD_ERR_OK) {
respond_error('Upload-Fehler (Code ' . (int) $file['error'] . ').');
}
$maxSize = 5 * 1024 * 1024;
if (!is_uploaded_file($file['tmp_name'])) {
respond_error('Ungültiger Upload.');
}
if ($file['size'] <= 0 || $file['size'] > $maxSize) {
respond_error('Datei zu groß oder leer (max 5 MB).');
}
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime = $finfo ? finfo_file($finfo, $file['tmp_name']) : false;
if ($finfo) {
finfo_close($finfo);
}
$mimeToExt = [
'image/jpeg' => 'jpg',
'image/png' => 'png',
'image/gif' => 'gif',
'image/webp' => 'webp',
];
if (!$mime || !isset($mimeToExt[$mime])) {
respond_error('Ungültiger Dateityp. Erlaubt: JPG, PNG, GIF, WEBP.');
}
$ext = $mimeToExt[$mime];
$hash = substr(sha1('kc_post_' . $postId), 0, 24);
$relBase = 'knowledgecenter_update/posts/' . $hash;
$absBase = $rootDir . '/userdata/' . $relBase;
$absInline = $absBase . '/inline';
if (!is_dir($absBase) && !@mkdir($absBase, 0775, true)) {
respond_error('Post-Ordner konnte nicht erstellt werden.', 500);
}
$sharedLink = $absBase . '/shared';
if (!is_link($sharedLink) && !file_exists($sharedLink)) {
@symlink('../../shared', $sharedLink);
}
if (!is_dir($absInline) && !@mkdir($absInline, 0775, true)) {
respond_error('Inline-Ordner konnte nicht erstellt werden.', 500);
}
$sha = hash_file('sha256', $file['tmp_name']);
if (!$sha) {
respond_error('Hashing fehlgeschlagen.', 500);
}
$finalName = $sha . '.' . $ext;
$finalPath = $absInline . '/' . $finalName;
$publicUrl = '/userdata/' . $relBase . '/inline/' . $finalName;
if (file_exists($finalPath)) {
if (filesize($finalPath) === (int) $file['size']) {
echo json_encode(['success' => true, 'url' => $publicUrl, 'dedup' => true]);
exit;
}
}
$tmpDest = $absInline . '/.tmp_' . bin2hex(random_bytes(6));
if (!move_uploaded_file($file['tmp_name'], $tmpDest)) {
respond_error('Datei konnte nicht gespeichert werden.', 500);
}
@chmod($tmpDest, 0664);
if (!rename($tmpDest, $finalPath)) {
@unlink($tmpDest);
respond_error('Datei konnte nicht verschoben werden.', 500);
}
echo json_encode(['success' => true, 'url' => $publicUrl]);
exit;