3.2.10 修复邮件页脚显示字面量 ©

邮件正文会被 yang_mail_escape_for_wpdiscuz() 无差别地把 & 加倍,用来抵消
wpDiscuz 在过滤器之后又做的那一次 html_entity_decode —— 不加倍的话,访客
评论里的 <script> 会在解码时还原成活标签。

但这个替换是全局的,连模板骨架里手写的字符实体也一起被加倍。于是
&copy; 变成 &amp;copy;,能否正常显示完全取决于后面那次解码有没有执行:
走了解码 → 还原成实体 → 浏览器显示 ©;没走 → 只解析一次 → 收件人看到
字面量 &copy;。用户遇到的正是后者。

修法不是在转义函数上开口子(那会重新打开脚本注入口),而是让骨架不再
依赖实体:版权符号与 3px 分隔条的不换行空格一律输出 UTF-8 字符本身。
整封邮件本就声明 charset=UTF-8,这样无论被解码几次都不会变形。

用户数据(站名、标题、URL)仍走 esc_html/esc_url —— 那类 & 的转义是
必要的,加倍后能由那次解码还原,属于应当保留的一类。

assertions: run_tests 89 → 95 条(新增 1e 组 6 条)
- 骨架里零手写实体(0 次 decode 也不露原文)
- 经 0~5 次 html_entity_decode 始终是 ©、从不露实体原文
- URL/站名里的 & 仍被转义(不能把 esc_html 一起废掉)
- 分隔条是 U+00A0 裸字符,过过滤器后仍是裸字符

falsify 20 → 22 条,两处注入(页脚退回实体、分隔条退回实体)都能抓住。
全量流水线 14 组 / 465 条断言全绿。
This commit is contained in:
2026-10-23 17:29:37 +08:00
parent 99e5a1ec0a
commit 6f50533e8e
2 changed files with 41 additions and 3 deletions
+40 -2
View File
@@ -644,6 +644,44 @@ function yang_mail_text($html, $limit = 0)
return $t;
}
/**
* 页脚版权行的文字
*
* ── 为什么不用字符实体 ───────────────────────────────────────
* 邮件的 HTML 会被 yang_mail_escape_for_wpdiscuz() 统一把 `&` 换成 `&amp;`
* (那是为了防 wpDiscuz 在过滤器之后又 decode 一次时把评论里的
* `<script>` 还原成活标签)。这个替换是**无差别**的,连我们自己写在
* 骨架里的字符实体也会被一起加倍。
*
* 正常路径下 wpDiscuz 会再 decode 一次,加倍过的实体恰好还原,
* 浏览器解析成 `©` —— 看起来没问题。但**只要有任何一条路径没有走那次
* decode**(插件版本差异、别的过滤器、后台预览、或是我们自己直接调
* wp_mail),加倍过的实体就只会被解析一次,收件人看到就是那串实体原文。
*
* 实体是"靠对家配合才好使"的东西,裸 UTF-8 字符不是。整封邮件都声明了
* `Content-Type: text/html; charset=UTF-8`,直接写 `©` 在多解码几次的
* 情况下也不会变形,所以这里一律输出字符本身,不输出实体。
*
* 站点名走 esc_html():站名可能带 `&`(如「A & B」),这个 `&` 是**用户数据**
* 的转义,被加倍后能由那次 decode 还原,是应当保留的那一类。
*/
function yang_mail_footer_copy($year, $site)
{
return '© ' . esc_html($year) . ' ' . esc_html($site);
}
/**
* 不换行空格
*
* 用途只有一个:给 3px 高的分隔条撑出行高(Outlook 里 td 不能是空的,
* 否则高度会被忽略)。同理不用那个常见的空格字符实体 —— 换成 U+00A0
* 字符本身,免得被 `&` 加倍后在某些路径下变成字面量文本,反而撑高那一行。
*/
function yang_mail_nbsp()
{
return "\xC2\xA0";
}
/**
* 把主色与白色按比例混合,得到一档浅色
*
@@ -846,7 +884,7 @@ function yang_mail_render($args)
height 必须**同时**写成 HTML 属性和 CSS:Outlook 只认属性,
只写 CSS 高度时这条 3px 带会撑成一行文字高(约 18px),比例就毁了。 */ ?>
<tr>
<td bgcolor="<?php echo esc_attr($cHeaderD); ?>" height="3" style="background-color:<?php echo esc_attr($cHeaderD); ?>;height:3px;line-height:3px;font-size:0;mso-line-height-rule:exactly;">&nbsp;</td>
<td bgcolor="<?php echo esc_attr($cHeaderD); ?>" height="3" style="background-color:<?php echo esc_attr($cHeaderD); ?>;height:3px;line-height:3px;font-size:0;mso-line-height-rule:exactly;"><?php echo yang_mail_nbsp(); ?></td>
</tr>
<?php /* ── 正文 ── */ ?>
@@ -952,7 +990,7 @@ function yang_mail_render($args)
<a href="<?php echo esc_url($home); ?>" target="_blank" rel="noopener" style="color:<?php echo esc_attr($cText); ?>;text-decoration:none;font-weight:600;"><?php echo esc_html($site); ?></a>
</div>
<div style="margin:0;">此邮件由系统自动发出,请勿直接回复。</div>
<div style="margin:6px 0 0 0;color:<?php echo esc_attr($cMuted); ?>;">&copy; <?php echo esc_html($year); ?> <?php echo esc_html($site); ?></div>
<div style="margin:6px 0 0 0;color:<?php echo esc_attr($cMuted); ?>;"><?php echo yang_mail_footer_copy($year, $site); ?></div>
</div>
</td>
</tr>
+1 -1
View File
@@ -1,7 +1,7 @@
/*
Theme Name: Kratos_Yang
Text Domain: kratos_Yang
Version: 3.2.9
Version: 3.2.10
Requires PHP: 7.0
Description: 这是一个Kratos主题的分支版本,用来增加一些定制化功能。
Tags: 博客, 双栏, 响应式, 自定义背景, 自定义颜色, 自定义图标, 自定义菜单, 特色图像, 收录优化, 邮件中心, 主题选项, 小工具, 文章置顶, 无障碍友好