36 lines
1.3 KiB
PHP
36 lines
1.3 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
session_start();
|
|
|
|
const DB_HOST = '127.0.0.1';
|
|
const DB_NAME = 'three_words_10th';
|
|
const DB_USER = 'root';
|
|
const DB_PASS = '';
|
|
|
|
try {
|
|
$pdo = new PDO(
|
|
'mysql:host=' . DB_HOST . ';dbname=' . DB_NAME . ';charset=utf8mb4',
|
|
DB_USER,
|
|
DB_PASS,
|
|
[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC]
|
|
);
|
|
} catch (PDOException $e) {
|
|
http_response_code(500);
|
|
exit('資料庫連線失敗,請先啟動 XAMPP MySQL 並匯入 setup.sql。');
|
|
}
|
|
|
|
function e(?string $value): string { return htmlspecialchars($value ?? '', ENT_QUOTES, 'UTF-8'); }
|
|
function loggedIn(): bool { return isset($_SESSION['admin_id']); }
|
|
function requireLogin(): void { if (!loggedIn()) { header('Location: login.php'); exit; } }
|
|
function csrf(): string {
|
|
if (empty($_SESSION['csrf'])) $_SESSION['csrf'] = bin2hex(random_bytes(24));
|
|
return $_SESSION['csrf'];
|
|
}
|
|
function checkCsrf(): void {
|
|
if (!hash_equals($_SESSION['csrf'] ?? '', $_POST['csrf'] ?? '')) exit('表單驗證失敗');
|
|
}
|
|
function youtubeId(string $url): string {
|
|
if (preg_match('~(?:youtu\.be/|youtube\.com/(?:watch\?v=|embed/|shorts/))([\w-]{11})~', $url, $m)) return $m[1];
|
|
return preg_match('/^[\w-]{11}$/', $url) ? $url : '';
|
|
}
|