diff --git a/.htaccess b/.htaccess
index 272f275..f40a73c 100644
--- a/.htaccess
+++ b/.htaccess
@@ -2,17 +2,26 @@
Options -Indexes
RewriteEngine On
-# Interne PHP- und Template-Verzeichnisse vor direktem Webzugriff sperren
+# HTTP Security Headers
+
+ Header always set X-Frame-Options "SAMEORIGIN"
+ Header always set X-Content-Type-Options "nosniff"
+ Header always set Referrer-Policy "strict-origin-when-cross-origin"
+
+
+# Interne PHP-, Vendor- und Template-Verzeichnisse vor direktem Webzugriff sperren
RewriteRule ^(home|philcore)/(app|core|views|src)/ - [F,L]
+RewriteRule ^(.*/)?vendor/ - [F,L]
# Sensible Dateien und Verzeichnisse vor direktem Webzugriff schützen
Require all denied
-
+# Interne Hilfsdateien vor direktem Aufruf schützen
+
Require all denied
-
+
# 1. Assets aus home/public weiterleiten (falls direkt aufgerufen wie /css/style.css)
RewriteCond %{REQUEST_FILENAME} !-f
diff --git a/auth.php b/auth.php
index 95a3f21..6a41921 100644
--- a/auth.php
+++ b/auth.php
@@ -6,6 +6,7 @@ if (session_status() === PHP_SESSION_NONE) {
session_set_cookie_params([
'path' => '/',
'httponly' => true,
+ 'secure' => (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off'),
'samesite' => 'Lax' // Lax erlaubt den Wechsel zwischen /home und /test
]);
session_start();
diff --git a/dinos/api_proxy.php b/dinos/api_proxy.php
new file mode 100644
index 0000000..3500eb5
--- /dev/null
+++ b/dinos/api_proxy.php
@@ -0,0 +1,92 @@
+ 'Nur POST-Anfragen sind erlaubt.']);
+ exit;
+}
+
+// 1. API-Schlüssel sicher aus .env laden
+$apiKey = '';
+$envFiles = [__DIR__ . '/.env', __DIR__ . '/../home/.env'];
+foreach ($envFiles as $envFile) {
+ if (file_exists($envFile)) {
+ foreach (file($envFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) as $line) {
+ $line = trim($line);
+ if ($line === '' || $line[0] === '#') continue;
+ if (strpos($line, '=') !== false) {
+ list($k, $v) = explode('=', $line, 2);
+ if (trim($k) === 'GEMINI_API_KEY') {
+ $apiKey = trim(trim($v), '"\'');
+ break 2;
+ }
+ }
+ }
+ }
+}
+
+if (empty($apiKey)) {
+ http_response_code(500);
+ echo json_encode(['error' => 'API-Schlüssel nicht konfiguriert.']);
+ exit;
+}
+
+// 2. JSON-Daten empfangen
+$json_input = file_get_contents('php://input');
+$request_data = json_decode($json_input, true);
+
+if (json_last_error() !== JSON_ERROR_NONE || !isset($request_data['apiUrl']) || !isset($request_data['payload'])) {
+ http_response_code(400);
+ echo json_encode(['error' => 'Ungültige Anfrage-Daten.']);
+ exit;
+}
+
+$apiUrl = $request_data['apiUrl'];
+$payload = $request_data['payload'];
+
+// 3. SSRF-Schutz: Nur generativelanguage.googleapis.com erlauben
+$parsed = parse_url($apiUrl);
+if (!isset($parsed['host']) || $parsed['host'] !== 'generativelanguage.googleapis.com') {
+ http_response_code(403);
+ echo json_encode(['error' => 'Ungültiges API-Ziel.']);
+ exit;
+}
+
+// 4. Ziel-URL mit API-Schlüssel zusammensetzen
+$separator = (strpos($apiUrl, '?') !== false) ? '&' : '?';
+$fullApiUrl = $apiUrl . $separator . 'key=' . $apiKey;
+
+// 5. Anfrage mit cURL an Google API senden
+$ch = curl_init();
+
+curl_setopt_array($ch, [
+ CURLOPT_URL => $fullApiUrl,
+ CURLOPT_RETURNTRANSFER => true,
+ CURLOPT_POST => true,
+ CURLOPT_POSTFIELDS => json_encode($payload),
+ CURLOPT_HTTPHEADER => [
+ 'Content-Type: application/json',
+ ],
+ CURLOPT_TIMEOUT => 90,
+]);
+
+$response_body = curl_exec($ch);
+$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
+
+if (curl_errno($ch)) {
+ http_response_code(500);
+ echo json_encode(['error' => 'Fehler bei Weiterleitung an Google: ' . curl_error($ch)]);
+ exit;
+}
+
+curl_close($ch);
+
+http_response_code($http_code);
+echo $response_body;
+?>
diff --git a/dinos/auth.php b/dinos/auth.php
index 840f793..812819e 100644
--- a/dinos/auth.php
+++ b/dinos/auth.php
@@ -5,6 +5,15 @@
* Führt den Google Login durch und speichert den Token.
*/
+$current_project = 'dinos';
+require_once __DIR__ . '/../auth.php';
+
+// Nur Administratoren dürfen Google OAuth Konten verknüpfen
+if (!isset($_SESSION['is_admin']) || $_SESSION['is_admin'] !== true) {
+ header('Location: /');
+ exit();
+}
+
require_once 'google_helper.php';
// Konfiguration
diff --git a/dinos/index.php b/dinos/index.php
index 0d44e53..ba49f6f 100644
--- a/dinos/index.php
+++ b/dinos/index.php
@@ -16,25 +16,6 @@ $dailyLimitEco = 100; // Eco (Flash) etwa 3-4 Cent pro Bild
$dailyLimitPro = 10; // Pro (Imagen 4) etwa 3-4 Cent pro Bild
$dailyLimitUltra = 10; // Ultra (Gemini 3) etwa 12 Cent pro Bild
-// API-Key sicher aus .env laden
-$apiKey = '';
-$envFiles = [__DIR__ . '/.env', __DIR__ . '/../home/.env'];
-foreach ($envFiles as $envFile) {
- if (file_exists($envFile)) {
- foreach (file($envFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) as $line) {
- $line = trim($line);
- if ($line === '' || $line[0] === '#') continue;
- if (strpos($line, '=') !== false) {
- list($k, $v) = explode('=', $line, 2);
- if (trim($k) === 'GEMINI_API_KEY') {
- $apiKey = trim(trim($v), '"\'');
- break 2;
- }
- }
- }
- }
-}
-
// API Modelle (hier zentral ändern, wenn Versionen veralten) siehe apis.php
$modelText = "gemini-2.5-flash"; // Für Fakten und Zufallsgenerator
$modelImageEco = "gemini-2.5-flash-image"; // ECO Modus
@@ -316,7 +297,6 @@ $totalUltra = $currentStats['total_ultra'];
-
-
-
-
-
-
-
-
-
-
-
-
-
- User:
-
-
-
- 🦕
-
- Dino Wissenskarten
-
-
-
Generiere fotorealistische Bilder und entdecke spannende Fakten.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
![Vorschau]()
-
-
- MODE
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 🦖
-
-
Tippe einen Dino-Namen ein und schau zu, was passiert.
-
-
-
-
-
-
-
-
-
-
-
-