= 70300) { session_set_cookie_params([ 'samesite' => 'Strict', 'httponly' => true, 'secure' => !empty($_SERVER['HTTPS']) ]); } session_start(); header('X-Frame-Options: DENY'); header('X-Content-Type-Options: nosniff'); if (!empty($_SERVER['HTTPS'])) { header('Strict-Transport-Security: max-age=31536000; includeSubDomains'); } header('Content-Type: text/html; charset=utf-8'); function csrf_token() { if (empty($_SESSION['csrf_token'])) { $_SESSION['csrf_token'] = bin2hex(random_bytes(32)); } return $_SESSION['csrf_token']; } function check_csrf() { $token = $_POST['csrf_token'] ?? ''; if (!isset($_SESSION['csrf_token']) || !hash_equals($_SESSION['csrf_token'], $token)) { die('CSRF token无效,请刷新页面重试。'); } } function smtp_mail($to, $subject, $body) { $to = filter_var($to, FILTER_VALIDATE_EMAIL); if (!$to) return false; $host = (SMTP_PORT == 465 ? 'ssl://' : '') . SMTP_HOST; $socket = @fsockopen($host, SMTP_PORT, $errno, $errstr, 30); if (!$socket) return false; stream_set_timeout($socket, 30); $line = fgets($socket, 515); if (substr($line, 0, 3) != '220') { fclose($socket); return false; } fputs($socket, "EHLO localhost\r\n"); $line = fgets($socket, 515); while (substr($line, 3, 1) == '-') $line = fgets($socket, 515); if (substr($line, 0, 3) != '250') { fclose($socket); return false; } fputs($socket, "AUTH LOGIN\r\n"); if (substr(fgets($socket, 515), 0, 3) != '334') { fclose($socket); return false; } fputs($socket, base64_encode(SMTP_USER) . "\r\n"); if (substr(fgets($socket, 515), 0, 3) != '334') { fclose($socket); return false; } fputs($socket, base64_encode(SMTP_PASS) . "\r\n"); if (substr(fgets($socket, 515), 0, 3) != '235') { fclose($socket); return false; } fputs($socket, "MAIL FROM: <" . SMTP_USER . ">\r\n"); if (substr(fgets($socket, 515), 0, 3) != '250') { fclose($socket); return false; } fputs($socket, "RCPT TO: <$to>\r\n"); if (substr(fgets($socket, 515), 0, 3) != '250') { fclose($socket); return false; } fputs($socket, "DATA\r\n"); if (substr(fgets($socket, 515), 0, 3) != '354') { fclose($socket); return false; } $subject = '=?UTF-8?B?' . base64_encode($subject) . '?='; $headers = "MIME-Version: 1.0\r\nContent-type: text/html;charset=utf-8\r\nFrom: =?UTF-8?B?" . base64_encode('Minecraft社区') . "?= <" . SMTP_USER . ">\r\n"; $msg = $headers . "\r\n" . wordwrap($body, 70, "\r\n", true); fputs($socket, $msg . "\r\n.\r\n"); if (substr(fgets($socket, 515), 0, 3) != '250') { fclose($socket); return false; } fputs($socket, "QUIT\r\n"); fclose($socket); return true; } function send_code_mail($to, $subject, $body) { return smtp_mail($to, $subject, $body); } try { $pdo = new PDO("mysql:host=" . DB_HOST . ";charset=utf8", DB_USER, DB_PASS); $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $pdo->exec("CREATE DATABASE IF NOT EXISTS `" . DB_NAME . "`"); $pdo->exec("USE `" . DB_NAME . "`"); $pdo->exec("CREATE TABLE IF NOT EXISTS users ( id INT AUTO_INCREMENT PRIMARY KEY, username VARCHAR(50) NULL UNIQUE, email VARCHAR(255) UNIQUE NOT NULL, password VARCHAR(255) NOT NULL, avatar VARCHAR(255) DEFAULT 'default.png', role ENUM('user','admin','super') DEFAULT 'user', member_expire TIMESTAMP NULL DEFAULT NULL, last_sign_date DATE NULL, sign_count INT DEFAULT 0, banned TINYINT(1) DEFAULT 0, ban_reason VARCHAR(255) NULL, banned_at TIMESTAMP NULL DEFAULT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP )"); $res = $pdo->query("SHOW COLUMNS FROM users LIKE 'username'"); if ($res->rowCount() == 0) $pdo->exec("ALTER TABLE users ADD COLUMN username VARCHAR(50) NULL UNIQUE AFTER id"); $res = $pdo->query("SHOW COLUMNS FROM users LIKE 'avatar'"); if ($res->rowCount() == 0) $pdo->exec("ALTER TABLE users ADD COLUMN avatar VARCHAR(255) DEFAULT 'default.png'"); $res = $pdo->query("SHOW COLUMNS FROM users LIKE 'member_expire'"); if ($res->rowCount() == 0) $pdo->exec("ALTER TABLE users ADD COLUMN member_expire TIMESTAMP NULL DEFAULT NULL"); $res = $pdo->query("SHOW COLUMNS FROM users LIKE 'last_sign_date'"); if ($res->rowCount() == 0) $pdo->exec("ALTER TABLE users ADD COLUMN last_sign_date DATE NULL"); $res = $pdo->query("SHOW COLUMNS FROM users LIKE 'sign_count'"); if ($res->rowCount() == 0) $pdo->exec("ALTER TABLE users ADD COLUMN sign_count INT DEFAULT 0"); $res = $pdo->query("SHOW COLUMNS FROM users LIKE 'banned'"); if ($res->rowCount() == 0) { $pdo->exec("ALTER TABLE users ADD COLUMN banned TINYINT(1) DEFAULT 0"); $pdo->exec("ALTER TABLE users ADD COLUMN ban_reason VARCHAR(255) NULL"); $pdo->exec("ALTER TABLE users ADD COLUMN banned_at TIMESTAMP NULL DEFAULT NULL"); } $pdo->exec("CREATE TABLE IF NOT EXISTS email_codes (id INT AUTO_INCREMENT PRIMARY KEY, email VARCHAR(255), code VARCHAR(10), expire INT)"); $pdo->exec("CREATE TABLE IF NOT EXISTS client_intro (id INT PRIMARY KEY DEFAULT 1, content TEXT, download_link TEXT)"); $stmt = $pdo->query("SELECT * FROM client_intro WHERE id=1"); if (!$stmt->fetch()) $pdo->exec("INSERT INTO client_intro VALUES(1,'欢迎下载我的世界客户端,体验原版生存乐趣。','#')"); $pdo->exec("CREATE TABLE IF NOT EXISTS guilds (id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(100), intro TEXT, leader VARCHAR(100), senior_members TEXT, created_by INT, FOREIGN KEY(created_by) REFERENCES users(id) ON DELETE SET NULL)"); $pdo->exec("CREATE TABLE IF NOT EXISTS guild_applies (id INT AUTO_INCREMENT PRIMARY KEY, guild_id INT, user_id INT, reason TEXT, status ENUM('pending','approved','rejected') DEFAULT 'pending', applied_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY(guild_id) REFERENCES guilds(id) ON DELETE CASCADE, FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE)"); $pdo->exec("CREATE TABLE IF NOT EXISTS posts (id INT AUTO_INCREMENT PRIMARY KEY, user_id INT, title VARCHAR(200), content TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE)"); $pdo->exec("CREATE TABLE IF NOT EXISTS replies (id INT AUTO_INCREMENT PRIMARY KEY, post_id INT, user_id INT, content TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY(post_id) REFERENCES posts(id) ON DELETE CASCADE, FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE)"); $pdo->exec("CREATE TABLE IF NOT EXISTS client_files (id INT AUTO_INCREMENT PRIMARY KEY, filename VARCHAR(255), origin_name VARCHAR(255), uploaded_by INT, upload_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP)"); $pdo->exec("CREATE TABLE IF NOT EXISTS community_music (id INT AUTO_INCREMENT PRIMARY KEY, filename VARCHAR(255) NOT NULL, origin_name VARCHAR(255) NOT NULL, uploaded_by INT, upload_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY(uploaded_by) REFERENCES users(id) ON DELETE SET NULL)"); $stmt = $pdo->prepare("SELECT id FROM users WHERE email=? AND role='super'"); $stmt->execute([SUPER_USER]); if (!$stmt->fetch()) { $hash = password_hash(SUPER_PASS, PASSWORD_DEFAULT); $pdo->prepare("INSERT INTO users(username,email,password,role) VALUES('SuperAdmin',?,?,'super')")->execute([SUPER_USER, $hash]); } } catch (PDOException $e) { die("数据库错误: " . $e->getMessage()); } function is_logged() { return isset($_SESSION['user_id']); } function is_admin() { return isset($_SESSION['role']) && ($_SESSION['role'] == 'admin' || $_SESSION['role'] == 'super'); } function is_super() { return isset($_SESSION['role']) && $_SESSION['role'] == 'super'; } function is_member($pdo) { if (!is_logged()) return false; $stmt = $pdo->prepare("SELECT member_expire FROM users WHERE id=?"); $stmt->execute([$_SESSION['user_id']]); $row = $stmt->fetch(); return $row && $row['member_expire'] && strtotime($row['member_expire']) > time(); } function go($url) { header("Location: $url"); exit; } function h($s) { return htmlspecialchars($s, ENT_QUOTES, 'UTF-8'); } function strong_pwd($p) { return strlen($p) >= 6 && !preg_match('/^\d+$/', $p) && !preg_match('/^(.)\1+$/', $p); } function captcha_generate() { $width = 120; $height = 45; $img = imagecreatetruecolor($width, $height); $bg = imagecolorallocate($img, mt_rand(220, 255), mt_rand(220, 255), mt_rand(220, 255)); imagefilledrectangle($img, 0, 0, $width, $height, $bg); $chars = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789'; $code = ''; for ($i = 0; $i < 5; $i++) $code .= $chars[random_int(0, strlen($chars) - 1)]; $_SESSION['captcha'] = $code; for ($i = 0; $i < mt_rand(3, 5); $i++) { $c = imagecolorallocate($img, mt_rand(100, 200), mt_rand(100, 200), mt_rand(100, 200)); imageline($img, mt_rand(0, $width), mt_rand(0, $height), mt_rand(0, $width), mt_rand(0, $height), $c); } for ($i = 0; $i < mt_rand(200, 300); $i++) { $c = imagecolorallocate($img, mt_rand(0, 200), mt_rand(0, 200), mt_rand(0, 200)); imagesetpixel($img, mt_rand(0, $width), mt_rand(0, $height), $c); } $x = 10; for ($i = 0; $i < 5; $i++) { $c = imagecolorallocate($img, mt_rand(0, 100), mt_rand(0, 100), mt_rand(0, 100)); imagestring($img, 5, $x, mt_rand(10, 28), $code[$i], $c); $x += 20; } header('Content-Type: image/png'); imagepng($img); imagedestroy($img); } $act = $_GET['action'] ?? 'home'; if ($act === 'captcha') { captcha_generate(); exit; } // 网易云音乐 API if ($act === 'search_music') { $keyword = trim($_GET['keyword'] ?? ''); if (empty($keyword)) { echo json_encode(['code' => 400, 'msg' => '请输入关键词']); exit; } $url = 'https://api.uomg.com/api/search.music?key=' . urlencode($keyword); $ch = curl_init(); curl_setopt_array($ch, [ CURLOPT_URL => $url, CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 10, CURLOPT_USERAGENT => 'Mozilla/5.0', CURLOPT_SSL_VERIFYPEER => true, CURLOPT_SSL_VERIFYHOST => 2 ]); $resp = curl_exec($ch); curl_close($ch); if ($resp === false) { echo json_encode(['code' => 500, 'msg' => '请求失败']); } else { $data = json_decode($resp, true); if (isset($data['code']) && $data['code'] == 200 && isset($data['data']['list'])) { $songs = []; foreach ($data['data']['list'] as $item) { $songs[] = ['id' => $item['id'], 'name' => $item['name'], 'artists' => [['name' => $item['artists']]]]; } echo json_encode(['code' => 200, 'result' => ['songs' => $songs]]); } else { echo json_encode(['code' => 500, 'msg' => '搜索无结果或格式错误']); } } exit; } if ($act === 'get_music_url') { $song_id = (int)($_GET['id'] ?? 0); if (!$song_id) { echo json_encode(['code' => 400, 'msg' => '缺少歌曲ID']); exit; } $url = 'https://api.uomg.com/api/music.163?id=' . $song_id; $ch = curl_init(); curl_setopt_array($ch, [ CURLOPT_URL => $url, CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 10, CURLOPT_USERAGENT => 'Mozilla/5.0', CURLOPT_SSL_VERIFYPEER => true, CURLOPT_SSL_VERIFYHOST => 2 ]); $resp = curl_exec($ch); curl_close($ch); if ($resp === false) { echo json_encode(['code' => 500, 'msg' => '获取播放链接失败']); } else { $data = json_decode($resp, true); if (isset($data['code']) && $data['code'] == 200 && isset($data['data']['url'])) { echo json_encode(['code' => 200, 'url' => $data['data']['url']]); } else { echo json_encode(['code' => 500, 'msg' => '无法获取播放地址']); } } exit; } // 签到 if ($act === 'sign' && is_logged()) { $uid = $_SESSION['user_id']; $today = date('Y-m-d'); $stmt = $pdo->prepare("SELECT last_sign_date, sign_count, member_expire FROM users WHERE id=?"); $stmt->execute([$uid]); $u = $stmt->fetch(); if ($u && $u['last_sign_date'] === $today) { $_SESSION['error'] = '今天已签到,请明天再来!'; go('?action=home'); } $yesterday = date('Y-m-d', strtotime('-1 day')); $new_count = 1; if ($u && $u['last_sign_date'] === $yesterday) $new_count = $u['sign_count'] + 1; $reward = false; if ($new_count >= 5) { $new_count = 0; $reward = true; } $pdo->prepare("UPDATE users SET last_sign_date=?, sign_count=? WHERE id=?")->execute([$today, $new_count, $uid]); if ($reward) { $pdo->prepare("UPDATE users SET member_expire = IFNULL(member_expire, NOW()) + INTERVAL 7 DAY WHERE id=?")->execute([$uid]); $_SESSION['success'] = "签到成功!连续签到5天,获得7天会员!"; } else { $_SESSION['success'] = "签到成功!已连续签到 {$new_count} 天。"; } go('?action=home'); } // 删除帖子/回复 if ($act === 'delete_post' && is_logged()) { $pid = (int)$_GET['id']; $stmt = $pdo->prepare("SELECT user_id, created_at FROM posts WHERE id=?"); $stmt->execute([$pid]); $post = $stmt->fetch(); if (!$post) { $_SESSION['error'] = '帖子不存在'; } elseif ($post['user_id'] != $_SESSION['user_id']) { $_SESSION['error'] = '无权删除'; } elseif (strtotime($post['created_at']) < time() - 86400) { $_SESSION['error'] = '超过24小时,无法删除'; } else { $pdo->prepare("DELETE FROM posts WHERE id=?")->execute([$pid]); $_SESSION['success'] = '帖子已删除'; } go('?action=forum'); } if ($act === 'delete_reply' && is_logged()) { $rid = (int)$_GET['id']; $stmt = $pdo->prepare("SELECT user_id, post_id, created_at FROM replies WHERE id=?"); $stmt->execute([$rid]); $rep = $stmt->fetch(); if (!$rep) { $_SESSION['error'] = '回复不存在'; } elseif ($rep['user_id'] != $_SESSION['user_id']) { $_SESSION['error'] = '无权删除'; } elseif (strtotime($rep['created_at']) < time() - 86400) { $_SESSION['error'] = '超过24小时,无法删除'; } else { $pdo->prepare("DELETE FROM replies WHERE id=?")->execute([$rid]); $_SESSION['success'] = '回复已删除'; } go('?action=view_post&id=' . $rep['post_id']); } // 上传头像 if ($act === 'upload_avatar' && is_logged()) { check_csrf(); $dir = __DIR__ . '/uploads/avatars/'; if (!is_dir($dir)) mkdir($dir, 0755, true); if (!isset($_FILES['avatar']) || $_FILES['avatar']['error'] !== UPLOAD_ERR_OK) { $_SESSION['error'] = '上传失败'; go('?action=profile'); } $tmp = $_FILES['avatar']['tmp_name']; $info = getimagesize($tmp); $allowed = [IMAGETYPE_JPEG, IMAGETYPE_PNG, IMAGETYPE_GIF]; if (!$info || !in_array($info[2], $allowed)) { $_SESSION['error'] = '只允许 JPG/PNG/GIF 图片'; go('?action=profile'); } if ($_FILES['avatar']['size'] > 2 * 1024 * 1024) { $_SESSION['error'] = '文件不能超过2MB'; go('?action=profile'); } $ext = image_type_to_extension($info[2], false); $filename = 'avatar_' . $_SESSION['user_id'] . '.' . $ext; if (move_uploaded_file($tmp, $dir . $filename)) { $pdo->prepare("UPDATE users SET avatar=? WHERE id=?")->execute([$filename, $_SESSION['user_id']]); $_SESSION['success'] = '头像更新成功'; } else { $_SESSION['error'] = '保存失败'; } go('?action=profile'); } // 封禁/解封 if (($act === 'ban_user' || $act === 'unban_user') && is_admin()) { check_csrf(); $uid = (int)($_POST['user_id'] ?? 0); if (!$uid) { $_SESSION['error'] = '未指定用户'; go('?action=admin'); } if ($uid == $_SESSION['user_id']) { $_SESSION['error'] = '不能操作自己'; go('?action=admin'); } $stmt = $pdo->prepare("SELECT role FROM users WHERE id=?"); $stmt->execute([$uid]); $target = $stmt->fetch(); if (!$target) { $_SESSION['error'] = '用户不存在'; go('?action=admin'); } if (!is_super() && $target['role'] !== 'user') { $_SESSION['error'] = '权限不足'; go('?action=admin'); } if ($act === 'ban_user') { $reason = trim($_POST['ban_reason'] ?? ''); $pdo->prepare("UPDATE users SET banned=1, ban_reason=?, banned_at=NOW() WHERE id=?")->execute([$reason, $uid]); $_SESSION['success'] = '用户已封禁'; } else { $pdo->prepare("UPDATE users SET banned=0, ban_reason=NULL, banned_at=NULL WHERE id=?")->execute([$uid]); $_SESSION['success'] = '用户已解封'; } go('?action=admin'); } // 添加/去除管理员 if ($act === 'add_admin' && is_super()) { check_csrf(); $email = trim($_POST['email'] ?? ''); $stmt = $pdo->prepare("UPDATE users SET role='admin' WHERE email=? AND role='user'"); $stmt->execute([$email]); if ($stmt->rowCount()) { $_SESSION['success'] = "已将 $email 设为管理员"; } else { $_SESSION['error'] = '用户不存在或已是管理员'; } go('?action=superadmin'); } if ($act === 'remove_admin' && is_super()) { check_csrf(); $email = trim($_POST['email'] ?? ''); $stmt = $pdo->prepare("SELECT id FROM users WHERE email=? AND role='admin'"); $stmt->execute([$email]); $t = $stmt->fetch(); if (!$t) { $_SESSION['error'] = '该管理员不存在或已非管理员'; } elseif ($t['id'] == $_SESSION['user_id']) { $_SESSION['error'] = '不能去除自己的超级管理员身份'; } else { $pdo->prepare("UPDATE users SET role='user' WHERE id=?")->execute([$t['id']]); $_SESSION['success'] = "已将 $email 的管理员身份移除"; } go('?action=superadmin'); } // 上传社区音乐 if ($act === 'upload_music' && is_admin()) { if ($_SERVER['REQUEST_METHOD'] !== 'POST' || !isset($_FILES['music_file'])) { go('?action=admin'); } check_csrf(); $dir = __DIR__ . '/uploads/music/'; if (!is_dir($dir)) { mkdir($dir, 0755, true); file_put_contents($dir . '.htaccess', "Deny from all\n"); } $origin = $_FILES['music_file']['name']; $ext = strtolower(pathinfo($origin, PATHINFO_EXTENSION)); $allowed = ['mp3', 'wav', 'ogg', 'flac', 'm4a', 'aac']; if (!in_array($ext, $allowed)) { $_SESSION['error'] = '不支持的音频格式'; go('?action=admin'); } if ($_FILES['music_file']['size'] > 10 * 1024 * 1024) { $_SESSION['error'] = '文件不能超过10MB'; go('?action=admin'); } $newname = 'music_' . bin2hex(random_bytes(8)) . '.' . $ext; if (move_uploaded_file($_FILES['music_file']['tmp_name'], $dir . $newname)) { $pdo->prepare("INSERT INTO community_music (filename, origin_name, uploaded_by) VALUES (?, ?, ?)")->execute([$newname, $origin, $_SESSION['user_id']]); $_SESSION['success'] = '音乐上传成功'; } else { $_SESSION['error'] = '上传失败,请检查目录权限'; } go('?action=admin'); } // 删除公会 if ($act === 'delete_guild' && is_admin()) { check_csrf(); $gid = (int)($_POST['guild_id'] ?? 0); if (!$gid) { $_SESSION['error'] = '未指定公会'; go('?action=admin'); } $stmt = $pdo->prepare("DELETE FROM guilds WHERE id=?"); $stmt->execute([$gid]); if ($stmt->rowCount()) { $_SESSION['success'] = '公会已删除'; } else { $_SESSION['error'] = '公会不存在'; } go('?action=admin'); } // 修改用户名 if ($act === 'change_username' && is_logged()) { check_csrf(); $newName = trim($_POST['new_username'] ?? ''); if (empty($newName) || mb_strlen($newName) > 50) { $_SESSION['error'] = '用户名不能为空且不超过50字符'; go('?action=profile'); } $stmt = $pdo->prepare("SELECT username FROM users WHERE id=?"); $stmt->execute([$_SESSION['user_id']]); $current = $stmt->fetch(); if ($current['username'] === $newName) { $_SESSION['error'] = '新用户名与当前相同'; go('?action=profile'); } $stmt = $pdo->prepare("SELECT id FROM users WHERE username=? AND id != ?"); $stmt->execute([$newName, $_SESSION['user_id']]); if ($stmt->fetch()) { $_SESSION['error'] = '该用户名已被占用'; go('?action=profile'); } $pdo->prepare("UPDATE users SET username=? WHERE id=?")->execute([$newName, $_SESSION['user_id']]); $_SESSION['success'] = '用户名修改成功'; go('?action=profile'); } // 注册/登录等 if ($act == 'do_register') { check_csrf(); $username = trim($_POST['username'] ?? ''); $email = trim($_POST['email'] ?? ''); $pwd = $_POST['password'] ?? ''; $captcha = $_POST['captcha'] ?? ''; $code = $_POST['email_code'] ?? ''; if (strtoupper($captcha) != $_SESSION['captcha']) { $_SESSION['error'] = '图形验证码错误'; go('?action=register'); } $stmt = $pdo->prepare("SELECT * FROM email_codes WHERE email=? AND code=? AND expire>?"); $stmt->execute([$email, $code, time()]); if (!$stmt->fetch()) { $_SESSION['error'] = '邮箱验证码错误或过期'; go('?action=register'); } $stmt = $pdo->prepare("SELECT id FROM users WHERE email=?"); $stmt->execute([$email]); if ($stmt->fetch()) { $_SESSION['error'] = '邮箱已注册'; go('?action=register'); } if (empty($username)) { $_SESSION['error'] = '用户名不能为空'; go('?action=register'); } $stmt = $pdo->prepare("SELECT id FROM users WHERE username=?"); $stmt->execute([$username]); if ($stmt->fetch()) { $_SESSION['error'] = '用户名已被占用'; go('?action=register'); } if (!strong_pwd($pwd)) { $_SESSION['error'] = '密码至少6位,不能纯数字或单一重复'; go('?action=register'); } $hash = password_hash($pwd, PASSWORD_DEFAULT); $pdo->prepare("INSERT INTO users(username, email, password, role) VALUES(?,?,?,'user')")->execute([$username, $email, $hash]); $_SESSION['success'] = '注册成功,请登录'; go('?action=login'); } if ($act == 'send_email_code') { $email = $_GET['email'] ?? ''; if (!filter_var($email, FILTER_VALIDATE_EMAIL)) die('invalid'); $limitKey = 'send_code_' . $email . '_' . $_SERVER['REMOTE_ADDR']; if (isset($_SESSION[$limitKey]) && $_SESSION[$limitKey] > time() - 60) die('rate_limit'); $code = random_int(100000, 999999); $pdo->prepare("REPLACE INTO email_codes (email, code, expire) VALUES(?,?,?)")->execute([$email, $code, time() + 300]); $ok = send_code_mail($email, '【Minecraft】注册验证码', "您的验证码:$code,有效期5分钟。"); if ($ok) $_SESSION[$limitKey] = time(); echo $ok ? 'ok' : 'fail'; exit; } if ($act == 'do_login') { check_csrf(); $email = $_POST['email'] ?? ''; $pwd = $_POST['password'] ?? ''; $stmt = $pdo->prepare("SELECT id, password, role, banned FROM users WHERE email=?"); $stmt->execute([$email]); $user = $stmt->fetch(); if (!$user || !password_verify($pwd, $user['password'])) { $_SESSION['error'] = '账号或密码错误'; go('?action=login'); } if ($user['banned']) { $_SESSION['error'] = '该账号已被封禁,请联系管理员。'; go('?action=login'); } session_regenerate_id(true); $_SESSION['user_id'] = $user['id']; $_SESSION['role'] = $user['role']; $_SESSION['success'] = '登录成功'; go('?action=home'); } if ($act == 'logout') { session_destroy(); go('?action=home'); } if ($act == 'add_guild' && is_admin()) { check_csrf(); $name = trim($_POST['name'] ?? ''); $intro = trim($_POST['intro'] ?? ''); $leader = trim($_POST['leader'] ?? ''); $senior = trim($_POST['senior_members'] ?? ''); if ($name) { $pdo->prepare("INSERT INTO guilds (name, intro, leader, senior_members, created_by) VALUES(?,?,?,?,?)")->execute([$name, $intro, $leader, $senior, $_SESSION['user_id']]); $_SESSION['success'] = '公会添加成功'; } else { $_SESSION['error'] = '公会名称不能为空'; } go('?action=admin'); } if ($act == 'apply_guild') { if (!is_logged()) go('?action=login'); check_csrf(); $gid = (int)($_POST['guild_id'] ?? 0); $reason = trim($_POST['reason'] ?? ''); $stmt = $pdo->prepare("SELECT 1 FROM guild_applies WHERE guild_id=? AND user_id=? AND status='pending'"); $stmt->execute([$gid, $_SESSION['user_id']]); if ($stmt->fetch()) { $_SESSION['error'] = '已有待审核申请'; } else { $pdo->prepare("INSERT INTO guild_applies (guild_id, user_id, reason) VALUES(?,?,?)")->execute([$gid, $_SESSION['user_id'], $reason]); $_SESSION['success'] = '申请已提交,等待审核'; } go('?action=guild_detail&id=' . $gid); } if ($act == 'review_apply' && is_admin()) { check_csrf(); $aid = (int)($_GET['apply_id'] ?? 0); $status = $_GET['status'] ?? ''; if (in_array($status, ['approved', 'rejected'])) { $pdo->prepare("UPDATE guild_applies SET status=? WHERE id=?")->execute([$status, $aid]); $_SESSION['success'] = '审核完成'; } go('?action=admin'); } if ($act == 'edit_client_intro' && is_super()) { check_csrf(); $content = $_POST['content'] ?? ''; $link = $_POST['download_link'] ?? ''; $pdo->prepare("UPDATE client_intro SET content=?, download_link=? WHERE id=1")->execute([$content, $link]); $_SESSION['success'] = '客户端介绍已更新'; go('?action=client'); } if ($act == 'upload_file' && is_super() && isset($_FILES['client_file'])) { check_csrf(); $dir = __DIR__ . '/uploads/'; if (!is_dir($dir)) mkdir($dir, 0755, true); $origin = $_FILES['client_file']['name']; $ext = strtolower(pathinfo($origin, PATHINFO_EXTENSION)); $allowed = ['zip', 'rar', '7z', 'jar', 'exe', 'dmg', 'msi', 'deb', 'tar', 'gz']; if (!in_array($ext, $allowed)) { $_SESSION['error'] = '不允许的文件类型'; go('?action=superadmin'); } $newname = 'client_' . time() . '.' . $ext; if (move_uploaded_file($_FILES['client_file']['tmp_name'], $dir . $newname)) { $pdo->prepare("INSERT INTO client_files (filename, origin_name, uploaded_by) VALUES(?,?,?)")->execute([$newname, $origin, $_SESSION['user_id']]); $_SESSION['success'] = '文件上传成功'; } else { $_SESSION['error'] = '上传失败'; } go('?action=superadmin'); } if ($act == 'new_post' && is_logged()) { check_csrf(); $title = trim($_POST['title'] ?? ''); $content = trim($_POST['content'] ?? ''); if ($title && $content) { $pdo->prepare("INSERT INTO posts (user_id, title, content) VALUES(?,?,?)")->execute([$_SESSION['user_id'], $title, $content]); } else { $_SESSION['error'] = '标题内容不能为空'; } go('?action=forum'); } if ($act == 'reply' && is_logged()) { check_csrf(); $pid = (int)($_POST['post_id'] ?? 0); $content = trim($_POST['content'] ?? ''); if ($content) { $pdo->prepare("INSERT INTO replies (post_id, user_id, content) VALUES(?,?,?)")->execute([$pid, $_SESSION['user_id'], $content]); } go('?action=view_post&id=' . $pid); } ?>
今日已签到 ✅ | 连续签到 = $us['sign_count'] ?> 天
点击签到连续签到 = $us['sign_count'] ?> 天,再签到 = 5 - $us['sign_count'] ?> 天可得7天会员
time()): ?>VIP 到期:= date('Y-m-d H:i', strtotime($us['member_expire'])) ?>
邮箱:= h($u['email']) ?>
会员到期:= $u['member_expire'] ? date('Y-m-d H:i', strtotime($u['member_expire'])) : '无' ?>
签到天数:= $u['sign_count'] ?>天
VIP用户名长度为1-50个字符,且不能与他人重复。
官方下载链接:点击下载客户端
= nl2br(h($g['intro'])) ?>
公会不存在
= nl2br(h(mb_substr($post['content'], 0, 120))) ?>...
帖子不存在
prepare("SELECT r.*, u.username, u.avatar FROM replies r JOIN users u ON r.user_id=u.id WHERE r.post_id=? ORDER BY r.created_at ASC"); $replies->execute([$pid]); ?>= nl2br(h($post['content'])) ?>
= nl2br(h($rep['content'])) ?>
暂无社区音乐,管理员快来上传吧~
| 用户名 | 邮箱 | 角色 | 状态 | 操作 |
|---|---|---|---|---|
| = h($u['username']) ?> | = h($u['email']) ?> | = $roleText ?> | = $banned ? '封禁' : '正常' ?> | 自己- |
| 公会名称 | 会长 | 操作 |
|---|---|---|
| = h($g['name']) ?> | = h($g['leader']) ?> |
暂无公会
| 原文件名 | 保存名 | 上传时间 |
|---|---|---|
| = h($f['origin_name']) ?> | = h($f['filename']) ?> | = $f['upload_time'] ?> |
页面未找到,返回 首页