Initiales CMS: Deutschsprachiges Blog-System mit Admin-Bereich

Vollständiges, schlankes PHP/SQLite-CMS für IT-, KI- und Gaming-Inhalte:

- Core: DB-Singleton, Auth mit Passwort-Hashing, Session-Cookies,
  CSRF-Schutz, Login-Rate-Limit, Bild-Upload mit serverseitiger Validierung
- Admin: Dashboard, Artikel/Seiten-Verwaltung mit Quill WYSIWYG-Editor,
  Kategorien, Navigation (Drag & Drop), Medienbibliothek, Profil
- Frontend: Responsive Dark-Theme, Artikel-Grid, Kategorie-Filter,
  Archiv, Paginierung, SEO-Meta-Tags
- Sicherheit: Prepared Statements, HTML-Sanitizer, .htaccess-Schutz
  für sensible Verzeichnisse, PHP-Ausführungsschutz im Upload-Ordner
- Installation: install.php erstellt DB-Schema und Admin-Account

https://claude.ai/code/session_01Xsg4j2t4S9goMuWVpF3ezG
This commit is contained in:
Claude
2026-04-05 20:59:52 +00:00
commit 3c97192386
45 changed files with 2839 additions and 0 deletions

43
admin/upload-handler.php Normal file
View File

@@ -0,0 +1,43 @@
<?php
/**
* AJAX Upload-Endpoint für den WYSIWYG-Editor
*/
require_once __DIR__ . '/../core/auth.php';
require_once __DIR__ . '/../core/upload.php';
auth_start_session();
header('Content-Type: application/json');
if (!auth_is_logged_in()) {
http_response_code(401);
echo json_encode(['success' => false, 'error' => 'Nicht angemeldet.']);
exit;
}
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
http_response_code(405);
echo json_encode(['success' => false, 'error' => 'Methode nicht erlaubt.']);
exit;
}
// CSRF prüfen
$token = $_POST['csrf_token'] ?? $_SERVER['HTTP_X_CSRF_TOKEN'] ?? '';
if (!hash_equals(csrf_token(), $token)) {
http_response_code(403);
echo json_encode(['success' => false, 'error' => 'Ungültiges Token.']);
exit;
}
if (empty($_FILES['image'])) {
echo json_encode(['success' => false, 'error' => 'Keine Datei ausgewählt.']);
exit;
}
$url = handle_upload($_FILES['image']);
if ($url === false) {
echo json_encode(['success' => false, 'error' => 'Upload fehlgeschlagen. Erlaubt: JPG, PNG, GIF, WebP (max. 5 MB).']);
exit;
}
echo json_encode(['success' => true, 'url' => $url]);