diff --git a/adminer/index.php b/adminer/index.php index 547cfea..f398c9a 100644 --- a/adminer/index.php +++ b/adminer/index.php @@ -255,6 +255,96 @@ try { } } + // Datensatz löschen + if ($_SERVER['REQUEST_METHOD'] === 'POST' && (string)($_POST['action'] ?? '') === 'delete_row') { + $delTable = (string)($_POST['table'] ?? ''); + $pkCol = (string)($_POST['pk_col'] ?? ''); + $pkVal = (string)($_POST['pk_val'] ?? ''); + + if (!preg_match('/^[A-Za-z0-9_]+$/', $delTable) || !preg_match('/^[A-Za-z0-9_]+$/', $pkCol)) { + $msg = ['ok' => false, 'text' => 'Ungültige Parameter für Löschen.']; + } else { + try { + // PK-Spalte gegen echte PK-Spalte validieren + $realPk = admin_get_primary_key_column($pdo, $delTable); + if ($realPk === null || $realPk !== $pkCol) { + $msg = ['ok' => false, 'text' => 'Löschen ist nur über eine echte Primary-Key-Spalte möglich.']; + } else { + $stmt = $pdo->prepare('DELETE FROM `' . $delTable . '` WHERE `' . $pkCol . '` = :v LIMIT 1'); + $stmt->execute([':v' => $pkVal]); + $msg = ['ok' => true, 'text' => 'Datensatz gelöscht.']; + + // Wenn wir gerade diese Tabelle anzeigen: auf Seite 1 zurück, damit man nicht auf leerer Seite landet + if ($table === $delTable) { + $page = 1; + $offset = 0; + } + } + } catch (Throwable $e) { + $msg = ['ok' => false, 'text' => $e->getMessage()]; + } + } + } + + // Datensatz hinzufügen + if ($_SERVER['REQUEST_METHOD'] === 'POST' && (string)($_POST['action'] ?? '') === 'insert_row') { + $insTable = (string)($_POST['table'] ?? ''); + if (!preg_match('/^[A-Za-z0-9_]+$/', $insTable)) { + $msg = ['ok' => false, 'text' => 'Ungültiger Tabellenname für Insert.']; + } else { + try { + $colsMeta = admin_get_table_columns($pdo, $insTable); + if (empty($colsMeta)) { + $msg = ['ok' => false, 'text' => 'Keine Spalten gefunden.']; + } else { + $fields = []; + foreach ($colsMeta as $c) { + $name = (string)$c['Field']; + // Nur Spalten zulassen, die wirklich existieren + if (!array_key_exists('col_' . $name, $_POST)) continue; + + $raw = (string)($_POST['col_' . $name] ?? ''); + $isNull = ((string)($_POST['null_' . $name] ?? '') === '1'); + + $fields[] = [ + 'name' => $name, + 'value' => $isNull ? null : ($raw === '' ? null : $raw), + 'forceNull' => $isNull, + ]; + } + + // Leere Submits verhindern + if (empty($fields)) { + $msg = ['ok' => false, 'text' => 'Keine Felder zum Einfügen übergeben.']; + } else { + $colNames = []; + $placeholders = []; + $params = []; + + foreach ($fields as $f) { + $colNames[] = '`' . $f['name'] . '`'; + $ph = ':c_' . $f['name']; + $placeholders[] = $ph; + $params[$ph] = $f['value']; + } + + $sql = 'INSERT INTO `' . $insTable . '` (' . implode(',', $colNames) . ') VALUES (' . implode(',', $placeholders) . ')'; + $stmt = $pdo->prepare($sql); + $stmt->execute($params); + $msg = ['ok' => true, 'text' => 'Datensatz hinzugefügt.']; + + // Nach Insert wieder zur Tabelle springen + $table = $insTable; + $page = 1; + $offset = 0; + } + } + } catch (Throwable $e) { + $msg = ['ok' => false, 'text' => $e->getMessage()]; + } + } + } + $tables = $pdo->query('SHOW TABLES')->fetchAll(PDO::FETCH_NUM); // ── TOP BAR ────────────────────────────────────────────────────────── @@ -305,18 +395,70 @@ try { if (!preg_match('/^[A-Za-z0-9_]+$/', $table)) { $body .= '
Ungültiger Tabellenname.
'; } else { + $pkCol = admin_get_primary_key_column($pdo, $table); $stmt = $pdo->query('SELECT * FROM `' . $table . '` LIMIT ' . (int)$limit . ' OFFSET ' . (int)$offset); $rows = $stmt->fetchAll(); $body .= '
'; - $body .= '

' . h($table) . '

'; - $body .= admin_render_table($rows); + $body .= '
' + . '

' . h($table) . '

' + . '+ Datensatz' + . '
'; + + $body .= admin_render_table($rows, $table, $pkCol); + $body .= ''; + $body .= '
'; + + // Add form + if ((string)($_GET['add'] ?? '') === '1') { + $colsMeta = admin_get_table_columns($pdo, $table); + $body .= '
'; + $body .= '

Datensatz hinzufügen

'; + $body .= '
' + . '' + . ''; + + foreach ($colsMeta as $c) { + $col = (string)$c['Field']; + $extra = (string)($c['Extra'] ?? ''); + $nullOk = ((string)($c['Null'] ?? 'NO') === 'YES'); + + // auto_increment standardmäßig nicht anfassen + if (stripos($extra, 'auto_increment') !== false) { + $body .= '
' + . '' + . '' + . '
'; + continue; + } + + $body .= '
' + . '' + . ''; + + if ($nullOk) { + $body .= '
' + . '' + . '' + . '
'; + } + + $body .= '
'; + } + + $body .= '
' + . '' + . 'Abbrechen' + . '
' + . '
'; + $body .= '
'; + } } } @@ -345,13 +487,17 @@ try { ); } -function admin_render_table(array $rows): string +function admin_render_table(array $rows, string $table = '', ?string $pkCol = null): string { if (empty($rows)) return '

(keine Zeilen)

'; $cols = array_keys((array)$rows[0]); + $hasActions = ($table !== '' && $pkCol !== null && in_array($pkCol, $cols, true)); + $html = '
'; foreach ($cols as $c) $html .= ''; + if ($hasActions) $html .= ''; + $html .= ''; foreach ($rows as $r) { $html .= ''; @@ -362,9 +508,50 @@ function admin_render_table(array $rows): string : (strlen((string)$v) > 300 ? h(substr((string)$v, 0, 300)) . '…' : h((string)$v)); $html .= ''; } + + if ($hasActions) { + $pkVal = $r[$pkCol] ?? null; + $safePkVal = $pkVal === null ? '' : (string)$pkVal; + + $html .= ''; + } + $html .= ''; } $html .= '
' . h((string)$c) . 'Aktionen
' . $cell . '' + . '
' + . '' + . '' + . '' + . '' + . '' + . '
' + . '
'; return $html; } +function admin_get_primary_key_column(PDO $pdo, string $table): ?string +{ + if (!preg_match('/^[A-Za-z0-9_]+$/', $table)) return null; + + $stmt = $pdo->prepare( + "SELECT COLUMN_NAME\n" + . "FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE\n" + . "WHERE TABLE_SCHEMA = DATABASE()\n" + . " AND TABLE_NAME = :t\n" + . " AND CONSTRAINT_NAME = 'PRIMARY'\n" + . "ORDER BY ORDINAL_POSITION\n" + . "LIMIT 1" + ); + $stmt->execute([':t' => $table]); + $pk = $stmt->fetchColumn(); + return $pk !== false ? (string)$pk : null; +} + +function admin_get_table_columns(PDO $pdo, string $table): array +{ + if (!preg_match('/^[A-Za-z0-9_]+$/', $table)) return []; + $stmt = $pdo->query('SHOW COLUMNS FROM `' . $table . '`'); + $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); + return is_array($rows) ? $rows : []; +}