欢迎客人!
• 开始前请阅读社区规则确保您顺利的熟悉本社区。注册用户可以提交资源,如果您有已发布资源的新版本,您可以随时更新版本!
• 文件链接损坏请在文件下方留言,我们将会及时更新来自备份服务器的新链接。如有其它问题请 提交工单 和我们联系!【加入Telegram】【QQ群:5977983】
• 我们拥有多账户检测系统,对于重复注册我们将采取严厉措施!快速获得积分
你正在使用过时的浏览器,可能无法正确显示此网站或其他网站。
你应该升级浏览器或使用其他浏览器。
你应该升级浏览器或使用其他浏览器。
功能增加/修复清单
- XenForo 2.3 兼容性修复
- 修复 Call to undefined method XF::logModerator() 等 XF 2.3 API 变更导致的报错
- 替换/兼容旧用法:例如 \GuzzleHttp\json_encode、getEventRepo 等相关调用点
- “资源过期后下载控制”功能(XFRM)
- 新增三种过期后下载策略(后台可选)
- permanent_old_versions(默认):过期后仍可下载“过期前/有效期内发布”的旧版本
- no_download:过期后完全禁止下载
- grace_period:过期后宽限期内允许下载旧版本(可配置天数)
- 新增后台选项
- hnExpiredDownloadPolicy
- hnExpiredDownloadGraceDays
- 前台状态展示与按钮逻辑(XFRM 资源页)
- 新增/完善购买状态计算与展示:激活中、已过期但可下旧版、宽限期、已过期不可下载等
- 调整主按钮逻辑:过期用户显示购买/续费,而不是继续访问/下载
- 补充/修正相关短语与 XML 编码问题
- 历史版本页“逐版本下载权限”一致性(修复漏洞)
- 修复问题:过期后发布的新版本在历史版本页仍显示“下载”
- 实现方式:在 add-on 中直接覆盖 public:xfrm_resource_history 模板
- 模板侧实现逻辑
- 下载列显示:使用 canAccessHistoryDownloads()
- 每行下载按钮:使用 canDownloadVersion($versionId) 判断是否允许下载
- 处理模板导入限制
- 修正 xf:if 内不允许的结构
- 将模板可调用方法名改为 can* 前缀以满足白名单限制(从 hn* 调整为 canDownloadVersion() 等)
- 下载后端强校验(防直链绕过)
- 在版本下载 action 中增加版本级校验,防止仅靠 URL 直接下载绕过前台限制
- 统一使用资源的购买记录获取逻辑 getUserPurchaseRecord(),确保积分/真钱/手动授权路径一致
- 放行作者/具备绕过权限的用户(避免误伤)
- “旧版下载仍提示过期”的修复
- 修复根因:资源 canDownload() 之前固定按 current_version_id 做校验,下载旧版本也会被当作“当前版本”拦截
- 改为优先从请求参数读取“正在下载的版本 ID”(兼容 resource_version_id / version_id),再做版本级判断
- 前台历史页展示与后端下载校验逻辑统一
- 购买记录与版本门控算法修复/增强(积分 + 真钱 + 两者)
- 修复问题
- resource_version_id=0、真钱购买不记录版本等导致“过期仍可下载所有版本”的漏洞
- 版本 ID 与发布时间不严格单调时,用“ID 大小比较”会误判
- 新策略:统一按 ResourceVersion.release_date <= cutoff 判断
- cutoff 优先用 expire_date,否则用 purchase_date
- 积分购买与真钱购买实体均实现同一套“按发布时间门控”的判断方法,并修复真钱购买实体中的异常逻辑(曾存在重复 return 之类问题)
- phrases.xml 重复键值修复
- 清理 _data/phrases.xml 中重复的短语 title,保证导入/构建不再报“重复键值”
- 红包 openBonus 报错修复(游客 user_id=0)
- 修复问题:triggerEvent failed: Invalid target user ID: 0 / Bonus open failed for user #0
- 修复方式:在 actionOpenBonus() 开头强制要求登录($visitor->user_id > 0),游客直接返回“需要登录”,不会触发事件
![]()
![]()
![]()
![]()
![]()
修复的错误:
- [Service/Transfer/Handler.php:236] - 将不存在的 XF::logModerator() 改为正确的 \XF::app()->logger()->logModeratorAction()
- [Pub/Controller/Credit.php:271] - 将不存在的 \GuzzleHttp\json_encode() 改为标准 PHP 的 json_encode()
- [Pub/Controller/Credit.php:712] - 修复了调用不存在的 getEventRepo() 方法,改为使用 repository('HuoNiu\Credits:Event') 并添加了 getEventRepo() 辅助方法
其他验证通过的内容:
✅ XF::logError() - 正确方法
✅ XF::logException() - 正确方法
✅ XF:😛hrase() - 正确方法
✅ XF::db() - 正确方法
✅ XF:😱ptions() - 正确方法
✅ $this->app->stringFormatter() - 正确方法
✅ Controller 方法 (assertNotFlooding, assertValidCsrfToken, assertRecordExists 等) - 均为标准 XenForo 方法
本次更新项目总结
1.
- ✅ 为所有积分菜单选项添加Font Awesome图标
- 购买积分:fa-shopping-cart
- 账单:fa-file-invoice
- 交易大厅:fa-store
- 发送积分:fa-paper-plane
- 兑换:fa-exchange-alt
- 处罚:fa-gavel
2.
- ✅ 积分显示卡片化:使用CSS Grid网格布局,支持多货币展示
- ✅ 账单和交易大厅:2列网格,横排图标+文字布局
- ✅ 购买积分区域:全宽卡片,统一视觉风格
- ✅ 隐藏弹窗顶部"积分"标题文字
3.
- ✅ 使用XenForo CSS变量系统(适配明暗模式)
- var(--xf-contentAltBg) - 卡片背景
- var(--xf-paletteNeutral3) - hover状态
- var(--xf-textColorFeature) - 强调色
- var(--xf-borderRadiusMedium) - 圆角
- ✅ 统一卡片样式:圆角、内边距、hover动画、阴影效果
- ✅ 响应式设计:移动端自动单列布局
4.
- ✅ 设置积分图标透明度为0.6,与其他图标协调
- ✅ 添加hover效果:悬停时透明度变为1
5.
- ✅ 将购买积分从扩展点注入改为直接在模板定义
- ✅ 删除template_modifications.xml中的hn_paygate_wallet_popup注入
- ✅ 移除所有中文注释,保持代码整洁
6.
- templates.xml - hn_wallet_popup模板(主要弹窗UI)
- templates.xml - hn_credits_app_nav.less模板(导航图标样式)
- template_modifications.xml - 删除了购买积分的扩展点注入
7.
- 现代化卡片设计
- 平滑过渡动画
- 明暗模式自适应
- 整体视觉统一
🔧 1. 修复积分转账反垃圾检查错误
- 修复了 XF\SubContainer\Spam::checker() 不存在导致的致命错误
- 改用数据库查询实现防刷机制(10次/小时限制)
⚠️ 2. 购买记录完整迁移系统
问题: 旧版迁移工具只迁移用户积分和资源定价,不迁移购买记录,导致用户丢失已购资源的下载权限
解决方案:
迁移数据包括:
- ✅ 自动迁移 xf_mjrcp_resource_purchase → xf_hn_resource_purchase
- ✅ 保留所有购买历史记录
- ✅ 保留过期日期设置
- ✅ 支持用户继续下载已购资源
- ✅ 插件升级时自动执行,无需手动操作
- 购买用户ID
- 资源ID和版本ID
- 购买日期和过期日期
- 支付金额和净价
- 购买状态(active → purchased)
🌐 3. 迁移验证界面新增购买记录统计
- 显示购买记录总数
- 显示涉及用户数和资源数
- 显示迁移成功率
- 未迁移时显示红色警告提示
📋
迁移执行方式:
数据安全:
- 自动触发:插件升级时自动执行
- 手动触发:管理后台"迁移工具"页面查看状态
- 使用 INSERT IGNORE 防止重复迁移
- 完整日志记录迁移过程
- 事务保护确保数据一致性
🚀
本次更新包含迁移文档MD说明文件
- 上传新版插件文件
- 后台点击"升级"
- 系统自动迁移购买记录
- 用户无需任何操作,继续下载已购资源
增加的功能
1.
- ✅ 积分销售文件:创建 ResourcePurchase 记录
- ✅ 真实货币销售文件:创建/更新 ResourceMoneyPurchase 记录
- ✅ 同时支持两种 (both):智能判断创建类型
- ✅ 自定义过期时长:支持天/月/年单位
- ✅ 永久授权:设置0表示永久有效
- ✅ 更新已过期记录:不会报唯一键冲突
2.
- ✅ 积分购买:设置 purchase_status = 'revoked'
- ✅ 真实货币购买:设置 expire_date = 过去时间
- ✅ 同时撤销两种类型
- ✅ 记录撤销信息:revoked_by 和 revoked_date
3.
- ✅ 购买按钮逻辑:有任一购买记录则隐藏所有购买按钮
- ✅ 下载按钮显示:只显示1个下载按钮
- ✅ 过期时间显示:优先显示购买记录的实际过期时间
- ✅ 动态倒计时:实时计算剩余天数
- ✅ 智能单位:>=365天显示年,>=30天显示月
4.
- ✅ checkRequirePurchase():检查两种购买类型
- ✅ getUserActivePurchase():返回最新的有效购买记录
- ✅ canDownload():正确处理下载权限
- ✅ 过期自动失效:isActive() 方法验证
5.
- ✅ 权限控制:只有有 hnCredits 权限的管理员可操作
- ✅ 菜单集成:在资源"更多选项"中显示
- ✅ 用户搜索:支持自动完成
- ✅ 表单验证:用户存在性检查、重复授权检查
- ResourceItem.php - 表名修正
- content_type_fields.xml - 添加 content type 注册
- ResourcePurchase.php - 恢复通知功能
新增功能
- 资源过期时间单位支持 - 支持天/月/年三种单位(新增 hn_expiration_unit 字段)
Bug修复
- 表单字段名修复 - hn_expiration_amount → hn_expiration_days
- 单位字段接收 - Category.php 和 ResourceItem.php 控制器添加单位字段处理
- 过期权限验证 - getUserActivePurchase() 添加过期检查
优化改进
- 显示逻辑增强 - 根据单位动态显示 "购买后 X 天/月/年过期"
- 语言短语更新 - 支持 {amount} 和 {unit} 参数
数据库变更
- 新增字段:xf_rm_resource.hn_expiration_unit (VARCHAR(10), default='day')
- 自动升级:upgrade2031006Step1() 方法
一、管理后台修复(Admin Panel)
- 积分标签导航修复
- 位置:后台用户积分管理页面
- 问题:点击"积分"标签无法跳转
- 修复:添加 id="user-credits" 到标签元素
二、货币系统修复(Currency System)
- 货币列访问错误防护
- 位置:多个模板中的货币显示代码
- 问题:访问未启用的货币导致报错
- 修复:添加 $currency 存在性检查
- 影响范围:所有显示货币信息的模板
三、折扣系统修复(Discount System)
- 折扣计算逻辑修正
- 位置:折扣百分比计算代码
- 问题:折扣计算错误(使用 100-discount)
- 修复:改为直接使用 discount 值
- 示例:设置80折应显示80%而非20%
- 折扣显示同步
- 位置:前端显示与后端设置
- 问题:前后端折扣显示不一致
- 修复:统一折扣显示逻辑
- 折扣计算TypeError修复
- 位置:折扣计算表达式
- 问题:数值类型不匹配导致TypeError
- 修复:添加 float() 类型转换
四、红包系统全面改版(Red Envelope System)
- 红包卡片UI完全重设计
- 位置:templates.xml hn_bonus_list 模板(2105-2300行)
- 设计特点:
- 320px宽度红包卡片容器
- 顶部金色"福"字印章(带脉冲动画)
- 用户头像(中号,白色边框+金色光环+浮动动画)
- 发送者祝福语显示
- 大型金色"开"按钮(脉冲动画)
- 底部传统祝福文字
- 6种CSS3动画效果
- 响应式移动端支持
- 红包领取者头像修复
- 位置:红包卡片和领取者列表
- 问题:头像显示问号/问号方块
- 原因:模板使用 $user.TriggerUser 但实体只定义了 User 关系
- 修复:
- 将所有 $user.TriggerUser 改为 $user.User
- 添加 .purchaser-extra .avatar flexbox居中样式
- 红包相关语言国际化
- 位置:phrases.xml
- 移除硬编码:删除所有中文硬编码文本("福"、"恭喜发财 大吉大利"等)
- 新增语言键:
- hn_red_packet_seal_text: "福"
- hn_red_packet_blessing: "恭喜发财 大吉大利"
- hn_you_have_received_a_red_envelope: "您已经领过红包了"
- hn_red_packet_received_message: "领取了您的红包获得了"
- hn_you_have_already_sent_a_red_envelope: "您已经发过红包了"
- hn_red_packet_open: "开"
- 红包错误消息修正
- 位置:Post.php 第580行
- 问题:语言键名称错误
- 修复:hn_credits_you_have_received_a_red_envelope → hn_you_have_received_a_red_envelope
- 帖子列表红包标识
- 位置:template_modifications.xml 第192-210行
- 功能:
- 帖子标题后添加 🎁 礼物图标(Font Awesome fa-gift)
- 红色高亮(#ff6b6b)
- 16px尺寸
- 帖子状态区域也添加标识
- 目标模板:thread_list_macros
五、积分显示增强(Points Display)
- "您将收到"积分提示增强
- 位置:templates.xml 第4894行
- 元素ID:receive-amount-text
- 增强效果:
- 字号增大30%(font-size: 1.3em)
- 文字加粗(font-weight: bold)
- 绿色文字(#27ae60)
- 渐变背景(浅绿到白)
- 圆角边框(border-radius: 6px)
- 左侧绿色强调线(border-left: 4px solid)
- 内边距10px,上下边距8px
修复若干错误
增加兼容性规范
提升代码性能
- 添加了 protected $events = []; 属性声明
- 修复了 "Undefined property: $events" 错误
🔴 致命问题修复(4项)
| # | 问题类型 | 修复文件 | 修复内容 |
|---|---------|---------|---------|
| 1 | **SQL注入** | `Repository/Credit.php` | 添加 `validateCurrencyColumn()` 白名单验证,修复9个方法 |
| 2 | **并发竞态** | `Service/Transfer/Handler.php` | 添加 `FOR UPDATE` 锁,事务内二次验证余额 |
| 3 | **权限绕过** | `Pub/Controller/Credit.php` | 添加 CSRF、Flooding、输入验证、XSS 防护 |
| 4 | **PHP 8.3兼容** | `Service/Transfer/Handler.php` | 添加完整的参数和返回类型声明 |
🟠 高风险问题修复(4项)
| # | 问题类型 | 修复方式 |
|---|---------|---------|
| 5 | XSS防护 | 添加 `stringFormatter()->censorText()` 过滤所有用户输入 |
| 6 | 资源购买并发 | 确认已有 `GET_LOCK()` 分布式锁保护 |
| 7 | N+1查询 | 添加 `with()` 预加载关联数据 |
| 8 | Flooding攻击 | 添加 `assertNotFlooding()` 频率限制 |
---
🔧 具体修复内容
1. SQL注入防护
**修复的方法**:
- `getUserBalance()` - 白名单验证货币ID
- `getUserBalances()` - 白名单验证货币ID
- `updateBalance()` - 白名单验证货币ID
- `setBalance()` - 白名单验证货币ID
- `getTotalSupply()` - 白名单验证货币ID
- `getUserCount()` - 白名单验证货币ID
- `getRichestUsers()` - 白名单验证货币ID
- `getUserRank()` - 白名单验证货币ID
- `hasEnoughBalance()` - 间接修复(调用 getUserBalance)
**新增方法**:
- `validateCurrencyColumn(int $currencyId): string` - 货币列名白名单验证
- `clearCurrencyCache(): void` - 清除缓存
---
2. 并发竞态防护
**修复的方法**:
- `transfer()` - 添加事务锁和余额二次检查
- `transferWithFee()` - 添加事务锁和余额二次检查
**新增机制**:
- 使用 `FOR UPDATE` 锁定发送者和接收者的数据行
- 在事务内二次验证余额(防止 TOCTOU 攻击)
- 完整的 try-catch 异常处理和事务回滚
---
3. 权限和输入验证
**修复的方法**:
- `actionTransfer()` - 完整的安全检查
- `actionBonus()` - Flooding 防护
- `actionRedEnvelope()` - CSRF + XSS + Flooding 防护
- `actionRedEnvelopeGrab()` - Flooding 防护
**新增验证**:
- CSRF Token 验证
- Flooding 防护(转账60s、奖励30s、红包120s、抢红包5s)
- 金额范围验证(必须 > 0)
- 接收者状态验证(user_state 必须为 'valid')
- 防止转账给自己
- 消息长度限制(500字符)
- XSS 过滤(使用 censorText())
---
4. PHP 8.3 类型声明
**修复的方法**:
- `validate(): bool`
- `transfer(string $message = ''): bool`
- `transferWithFee(float $taxPercent, string $message = '', string $feePayer = 'sender'): bool`
- `createTransaction(...): bool`
- `sendTransferAlert(): void`
- `refundPurchase(...): bool`
- `getErrors(): array`
- `hasErrors(): bool`
---
🛡️ 安全增强总结
| 安全层面 | 实施措施 | 效果 |
|---------|---------|------|
| **SQL注入** | 白名单验证 + 参数化查询 | ✅ 完全防护 |
| **并发控制** | FOR UPDATE 锁 + 分布式锁 | ✅ 防止双花和竞态 |
| **CSRF** | Token 验证 | ✅ 所有 POST 请求受保护 |
| **XSS** | 输入过滤 + 长度限制 | ✅ 防止脚本注入 |
| **Flooding** | 频率限制 | ✅ 防止滥用 |
| **权限** | 多层验证 | ✅ 细化访问控制 |
---
⚡ 性能优化
- ✅ 货币列名白名单使用静态缓存
- ✅ 预加载关联数据避免 N+1 查询
- ✅ 精准行锁减少锁竞争
- ✅ 提前验证减少无效数据库操作
---
✅ 修复验证
- [x] 所有修复文件无语法错误
- [x] 符合 XenForo 2.3 开发规范
- [x] 符合 PHP 8.3 严格类型标准
- [x] 完整的错误处理和日志记录
- [x] 向后兼容,不影响现有功能