Xiuno BBS 重构记录贴(十八)插件兼容扫描器

插件兼容性扫描器

概述

插件兼容性扫描器用于检测已安装插件中与 Xiuno BBS 4.5+ 现代化改造不兼容的代码,涵盖 PHP 8.0+ 语法、Bootstrap 5 迁移、jQuery 去除、安全规范等方面。

入口 :后台 → 插件管理 → 插件兼容性检查(/admin/?plugin-scanner.htm

相关文件

文件 说明
lib/PluginScanner.php 扫描器核心,定义规则与扫描逻辑
admin/route/plugin_scanner.php 后台路由,处理扫描/导出请求
admin/view/htm/plugin_scanner.htm 扫描器页面模板
lang/zh-cn/bbs_admin.php 中文语言项(plugin_scanner_*
lang/en-us/bbs_admin.php 英文语言项

使用方式

  1. 进入后台「插件兼容性检查」页面
  2. 点击「开始扫描」按钮
  3. 前端通过 fetch() 请求 ?plugin-scanner-do.htm,后端返回 JSON 格式扫描结果
  4. 结果按插件分组展示,支持按严重级别筛选
  5. 可导出 CSV 报告

扫描范围

扫描 plugin/ 目录下所有包含 conf.json 的插件目录,递归检查以下扩展名的文件:

  • .php --- PHP 代码
  • .htm / .html --- 模板文件
  • .js --- JavaScript 脚本
  • .css --- 样式文件

自动跳过 img/images/fonts/ 目录。

规则类别

严重级别说明

级别 含义
fatal 致命:代码在 PHP 8.0+ 下会直接报错或崩溃
warning 警告:存在安全风险或功能异常
medium 中等:不兼容但不会直接崩溃,需要迁移
info 信息:建议优化,非必须

PHP 兼容性规则

废弃函数(PHP 7.x 移除)--- fatal

检测 mysql_* 系列函数及其他在 PHP 7.x 已移除的函数:

匹配模式 说明
mysql_connect 等 19 个 mysql 扩展已在 PHP 7.0 移除
each( PHP 7.2 废弃,8.0 移除
create_function( PHP 7.2 废弃,8.0 移除,用闭包替代
split( / spliti( PHP 7.0 移除,用 preg_split()explode()
ereg( / ereg_replace( PHP 7.0 移除,用 preg_match() / preg_replace()
call_user_method( PHP 7.0 移除,用 call_user_func()
PHP 8 不兼容语法 --- fatal
匹配模式 说明
&new 按引用创建对象已移除,改用 new
preg_replace.*\/e /e 修饰符已移除,用 preg_replace_callback()
花括号数组访问 --- fatal
匹配模式 说明
{$ {$arr['key']} 语法已移除,改用 [$arr['key']]
HTTP_*_VARS 变量 --- fatal
匹配模式 说明
HTTP_POST_VARS 已移除,用 $_POST / $_GET / $_SESSION
PHP 8.0+ 废弃函数 --- fatal
匹配模式 说明
get_magic_quotes_gpc PHP 7.4 废弃、8.0 移除,始终返回 false
get_magic_quotes_runtime PHP 7.4 废弃、8.0 移除
utf8_encode( PHP 8.2 废弃,用 mb_convert_encoding()
utf8_decode( PHP 8.2 废弃,用 mb_convert_encoding()
money_format( PHP 7.4 废弃、8.0 移除,用 NumberFormatter
is_resource( 对 PDO/MySQLi 对象返回 false(PHP 8.0+),改用 instanceof

安全规则

危险函数 --- warning
匹配模式 说明
eval( / system( / exec( 代码注入/命令执行风险,应避免使用
权限安全(敏感字段修改)--- warning
匹配模式 说明
user_update.*password 应使用 user_change_password()
user_update.*gid 应使用 user_change_group()
user_update.*salt salt 由系统自动管理,不应直接修改
user_update.*password_hash 应使用 user_change_password()
POST 表单缺少 CSRF 令牌 --- warning
匹配模式 说明
method="post" 但无 CsrfService / csrf_token 所有 POST 表单必须包含 CSRF 令牌

此规则采用文件级检测:读取整个文件内容,检查是否同时包含 method="post"CsrfService/csrf_token,若缺少则报告。

Bootstrap 迁移规则

BS4 旧类名 --- medium
匹配模式 替换建议
ml- ms-
mr- me-
pl- ps-
pr- pe-
form-group mb-3
custom-select form-select
custom-control form-check
btn-block w-100
input-group-prepend / input-group-append 直接 input-group-text
BS4 旧 data 属性 --- medium
匹配模式 替换建议
data-toggle data-bs-toggle
data-dismiss data-bs-dismiss
data-target data-bs-target
data-slide-to data-bs-slide-to
data-slide data-bs-slide
BS3 旧类名 --- medium
匹配模式 替换建议
panel-heading card-header
panel-body card-body
panel-footer card-footer
panel-default card + 颜色
well card .card-body 或自定义样式
glyphicon Tabler Icons ti-*
pull-left float-start
pull-right float-end
hidden-xs d-none .d-sm-block
visible-xs d-sm-none
label-default badge .bg-*
img-responsive img-fluid
img-circle rounded-circle
img-rounded rounded
col-xs- col-(xs 断点已移除)
Bootstrap jQuery 插件调用 --- warning
匹配模式 替换建议
.modal( new bootstrap.Modal()
.dropdown( new bootstrap.Dropdown()
.tooltip( new bootstrap.Tooltip()
.popover( new bootstrap.Popover()
.collapse( new bootstrap.Collapse()
.carousel( new bootstrap.Carousel()
.alert( new bootstrap.Alert()
.button( new bootstrap.Button()
.tab( new bootstrap.Tab()

前端迁移规则

jQuery 使用 --- medium
匹配模式 替换建议
$.ajax( htmx 或原生 fetch
$.post( htmx hx-post 或原生 fetch
$.get( htmx hx-get 或原生 fetch
$.each( Array.forEach()
$.fn. Alpine.js 组件
$.extend( Object.assign()
$.trim( String.trim()
$.parseJSON( JSON.parse()
$.isArray( Array.isArray()
$.isFunction( typeof fn === "function"
$.browser 特性检测
$(document).ready DOMContentLoaded
$(function( DOMContentLoaded
jQuery( htmx + Alpine.js
Fontello 旧图标 --- medium
匹配模式 替换建议
icon-lock ti-lock
icon-home ti-home
icon-edit ti-pencil
icon-remove ti-trash
icon-eye ti-eye
icon-ok ti-check
icon-cog / icon-cogs ti-settings
icon-comment ti-message
icon-user ti-user
icon-envelope ti-mail
icon-key ti-key
icon-star ti-star
非 Tabler Icons 图标库 --- medium
匹配模式 说明
fa- Font Awesome 图标 → Tabler Icons ti-*
bi- Bootstrap Icons → Tabler Icons ti-*
glyphicon- Glyphicon 图标 → Tabler Icons ti-*

代码规范规则

直接数据库操作 --- info
匹配模式 说明
db_exec( / db_update( / db_insert( / db_delete( / db_find( / db_create( / db_drop( 建议使用 model 层封装

此规则排除 install.phpuninstall.phpunstall.phpupgrade.php 文件(安装/升级脚本中直接操作数据库是合理的)。

其他规则

conf.json 版本检查 --- info

检查 conf.jsonbbs_version 字段,若 < 4.5 则提示更新。

Hook 文件名检查 --- info

检查 hook/ 目录下文件名是否符合 [a-z_][a-z0-9_]* 命名规范。

特殊处理逻辑

missing_csrf(跨行检测)

POST 表单的 CSRF 检测不能逐行匹配,因为 method="post"CsrfService::input() 可能分布在文件不同位置。因此采用文件级检测:

  1. 读取整个文件内容
  2. 检查是否包含 method="post"
  3. 若包含,再检查是否包含 CsrfServicecsrf_token
  4. 仅当 POST 表单存在且缺少 CSRF 令牌时才报告

direct_db(文件名排除)

安装/升级脚本中直接操作数据库是合理的,因此排除以下文件:

  • install.php
  • uninstall.php
  • unstall.php(Xiuno 旧版拼写)
  • upgrade.php

API 接口

扫描请求

ruby 复制代码
GET /admin/?plugin-scanner-do.htm

返回 JSON 数组,每个元素代表一个插件的扫描结果:

json 复制代码
[
  {
    "dir": "xn_tag",
    "name": "标签",
    "version": "1.0",
    "bbs_version": "4.0",
    "installed": true,
    "enable": true,
    "issues": [
      {
        "file": "plugin/xn_tag/hook/post_js.htm",
        "line": 15,
        "category": "jquery_usage",
        "match": "$.ajax(",
        "suggestion": "使用 htmx 或原生 fetch 替代 $.ajax",
        "severity": "medium",
        "context": "$.ajax({url: '...'})"
      }
    ],
    "total": 3,
    "fatal": 0,
    "warning": 1
  }
]

CSV 导出

arduino 复制代码
GET /admin/?plugin-scanner-export.htm

下载 CSV 文件,包含所有插件的扫描结果。

指定插件导出

bash 复制代码
GET /admin/?plugin-scanner-export.htm&dir=xn_tag

仅导出指定插件的扫描结果。

扩展规则

如需添加新的扫描规则,编辑 lib/PluginScanner.php

  1. $rules 数组中添加新类别和匹配模式
  2. $severityLevels 数组中添加严重级别映射
  3. getCategoryName() 方法的 $names 数组中添加中文名称
  4. lang/zh-cn/bbs_admin.phplang/en-us/bbs_admin.php 中添加 plugin_scanner_cat_* 语言项

如需特殊处理逻辑(如跨行检测、文件名排除),在 scanPluginDir() 方法中添加相应代码。

相关推荐
神奇小汤圆1 小时前
阿里面试官:什么才是可工程化落地的RAG项目
后端
ZPYZTech1 小时前
用 Wails + Go + Vue3 开发桌面软件,聊聊踩过的坑
后端
好家伙VCC2 小时前
区块链双向支付通道实战:从签名到结算
java·后端·区块链·asp.net
我登哥MVP3 小时前
Spring Boot 从“会用”到“精通”:参数解析原理
java·spring boot·后端·spring·servlet·maven·intellij-idea
JustHappy4 小时前
古法编程秘籍(五):什么是进程和线程?从软件到 CPU 的一次完整旅程
前端·后端·代码规范
BLSxiaopanlaile4 小时前
关于常见 map的一些比较探究
后端
花大师4 小时前
基于深度学习的鼠标轨迹真实性检测系统
后端
小江的记录本5 小时前
【Spring全家桶】Spring Cloud 2023.0.x:微服务核心理论、CAP/BASE定理(附《思维导图》+《面试高频考点清单》)
java·spring boot·后端·spring·spring cloud·微服务·面试