XIUNOX 更新日志 2026-08-20 [复制链接]

管理员组

[xnx_home_block] 1.0.0 → 1.0.4

  • 修复 bbs_xnx_home_block_slide 表缺失导致安装默认数据和后台轮播管理新增项均报 SQLSTATE[42S02]:根因是 MySQL 将未加反引号的 rank 判为保留关键字,建表 SQL 在该字段处报 1064;install.phpupgrade.php 均改为反引号引用字段和联合索引。upgrade.php 同时提供幂等建表与空表默认轮播初始化;安装路径在建表失败时记录错误、回滚插件状态并中止。

  • 优化首页区块:移除轮播左右控制区,改为不依赖 Bootstrap 初始化时机的原生稳定自动播放;重做圆点指示器;帖子列表仅保留作者和时间;帖子/会员 Tab 选中圆角为 3px,会员卡片底部内边距为 0;新增“移动端显示帖子列表”后台开关并同步默认设置、三语言包与前台样式;核心 static_version 递增至 1.4.192。


[xnx_quiz] v1.1.1

  • 修复设置页“基本设置”与“认证联动”两个 Tab 共用 op=save_settings 保存分支,互相把未提交字段重置为默认值(表现为开关互斥、保存后过段时间被覆盖);拆分为 save_settings / save_linkage 各自只更新本表单字段。


[xnx_quest] 1.4.3 → 1.4.17

1.4.3 → 1.4.4

  • 修复前后台积分类型名称未随后台配置读取的问题:奖励显示与表单标签统一改用核心标准键 credits_label/golds_label/rmb_label(index.inc.php 已用后台积分名称动态覆盖),移除插件自有固定键 quest_reward_credits/golds/rmbsquest_admin_reward_credits/golds/rmbs(三语言包同步清理)。

1.4.5

  • 任务管理页“获得勋章”事件无法指定具体勋章(恒显示“需启用 xnx_medal 插件”)。根因:setting.php 用 plugin_paths_enabled() 的数组 key(完整路径)直接与目录名 xnx_medal 比较,恒不相等;改用 file_name() 转目录名后匹配(与 NavService 一致)。

1.4.6 → 1.4.7

  • 设置头像任务改为“非默认头像即发放”:新增 QuestService::syncAvatarEvent 被动同步(进任务中心/我的任务页时按 user.avatar 字段判定:0=默认不补发,<0 预设/>0 自定义上传均自动补发 avatar_upload 事件),头像上传 hook 放宽为上传成功即触发(不再限制仅首次),解决任务开启前已设置头像的老用户任务永远卡在“去完成”的问题。

  • “去完成”跳转按任务 event_params 精确定位:获得勋章任务配置了指定勋章时跳该勋章详情页(medal-<id>,未配置仍跳勋章墙),发帖任务配置了指定版块时跳该版块发帖页(thread-create-<fid>),回帖/点赞任务配置了指定版块时跳该版块页(forum-<fid>)。

1.4.7 → 1.4.8

  • 修复任务中心/我的任务/后台审核页三个 Modal 的“取消”按钮显示 lang[quest_admin_cancel] 字面量的问题:模板引用了该语言键但三个语言包均未定义,lang() 找不到键时返回字面量;已补齐定义(取消/取消/Cancel)。

1.4.8 → 1.4.9

  • 前置条件交互重构:前置任务未完成/勋章条件不满足时,任务卡片常驻红色警告行(锁定图标 + 未满足前置条件 + 具体原因“需完成任务:xxx”/“需持有勋章:xxx”),申请/去完成/提交审核/领取奖励按钮全部禁用为“未满足前置条件”,已完成/审核中状态不受影响。

  • 修复“有前置任务的任务申请后没进后台仍显示申请”的困惑:后端 checkPrerequisites 正确拦截(申请未写库故后台无记录),但前端无预检、失败 toast 一闪而过,用户误以为提交成功;现卡片渲染时预检(quest_card.inc.htm 顶部,仅配置了 prereq 字段的任务查库),不满足直接锁定按钮从源头杜绝无效提交。

  • 后端补齐绕过路径:onUserEvent 前置不满足跳过计数与自动发奖(任务未解锁语义)、submitCustomApplicationmanualClaim 均补前置校验(防直接 POST 绕过前端禁用)。

1.4.9 → 1.4.10

  • 修复审核任务被自动发奖绕过审核流程的严重 bug:onUserEvent 达标后原直接调 grantReward 从不检查 audit_enable——审核任务一旦事件触发(如勋章授予)奖励立即自动到账、completed=1,而后台申请还挂在待审核,发奖完全绕过管理员;现在审核任务达标后只推进 progress(卡片显示“申请”按钮),发奖唯一路径是 reviewApplication 审核通过。

  • manualClaimaudit_enable 拒绝(防直接 POST 绕过审核领取,新增语言键 quest_audit_claim_blocked 三语)。

  • 新增 syncMedalEvent 勋章被动同步:任务开启前已持有满足条件勋章的老用户因 grantMedal 对已持有者不重授、事件永远无法触发而死锁在“去完成”,现进任务中心/我的任务页时按当前持有勋章补发 medal_grant 事件(配置 medal_id 的任务须持有该勋章,未配置的持有任意勋章即可)。

  • 遗留脏数据提示:修复前被误发奖的任务 completed=1 且奖励已到账,后台对应 pending 申请可直接拒绝(拒绝无副作用)或管理员自行处置。

1.4.10 → 1.4.11

  • 日常任务跨天状态推导补全:日常任务重置是懒重置(下一次事件触发时才重置),跨天后未触发事件前 completed 仍为 1,任务中心/我的任务页显示“已完成”会让用户误以为今天不能再做。现卡片渲染时推导 $daily_redo(daily 类型 + completed=1 + progress_date 已跨天):普通任务显示“已完成(灰字)+ 可重做按钮(跳转目标与去完成一致,触发事件后自动重置重新计数)”,自定义任务显示“已完成 + 可重做徽章”;新增语言键 quest_daily_redo 三语。

1.4.11 → 1.4.12

  • 修复“我的任务”页(my-quest)提交审核申请无效:申请 Modal 的 hx-post/hx-target 初始化 JS 只存在于任务中心页(quest_index.htm 内联),quest_my.htm 渲染同名 Modal 但无任何初始化脚本,表单无 hx-post 属性触发浏览器原生提交(GET 当前页),申请从未写入 xnx_quest_application 表。修复:初始化逻辑统一移入 quest.jsinitApplyModal + waitBootstrap 轮询),POST 地址由两页各自注入 window.questPostUrlhx-target 仍按卡片 id 动态设置。

  • 移除 quest_index.htm 内联版 XN.toast 参数反序 bug(type/message 位置颠倒,与 quest.js 正确监听并存时显示错乱 toast),成功关 Modal 逻辑并入 quest.js 的 questApplyResult 监听。

1.4.12 → 1.4.13(安全审计修复)

  • reviewApplication 审核通过前重新校验前置条件(此前是全插件唯一无前置校验的发奖路径——申请提交后勋章被撤销 revokeMedal 物理删除无 hook,或 1.4.9 之前无校验时期提交的存量 pending 申请,管理员点通过即发奖)。

  • checkPrerequisites 改 fail-closed(xnx_medal 未启用/MedalService 加载失败时勋章前置由静默放行改为拦截)。

  • 后台审核页 pending 申请实时显示“前置已满足/不满足”徽章(含原因 tooltip)。

  • 修复 xnx_quest_applicationUNIQUE KEY quest_uid_latest (quest_id,uid,status) 结构缺陷——同用户同任务第二次审核流转 UPDATE 撞历史唯一键致 CAS 失败、申请永久卡 pending,INSERT 撞键静默失败表现为“提交了但后台无记录”,改为普通索引 + 应用层防重(install.php 同步 + upgrade.php 幂等 DROP)。

  • 申请链路加临时调试日志(log/YYYYMM/quest_apply_error.php,定位后移除)。语言包三语新增 5 键。升级后需在后台触发升级执行表结构迁移。

1.4.13 → 1.4.14

  • 修复“勋章插件已启用却提示未启用”:checkPrerequisites/syncMedalEvent 原用 plugin_paths_enabled() 后以 $_pdir === "xnx_medal" 目录名比较,但该函数返回键是完整路径(/path/to/plugin/xnx_medal),比较恒 false——勋章前置校验永远报“勋章插件未启用”。新增 isMedalPluginEnabled() 私有方法直接查 db(plugin_db_get_all 键即目录名,enable+installed 双条件,请求级静态缓存,fail-closed),两处调用点统一替换。

1.4.14 → 1.4.15

  • 修复 POST 限流分支(60秒5次,申请/领取/步骤提交共享计数)两个缺陷——事件名原固定发 questRewardGranted(申请被限流时 toast 走错通道),现按 op 映射(apply→questApplyResult/submit_step→questStepResult);卡片渲染原缺 app_status 判断,审核任务被限流时恒回退显示“提交申请”按钮,现 op=apply 时按 has_pending 渲染 audit_pending/audit_available

  • 前端 quest.js 加 [quest] 前缀 console 全链路日志,新增 htmx:responseError 监听(此前 4xx/5xx 完全静默是排查盲区)。

  • 后端 route 限流触发写 xn_log(含 op/quest_id/计数)。调试代码定位后移除。

1.4.15 → 1.4.16

  • 修复申请提交走浏览器原生 GET 导致申请丢失(前端日志实锤根因):initApplyModal 在 bootstrap 就绪即执行,此时 htmx 可能尚未加载完,hx-post 设置失败且 data-quest-init 标志阻止重试——Modal 打开时仅补设 hx-target,表单无 hx-post 走浏览器原生 GET 提交(/?quest.html?op=apply&reason=... 页面跳转),后端 GET 分支不处理 op=apply,申请静默丢失。修复:hx-post/hx-swap/hx-target 统一移到 show.bs.modal 回调设置(每次打开幂等重设,htmx.process 幂等安全),初始化时保留 best effort 设置。

1.4.16 → 1.4.17

  • 修复 HX-Trigger 响应头中文乱码(ç³è¯·å·²æäº¤):PHP 端 json_encodeJSON_UNESCAPED_UNICODE 输出原始 UTF-8 中文字节到 header,前端 JSON.parse 后按 Latin-1 解释导致乱码。修复:6 处 HX-Trigger 头的 json_encode 去掉 JSON_UNESCAPED_UNICODE,中文转 \uXXXX 转义(纯 ASCII,header 安全,JS 解析后还原);模板内联 script 与 DB 写入的 8 处保留原样(UTF-8 上下文无此问题)。

  • 修复 csrf_token 残留 URL:1.4.16 前时序竞态 bug 的原生 GET 提交曾跳转到 /?quest.html?csrf_token=xxx&op=apply&reason=...,GET 分支忽略多余参数正常渲染导致用户一直停留在脏 URL(token 暴露在地址栏与历史)。修复:GET 分支开头检测 POST 专用 op(apply/claim/submit_step)时 http_location 302 到干净 url(quest),任何未来原生 GET 泄漏立即被带回干净 URL。


[xnx_adminlogin] 新增 1.0.0 → 1.0.2

1.0.0(前端部分)

  • 登录页 hook 注入验证码输入行(纯原生 JS,I18N/CFG 经 window 注入并逐键英文兜底,含发送间隔倒计时/IP 频率 wait/锁定 lock 处理)。

  • 后台设置页 setting.php/setting.htm(7 个字段 param 接收与模板控件双向核对一致,clamp 范围收敛,SMTP 未配置告警,邮件模板占位符实时预览)。

1.0.0(后端部分)

  • conf.json(hooks_rank 含 admin_index_login_end.htm 预登记)。

  • install/uninstall(默认设置幂等写入、log 目录创建、卸载清 setting+插件缓存+log 目录)。

  • MailCodeService:发码主流程(POST 限定/开关/CSRF 幂等/gid=1/ban_type/系统与插件锁定/密码预验/IP 间隔/SMTP/6 位码 random_int 写缓存/模板占位符替换邮件);verifyCode 返回 required|expired|error|TRUE

  • XnxAdminloginSecurityService:isLocked/lock/recordFail 阈值锁定/checkIpInterval/recordIpSend/audit 写 log/YYYYMM/xnx_adminlogin_audit.php。

  • model_inc_file 注册两个 Service。

  • admin_index_login_get_post hook:adminlogin_send Ajax 发码接口挂 index-login 内。

  • admin_index_login_post_end hook:验证码二次校验,失败回滚 $_SESSION[uid] + admin_token_clean,error 分支计数达阈值锁定并返回 lock 秒数。

  • 三语语言包 lang/ 与 hook/ 双写同键同值 18 键。

1.0.1

  • 修复已配置 SMTP 仍提示“邮件服务未配置”:xn_send_mail.func.php 不在框架自动加载列表,插件 Service 与 setting.php 上下文未加载导致 function_exists 判定失败;两处补 function_exists 守卫 + include_once 显式加载(参照 route/user.php 模式),并修复登录页发码潜在的 undefined function fatal。

1.0.2(安全审计加固)

  • 登录校验增加锁定前置检查(锁定期间验证环节完全冻结,杜绝锁定期试码窗口)。

  • 触发锁定时同步作废已发验证码缓存(旧码在锁定期间不得再作为通过凭证)。

  • 审计确认:前端隐藏/删除验证码输入框无法绕过服务端强制校验(拦截在编译期注入的 login POST 分支,与前端渲染无关)。


[xnx_login_as] 1.0.7 → 1.0.8

  • 修复结束模拟登录后“返回后台”跳转 URL 缺少 admin 前缀:end() 原用 admin_user_list_url()(内部经 route_url → url(),url()$_SERVER[SCRIPT_NAME] 上下文敏感),模拟登录会话运行在前台 index.php,$is_admin=false 生成 /?user-list.htm 落入前台路由。改用核心 admin_url("user-list")(专门从前台生成后台 URL,强制 ? 格式 + admin/ 前缀 + base_path),生成 /admin/?user-list.htm


核心:编译器加固

  • model/plugin.func.phpplugin_compile_srcfile_callback() 在拼接 hook 内容前,强制将 hook 内容中的 // hook xxx 注释改写为 // hook:xxx,将 <!--{hook xxx}--> 字符串改写为 [hook: xxx] 文字描述,破坏下一趟编译的正则匹配,避免 _include() 两趟编译机制将 hook 内容里的违规注释当作占位符再次拼接导致同一作用域静态变量重复声明。

  • plugin_compile_hooks() 循环加入 $s === $before break 检查,避免 strpos 命中但正则不匹配时的无效 10 趟循环。


安全:移除 DEBUG=3 超管免登录旁路

  • admin/index.inc.php 登录检查恢复无条件执行。

  • index.php 入口对 DEBUG 常量严格校验(仅允许 0/1/2),非法值输出配置错误页(三语支持),修复 DEBUG=3 进后台报 Undefined array key username 的问题。


工具:新增 CLI 管理员密码重置工具

  • tool/reset_password.php:仅 CLI 可运行,Web 拦截。落库逻辑对齐 user_change_password(bcrypt、清 md5、password_ver+1、删 api_token、清缓存),支持用户名/邮箱/uid 定位。

  • 新增站长教程:docs/userguide/reset-admin-password.md(邮箱找回/已登录修改/CLI 脚本/phpMyAdmin SQL 兜底四种途径)。


📦 版本总览

插件

版本变化

xnx_home_block

1.0.0 → 1.0.4

xnx_quiz

→ 1.1.1

xnx_quest

1.4.3 → 1.4.17

xnx_adminlogin

新增 1.0.2

xnx_login_as

1.0.7 → 1.0.8


⚠️ 升级提醒

  1. 编译器加固后,需清理 tmp/ 全部编译缓存。

  2. xnx_quest 1.4.13 含表结构变更(xnx_quest_application 索引调整),升级后需在后台触发升级执行迁移。

  3. xnx_adminlogin 为新插件,需在后台手动安装。

  4. DEBUG=3 已彻底移除,如有使用 define('DEBUG', 3) 的站点,请改为 0/1/2,否则前台将显示配置错误页。

  5. OPcachevalidate_timestamps=0 时,修改核心文件后需重启 PHP-FPM 或手动清 OPcache。

本回答由 AI 生成,内容仅供参考,请仔细甄别

最新回复
  • xiunox 一级用户组

    已阅读更新日志,几个修复经验很有价值:

    1. MySQL 对 rank 这类保留字需反引号,建议所有字段名统一加反引号,避免踩坑。
    2. plugin_paths_enabled() 返回的是完整路径,用目录名直接比较永远不相等,应该用 file_name() 提取目录名判断,这是插件开发常见隐含错误。
    3. HX-Trigger 响应头中文乱码,根因是 JSON_UNESCAPED_UNICODE 输出原始 UTF-8 字节到 header,应改成 \u 转义。
    4. htmx 初始化时序问题,在 show.bs.modal 回调里设置 hx-* 属性是稳妥做法。

    这些点对其他开发者很有参考价值。您是想分享经验,还是有具体问题需要深入讨论?【 AI 自动回复,仅供参考】

    21小时前

请先登录后再回复 登录