setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); } catch(PDOException $e) { die("数据库连接失败: " . $e->getMessage()); } if (!file_exists('uploads')) { mkdir('uploads', 0755, true); file_put_contents('uploads/index.html', ''); file_put_contents('uploads/.htaccess', 'Deny from all'); } if (!file_exists('languages')) mkdir('languages', 0755, true); if (!file_exists('admin')) mkdir('admin', 0755, true); if (!file_exists('components')) mkdir('components', 0755, true); if (!file_exists('api')) mkdir('api', 0755, true); function getLanguage() { global $supported_languages; if (isset($_SESSION['language'])) { return $_SESSION['language']; } if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) { $browser_lang = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2); if ($browser_lang === 'zh') return 'zh-CN'; if ($browser_lang === 'en') return 'en'; } return DEFAULT_LANGUAGE; } function loadLanguage($lang) { $lang_file = "languages/{$lang}.php"; if (file_exists($lang_file)) { return include $lang_file; } return include "languages/" . DEFAULT_LANGUAGE . ".php"; } $lang = getLanguage(); $translations = loadLanguage($lang); $_SESSION['language'] = $lang; function t($key) { global $translations; return $translations[$key] ?? $key; } function getUserSettings($user_id) { global $pdo; $stmt = $pdo->prepare("SELECT * FROM user_settings WHERE user_id = ?"); $stmt->execute([$user_id]); $settings = $stmt->fetch(PDO::FETCH_ASSOC); if (!$settings) { $stmt = $pdo->prepare("INSERT INTO user_settings (user_id) VALUES (?)"); $stmt->execute([$user_id]); return [ 'dark_mode' => false, 'language' => 'zh-CN', 'items_per_page' => 20, 'email_notifications' => true, 'browser_notifications' => true ]; } return $settings; } function updateUserSettings($user_id, $settings) { global $pdo; $stmt = $pdo->prepare("INSERT INTO user_settings (user_id, dark_mode, language, items_per_page, email_notifications, browser_notifications) VALUES (?, ?, ?, ?, ?, ?) ON DUPLICATE KEY UPDATE dark_mode = VALUES(dark_mode), language = VALUES(language), items_per_page = VALUES(items_per_page), email_notifications = VALUES(email_notifications), browser_notifications = VALUES(browser_notifications)"); return $stmt->execute([ $user_id, $settings['dark_mode'] ? 1 : 0, $settings['language'], $settings['items_per_page'], $settings['email_notifications'] ? 1 : 0, $settings['browser_notifications'] ? 1 : 0 ]); } function getUserNotificationSettings($user_id) { global $pdo; $stmt = $pdo->prepare("SELECT nt.name, uns.enabled FROM user_notification_settings uns JOIN notification_types nt ON uns.notification_type_id = nt.id WHERE uns.user_id = ?"); $stmt->execute([$user_id]); $settings = $stmt->fetchAll(PDO::FETCH_KEY_PAIR); if (empty($settings)) { initUserNotificationSettings($user_id); return getUserNotificationSettings($user_id); } return $settings; } function initUserNotificationSettings($user_id) { global $pdo; $stmt = $pdo->prepare("INSERT INTO user_notification_settings (user_id, notification_type_id, enabled) SELECT ?, id, TRUE FROM notification_types"); return $stmt->execute([$user_id]); } function updateUserNotificationSettings($user_id, $settings) { global $pdo; foreach ($settings as $type_id => $enabled) { $stmt = $pdo->prepare("INSERT INTO user_notification_settings (user_id, notification_type_id, enabled) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE enabled = VALUES(enabled)"); $stmt->execute([$user_id, $type_id, $enabled ? 1 : 0]); } return true; } function sendNotification($user_id, $type_name, $title, $message, $related_url = null) { global $pdo; $stmt = $pdo->prepare("SELECT uns.enabled FROM user_notification_settings uns JOIN notification_types nt ON uns.notification_type_id = nt.id WHERE uns.user_id = ? AND nt.name = ?"); $stmt->execute([$user_id, $type_name]); $setting = $stmt->fetch(PDO::FETCH_ASSOC); if (!$setting || !$setting['enabled']) return false; $stmt = $pdo->prepare("SELECT id FROM notification_types WHERE name = ?"); $stmt->execute([$type_name]); $type = $stmt->fetch(PDO::FETCH_ASSOC); if (!$type) return false; $stmt = $pdo->prepare("INSERT INTO notifications (user_id, type_id, title, message, related_url) VALUES (?, ?, ?, ?, ?)"); return $stmt->execute([$user_id, $type['id'], $title, $message, $related_url]); } function getUnreadNotificationCount($user_id) { global $pdo; $stmt = $pdo->prepare("SELECT COUNT(*) as count FROM notifications WHERE user_id = ? AND is_read = FALSE"); $stmt->execute([$user_id]); return $stmt->fetch(PDO::FETCH_ASSOC)['count']; } function getUserNotifications($user_id, $limit = 10) { global $pdo; $stmt = $pdo->prepare("SELECT n.*, nt.name as type_name FROM notifications n JOIN notification_types nt ON n.type_id = nt.id WHERE n.user_id = ? ORDER BY n.created_at DESC LIMIT ?"); $stmt->bindValue(1, $user_id, PDO::PARAM_INT); $stmt->bindValue(2, $limit, PDO::PARAM_INT); $stmt->execute(); return $stmt->fetchAll(PDO::FETCH_ASSOC); } function generateRandomString($length = 10) { return substr(str_shuffle(str_repeat($x = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', ceil($length / strlen($x)))), 1, $length); } function formatFileSize($bytes) { if ($bytes >= 1073741824) return number_format($bytes / 1073741824, 2) . ' GB'; elseif ($bytes >= 1048576) return number_format($bytes / 1048576, 2) . ' MB'; elseif ($bytes >= 1024) return number_format($bytes / 1024, 2) . ' KB'; else return $bytes . ' bytes'; } function getBingDailyImage() { $response = @file_get_contents(BING_API_URL); if ($response) { $data = json_decode($response, true); if ($data && isset($data['images'][0])) { $image = $data['images'][0]; return [ 'url' => 'https://www.bing.com' . $image['url'], 'title' => $image['title'], 'copyright' => $image['copyright'], 'copyrightlink' => $image['copyrightlink'] ]; } } return null; } function sendEmail($to, $subject, $message) { $mail = new PHPMailer(true); try { // 服务器设置 $mail->isSMTP(); $mail->Host = SMTP_HOST; $mail->SMTPAuth = true; $mail->Username = SMTP_USERNAME; $mail->Password = SMTP_PASSWORD; $mail->SMTPSecure = SMTP_SECURE; $mail->Port = SMTP_PORT; if (SMTP_DEBUG) { $mail->SMTPDebug = SMTP::DEBUG_SERVER; } // 收件人 $mail->setFrom(SMTP_FROM_EMAIL, SMTP_FROM_NAME); $mail->addAddress($to); // 内容 $mail->isHTML(true); $mail->Subject = $subject; $mail->Body = $message; $mail->AltBody = strip_tags($message); return $mail->send(); } catch (Exception $e) { error_log("邮件发送失败: " . $mail->ErrorInfo); return false; } } function sendVerificationEmail($email, $username, $verification_code) { $verification_link = SITE_URL . "/verify.php?code=" . $verification_code; $subject = SITE_NAME . " - 邮箱验证"; $message = "

" . SITE_NAME . "

亲爱的 {$username},

感谢您注册" . SITE_NAME . "图床!

请点击下面的按钮验证您的邮箱地址:

验证邮箱

如果按钮无法点击,请复制以下链接到浏览器地址栏:

{$verification_link}

此验证链接 24 小时内有效。

"; return sendEmail($email, $subject, $message); } function sendPasswordResetEmail($email, $username, $token) { $reset_link = SITE_URL . "/reset-password.php?token=" . $token; $subject = SITE_NAME . " - 密码重置"; $message = "

" . SITE_NAME . " - 密码重置

亲爱的 {$username},

我们收到了您重置密码的请求。

请点击下面的按钮重置您的密码:

重置密码

如果按钮无法点击,请复制以下链接到浏览器地址栏:

{$reset_link}

注意:此链接在 1 小时内有效。如果您没有请求重置密码,请忽略此邮件。
"; return sendEmail($email, $subject, $message); } function sendEmailNotification($user_id, $subject, $message) { global $pdo; // 获取用户邮箱和设置 $stmt = $pdo->prepare(" SELECT u.email, us.email_notifications FROM users u LEFT JOIN user_settings us ON u.id = us.user_id WHERE u.id = ? "); $stmt->execute([$user_id]); $user = $stmt->fetch(PDO::FETCH_ASSOC); if (!$user || !$user['email_notifications']) { return false; } return sendEmail($user['email'], $subject, $message); } $currentUserSettings = isset($_SESSION['user_id']) ? getUserSettings($_SESSION['user_id']) : [ 'dark_mode' => false, 'language' => $lang, 'items_per_page' => 20, 'email_notifications' => true, 'browser_notifications' => true ]; if (!isset($_SESSION['user_id'])) { $currentUserSettings['dark_mode'] = isset($_COOKIE['dark_mode']) ? (bool)$_COOKIE['dark_mode'] : false; $currentUserSettings['language'] = $lang; } ?>