软件图标支持上传图片:存 OSS/本机,media.php 代理读取
用户要求图标可以自己上传一张真实图片,而不是只能填一个字符。
设计:字符和图片并存,图片优先
- software 加 icon_key(图片对象键),icon(字符)保留作兜底
- 有图片用图片,删掉图片自动退回字符,任何时刻都不会没有图标
- 前端 badge 与邮件头部同一套判断,页面和邮件永远一致
存储与读取
- 图标走独立键空间 icons/YYYY/MM/<16hex>.<ext>
不复用附件那套:附件必须挂在 thread 下才给读,图标不属于任何帖子
- 写:仅管理员(后台动作链)+ finfo 真实类型校验 + 尺寸下限 + 2MB 上限
- 读:media.php 对 icons/ 只校验键形状与文件存在(图标本就公开),
写入侧仍然严格,不会让本站变成能读整个桶的开放代理
- 优先用 media.php?k= 代理;OSS 下顺便借图片处理缩放,省下行
顺手修掉两个真实安全问题
1. fb_icon_key_ok 原来用 [a-z0-9]{2,5} 匹配扩展名,.php 正好能过
(3 个字母)—— 测试反向验证时发现,已改为图片扩展名白名单
2. fb_upload_key_ok 有同样的问题,附件键也能构造出 .php
虽然真上传还有 finfo 兜底,但键本身就不该长这样,一并收紧
3. fb_icon_delete 原来用 @ 吞掉错误,删除失败仍返回「已保存」,
用户会以为旧图清了、实际留了个可访问的孤儿图。改为返回 bool 并如实提示
验证:键校验 7 类非法输入全拒;图标写入 OSS 成功、media.php 读回 200 image/png、
PNG 魔数正确、缩放生效;越权读取(穿越/.php/未入库附件/不存在)全部按预期拒绝;
表单 enctype/文件框/accept/预览渲染齐全;仿真 PHP 伪图与 SVG 均被拒;
16x16 小图被拒。
This commit is contained in:
@@ -149,6 +149,28 @@ main.wrap{padding-top:24px; padding-bottom:40px; min-height:60vh}
|
||||
display:inline-flex; align-items:center; justify-content:center;
|
||||
}
|
||||
.icon-preset:hover{border-color:var(--brand); background:var(--brand-soft)}
|
||||
|
||||
/* ---------- 软件图标(上传图片) ---------- */
|
||||
/* 图标图片:外框与字符版完全一致,换图不会让布局跳动 */
|
||||
.sw-badge-img{
|
||||
display:inline-block; border-radius:7px; object-fit:cover; flex:none;
|
||||
box-shadow:0 1px 2px rgba(15,25,45,.18); background:var(--card);
|
||||
}
|
||||
.chip.on .sw-badge-img{box-shadow:0 0 0 1px rgba(255,255,255,.5)}
|
||||
/* 后台图标上传行 */
|
||||
.icon-up{display:flex; align-items:flex-start; gap:14px; flex-wrap:wrap; margin-top:6px}
|
||||
.icon-prev{
|
||||
width:56px; height:56px; flex:none; border-radius:12px; overflow:hidden;
|
||||
border:1px solid var(--line); background:var(--card);
|
||||
display:flex; align-items:center; justify-content:center;
|
||||
}
|
||||
.icon-prev img{width:100%; height:100%; object-fit:cover; display:block}
|
||||
.icon-prev-ph{
|
||||
width:100%; height:100%; display:flex; align-items:center; justify-content:center;
|
||||
color:#fff; font-size:24px; font-weight:600;
|
||||
}
|
||||
.icon-up-main{flex:1; min-width:220px; display:flex; flex-direction:column}
|
||||
.icon-up-main input[type=file]{font-size:13.5px; max-width:100%}
|
||||
/* 选中态的 chip 里,图标底衬白、字符取软件色,避免同色糊在一起 */
|
||||
.chip.on .sw-badge-ic{background:#fff !important; color:var(--brand) !important; box-shadow:none}
|
||||
.chip.on .sw-badge-nm{color:#fff}
|
||||
|
||||
Reference in New Issue
Block a user