fix(vip): preserve safe HTML in VIP copy

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
kate522andClaude Opus 5 committed 2026-10-19 12:52:23 +08:00
1 parent 7a0445fc4a
commit 573040381d
15 files changed
+155 -118

No files matched your search

+2 -2
View File
@@ -200,7 +200,7 @@ if (!function_exists('aksrt_header_payvip_bar')) :
$level = function_exists('aksrt_get_user_vip_level') ? (int) aksrt_get_user_vip_level($user_id) : 0;
if ($level > 0) {
$levels = is_array($vip['levels'] ?? null) ? $vip['levels'] : [];
$name = (string) ($levels[$level]['name'] ?? ($level === 2 ? __('二级会员', 'aksrt') : __('一级会员', 'aksrt')));
$name = (string) ($levels[$level]['name_html'] ?? $levels[$level]['name'] ?? ($level === 2 ? __('二级会员', 'aksrt') : __('一级会员', 'aksrt')));
// 到期徽章语义对齐参考主题 zib_get_user_vip_exp_date_text():只有真的拿到
// 到期时间才渲染这枚徽章,已过期显示「会员已过期」否则显示裸日期;显式永久
// 会员显示「永久会员」;拿不到到期数据时参考主题返回 false,整枚徽章不渲染。
@@ -219,7 +219,7 @@ if (!function_exists('aksrt_header_payvip_bar')) :
$html = '<div class="mt10 em09" style="padding:2px;">';
$html .= '<span class="radius4 payvip-icon btn-block text-center">';
$html .= function_exists('aksrt_get_vip_icon') ? aksrt_get_vip_icon($user_id, 'em12 mr6', false) : '';
$html .= '<span>' . esc_html($name) . '</span>';
$html .= '<span>' . wp_kses_post($name) . '</span>';
if ($exp_label !== '') {
$html .= '<span class="ml10 badg jb-yellow vip-expdate-tag">'
. '<i class="fa fas fa-clock mr3" aria-hidden="true"></i>'
+6 -2
View File
@@ -1309,6 +1309,7 @@ if (!function_exists('aksrt_get_posts_vip_price')) {
}
$level_name = (string) ($level_settings['name'] ?? sprintf(__('VIP%d', 'aksrt'), $level));
$level_name_html = (string) ($level_settings['name_html'] ?? $level_name);
$price = $vip_minor === 0
? esc_html__('免费', 'aksrt')
: $mark . esc_html(aksrt_format_price($value));
@@ -1319,7 +1320,7 @@ if (!function_exists('aksrt_get_posts_vip_price')) {
? ' data-toggle="tooltip" title="' . esc_attr($title) . '"'
: '';
$items[] = '<span class="but vip-price' . $action_class . '" vip-level="' . esc_attr((string) $level) . '" data-vip-level="' . esc_attr((string) $level) . '"' . $title_attr . '>' . $icon . esc_html($level_name) . '<span class="em12 ml3 vip-price-text">' . $price . '</span></span>';
$items[] = '<span class="but vip-price' . $action_class . '" vip-level="' . esc_attr((string) $level) . '" data-vip-level="' . esc_attr((string) $level) . '"' . $title_attr . '>' . $icon . wp_kses_post($level_name_html) . '<span class="em12 ml3 vip-price-text">' . $price . '</span></span>';
}
$html = implode('', $items);
@@ -1384,10 +1385,13 @@ if (!function_exists('aksrt_get_paywall_html')) {
$vip_action = $vip_level > 0
? sprintf(__('升级%s', 'aksrt'), $level_name)
: __('开通会员', 'aksrt');
$vip_action_html = $vip_level > 0
? __('升级', 'aksrt') . wp_kses_post((string) ($level_settings['name_html'] ?? $level_name))
: esc_html__('开通会员', 'aksrt');
$action_class = is_user_logged_in() ? 'pay-vip' : 'signin-loader';
$icon = aksrt_get_pay_vip_icon_html($level_settings);
$button = '<div class="badg c-yellow em09 mb6"><i class="fa fas fa-fw fa-info-circle mr6" aria-hidden="true"></i>' . esc_html(sprintf(__('您暂无购买权限,请先%s', 'aksrt'), $vip_action)) . '</div>';
$button .= '<a href="javascript:;" vip-level="' . esc_attr((string) $pay_limit) . '" data-vip-level="' . esc_attr((string) $pay_limit) . '" class="but btn-block jb-vip' . esc_attr((string) $pay_limit) . ' ' . esc_attr($action_class) . ' padding-lg">' . $icon . esc_html($vip_action) . '</a>';
$button .= '<a href="javascript:;" vip-level="' . esc_attr((string) $pay_limit) . '" data-vip-level="' . esc_attr((string) $pay_limit) . '" class="but btn-block jb-vip' . esc_attr((string) $pay_limit) . ' ' . esc_attr($action_class) . ' padding-lg">' . $icon . $vip_action_html . '</a>';
} elseif (!is_user_logged_in()) {
if ($amount_minor > 0 && $modo === '0' && aksrt_allow_guest_content_pay($post)) {
$button = '<button type="button" class="but jb-red padding-lg cashier-link' . $block_class . '" data-aksrt-pay-content="' . esc_attr((string) $post->ID) . '"><i class="fa fas fa-shopping-cart" aria-hidden="true"></i> ' . esc_html__('立即购买', 'aksrt') . '</button>';
+2 -16
View File
@@ -481,7 +481,7 @@ endif;
* or Chinese keyword heuristics — that mangles intentional HTML.
*
* Rules:
* - Sanitize with a small allowlist.
* - Sanitize with WordPress post-safe HTML.
* - If markup already has <li>, wrap the items in <ul class="v-equity …">.
* - Otherwise output the sanitized HTML inside <div class="v-equity …">.
* - Plain multi-line text: each non-empty line becomes one <li> (only \n split).
@@ -497,21 +497,7 @@ if (!function_exists('aksrt_format_vip_equity_html')) {
return '';
}
$allowed = [
'li' => ['class' => true],
'ul' => ['class' => true],
'ol' => ['class' => true],
'strong' => [],
'b' => [],
'em' => [],
'i' => ['class' => true],
'span' => ['class' => true],
'br' => [],
'p' => ['class' => true],
'div' => ['class' => true],
'a' => ['href' => true, 'target' => true, 'rel' => true, 'class' => true],
];
$clean = trim(wp_kses($raw, $allowed));
$clean = trim(wp_kses_post($raw));
if ($clean === '') {
return '';
}
@@ -29,7 +29,7 @@ if ($status === '') {
}
if ($vip_level > 0) {
$title = (string) ($vip_levels[$vip_level]['name'] ?? ('VIP' . $vip_level));
$title = (string) ($vip_levels[$vip_level]['name_html'] ?? $vip_levels[$vip_level]['name'] ?? ('VIP' . $vip_level));
if ($expires <= 0 && ($vip_state['source'] ?? 'none') !== 'order') {
$status = __('永久会员', 'aksrt');
} else {
@@ -41,7 +41,7 @@ if ($vip_level > 0) {
);
}
} elseif ($expired_level > 0) {
$title = (string) ($vip_levels[$expired_level]['name'] ?? ('VIP' . $expired_level));
$title = (string) ($vip_levels[$expired_level]['name_html'] ?? $vip_levels[$expired_level]['name'] ?? ('VIP' . $expired_level));
$status = __('已过期', 'aksrt');
}
@@ -55,8 +55,8 @@ $sidebar_arrow = aksrt_icon_markup('zibsvg-right', 'uc-sidebar-vip__arrow');
<a class="uc-sidebar-vip" href="<?php echo esc_url($vip_url); ?>" data-tab="vip">
<span class="uc-sidebar-vip__icon"><?php echo $sidebar_icon; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></span>
<span class="uc-sidebar-vip__content">
<strong><?php echo esc_html($title); ?></strong>
<small><?php echo esc_html($status); ?></small>
<strong><?php echo wp_kses_post($title); ?></strong>
<small><?php echo wp_kses_post($status); ?></small>
</span>
<?php echo $sidebar_arrow; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
</a>
+14 -14
View File
@@ -46,7 +46,7 @@ $btn_type = 'pay';
if ($level > 0) {
$vip_level_number = $level;
$vip_level_name = (string) ($levels[$level]['name'] ?? ('VIP' . $level));
$vip_level_name = (string) ($levels[$level]['name_html'] ?? $levels[$level]['name'] ?? ('VIP' . $level));
$level_desc = (string) ($levels[$level]['desc'] ?? '');
$vip_description = $level_desc !== '' ? $level_desc : __('尊享专属特权', 'aksrt');
@@ -63,7 +63,7 @@ if ($level > 0) {
$vip_state_label = __('生效中', 'aksrt');
$vip_expiry_text = sprintf(__('到期时间:%s', 'aksrt'), wp_date('Y年m月d日', $expires));
if ($base_level > 0 && $base_level < $level) {
$base_name = (string) ($levels[$base_level]['name'] ?? ('VIP' . $base_level));
$base_name = wp_strip_all_tags((string) ($levels[$base_level]['name'] ?? ('VIP' . $base_level)));
$base_expiry_text = $base_expires > 0
? wp_date('Y年m月d日', $base_expires)
: __('永久', 'aksrt');
@@ -75,7 +75,7 @@ if ($level > 0) {
$vip_state = 'expired';
$vip_state_label = __('已过期', 'aksrt');
$vip_level_number = $expired_level;
$vip_level_name = (string) ($levels[$expired_level]['name'] ?? ('VIP' . $expired_level));
$vip_level_name = (string) ($levels[$expired_level]['name_html'] ?? $levels[$expired_level]['name'] ?? ('VIP' . $expired_level));
$expired_desc = (string) ($levels[$expired_level]['desc'] ?? '');
$vip_description = $expired_desc !== ''
? $expired_desc
@@ -97,9 +97,9 @@ $status_html = '<div class="uc-vip-status" role="status">'
. '<div class="uc-vip-status__main uc-vip-status__main--level-' . (int) $vip_level_number . '">'
// 未开通(level 0)不输出图标位:名称前不放通用证书图标。
. ($vip_level_number > 0 ? '<span class="uc-vip-status__icon" aria-hidden="true">' . $status_icon . '</span>' : '')
. '<span class="uc-vip-status__level">' . esc_html($vip_level_name) . '</span>'
. '<span class="uc-vip-status__level">' . wp_kses_post($vip_level_name) . '</span>'
. '</div>'
. '<div class="uc-vip-status__desc">' . esc_html($vip_description) . '</div>'
. '<div class="uc-vip-status__desc">' . wp_kses_post($vip_description) . '</div>'
. ($vip_expiry_text !== '' ? '<div class="uc-vip-status__expiry"><i class="fa fas fa-clock" aria-hidden="true"></i><span>' . esc_html($vip_expiry_text) . '</span></div>' : '')
. '</div>';
@@ -109,14 +109,14 @@ foreach ([1, 2] as $lv) {
if (empty($levels[$lv]['enabled'])) {
continue;
}
$lv_name = (string) ($levels[$lv]['name'] ?? ('VIP' . $lv));
$lv_name = (string) ($levels[$lv]['name_html'] ?? $levels[$lv]['name'] ?? ('VIP' . $lv));
$lv_desc = (string) ($levels[$lv]['desc'] ?? '');
// Preserve admin equity HTML as-is (sanitize/wrap only; never re-split into items).
$equity_raw = (string) ($levels[$lv]['equity'] ?? '');
$equity = function_exists('aksrt_format_vip_equity_html')
? aksrt_format_vip_equity_html($equity_raw)
: '';
$cta = sprintf(__('开通%s', 'aksrt'), $lv_name);
$cta = __('开通', 'aksrt') . wp_kses_post($lv_name);
$vip_attr = $lv;
// 参考主题 zibpay_get_vip_card:续费/升级档位卡展示各自的一句话简介。
$card_action = 'pay';
@@ -128,10 +128,10 @@ foreach ([1, 2] as $lv) {
if (str_starts_with($btn_type, 'renew_')) {
$renew_lv = (int) substr($btn_type, 6);
if ($lv === $renew_lv) {
$cta = sprintf(__('续费%s', 'aksrt'), $lv_name);
$cta = __('续费', 'aksrt') . wp_kses_post($lv_name);
$card_action = 'renew';
} elseif ($lv > $renew_lv) {
$cta = sprintf(__('升级%s', 'aksrt'), $lv_name);
$cta = __('升级', 'aksrt') . wp_kses_post($lv_name);
$card_action = 'upgrade';
} else {
continue;
@@ -140,13 +140,13 @@ foreach ([1, 2] as $lv) {
if ($lv <= $level) {
continue;
}
$cta = sprintf(__('升级%s', 'aksrt'), $lv_name);
$cta = __('升级', 'aksrt') . wp_kses_post($lv_name);
$card_action = 'upgrade';
$vip_attr = 2;
} elseif ($level > 0 && $lv < $level) {
continue;
} elseif ($level > 0 && $lv === $level) {
$cta = sprintf(__('续费%s', 'aksrt'), $lv_name);
$cta = __('续费', 'aksrt') . wp_kses_post($lv_name);
$card_action = 'renew';
}
if ($card_action === 'renew' && $renew_desc !== '') {
@@ -158,14 +158,14 @@ foreach ([1, 2] as $lv) {
$cards .= '<div class="aksrt-panel text-center pay-vip-info flex1 level-' . $lv . ' uc-vip-level-card">';
$cards .= '<div class="relative uc-vip-level-card__inner">';
$cards .= '<div class="v-iconbox mb10">';
$cards .= '<div class="v-name font-bold"><span class="v-icon">' . $lv_icon . '</span>' . esc_html($lv_name) . '</div>';
$cards .= '<div class="v-name font-bold"><span class="v-icon">' . $lv_icon . '</span>' . wp_kses_post($lv_name) . '</div>';
if ($card_desc !== '') {
$cards .= '<div class="v-desc em09 muted-2-color">' . esc_html($card_desc) . '</div>';
$cards .= '<div class="v-desc em09 muted-2-color">' . wp_kses_post($card_desc) . '</div>';
}
$cards .= '</div>';
$cards .= $equity;
$cards .= '<a class="padding-lg but jb-vip' . $lv . ' radius pay-vip uc-vip-cta" href="javascript:;" vip-level="' . (int) $vip_attr . '">'
. '<span>' . esc_html($cta) . '</span>'
. '<span>' . $cta . '</span>'
. ' <i class="fa fas fa-chevron-circle-right" aria-hidden="true"></i></a>';
$cards .= '</div></div>';
}