首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP UBB 標籤解析器:完整標籤支援與安全強化版

     編輯:PHP 綜合知識

什麼是 UBB?

UBB (Ultimate Bulletin Board) 是早期論壇常用的輕量標記語言,使用方括號標籤(如 [b]粗體[/b])替代 HTML,避免使用者輸入惡意腳本。本文提供一個功能完整、經過安全強化的 PHP 解析函式 ubb()。

支援標籤一覽

UBB 標籤轉換後 HTML說明
[h1]~[h6]<h1>~<h6>標題層級
[center]<center>置中(HTML5 建議改 CSS)
[url]/[url=link]<a href="..." target="_blank">超連結,支援自動補全協定
[img]/[img=attr]<img src="...">圖片,可附加屬性
[color=#fff]<font color="...">字體顏色
[size=12]<font size="...">字體大小
[b]/[i]/[u]<b>/<i>/<u>粗體/斜體/底線
[quote]<blockquote>...</blockquote>引用區塊
[code]/[php]<pre><code>...</code></pre>程式碼區塊(含語法高亮)
[email]<a href="mailto:...">電子郵件連結
[sup]/[sub]<sup>/<sub>上/下標
[hr]/[separator]<hr>/<br/>分隔線
[sig]簽名檔區塊自訂樣式

完整解析函式(已移除 /e 修飾符、加入 XSS 防護)

<?php
function ubb($text) {
    $text = trim($text);
    // 基礎轉換
    $text = str_replace("\n", '<br>', $text);
    $text = preg_replace('/\t/', ' ', $text);
    $text = preg_replace('/\[hr\]/i', '<hr>', $text);
    $text = preg_replace('/\[separator\]/i', '<br/>', $text);

    // 標題
    for ($i = 1; $i <= 6; $i++) {
        $text = preg_replace("/\\[h{$i}\\](.+?)\\[\\/h{$i}\\]/is", "<h{$i}>\\1</h{$i}>", $text);
    }

    // 置中
    $text = preg_replace('/\[center\](.+?)\[\/center\]/is', '<div style="text-align:center">\\1</div>', $text);

    // 超連結:[url]link[/url] 或 [url=link]text[/url]
    $text = preg_replace('/\[url\](.+?)\[\/url\]/is', '<a href="\\1" target="_blank" rel="noopener">\\1</a>', $text);
    $text = preg_replace('/\[url=(https?:\/\/.+?)\](.+?)\[\/url\]/is', '<a href="\\1" target="_blank" rel="noopener">\\2</a>', $text);
    $text = preg_replace('/\[url=(.+?)\](.+?)\[\/url\]/is', '<a href="\\1" target="_blank" rel="noopener">\\2</a>', $text);

    // 圖片:[img]src[/img] 或 [img=width=100]src[/img]
    $text = preg_replace('/\[img\](.+?)\[\/img\]/is', '<img src="\\1" alt="">', $text);
    $text = preg_replace('/\[img\s+(.+?)\](.+?)\[\/img\]/is', '<img \\1 src="\\2" alt="">', $text);

    // 字體顏色
    $text = preg_replace('/\[color=(.+?)\](.+?)\[\/color\]/is', '<span style="color:\\1">\\2</span>', $text);

    // 字體大小
    $text = preg_replace('/\[size=(.+?)\](.+?)\[\/size\]/is', '<span style="font-size:\\1px">\\2</span>', $text);

    // 樣式類別
    $text = preg_replace('/\[style=(.+?)\](.+?)\[\/style\]/is', '<div class="\\1">\\2</div>', $text);

    // 上下標
    $text = preg_replace('/\[sup\](.+?)\[\/sup\]/is', '<sup>\\1</sup>', $text);
    $text = preg_replace('/\[sub\](.+?)\[\/sub\]/is', '<sub>\\1</sub>', $text);

    // 程式碼區塊(需自行實作 highlight_code())
    $text = preg_replace_callback('/\[code\](.+?)\[\/code\]/is', function($m) {
        return '<pre><code>' . htmlspecialchars($m[1]) . '</code></pre>';
    }, $text);
    $text = preg_replace_callback('/\[php\](.+?)\[\/php\]/is', function($m) {
        return '<pre><code class="php">' . highlight_string($m[1], true) . '</code></pre>';
    }, $text);

    // 粗體、斜體、底線
    $text = preg_replace('/\[b\](.+?)\[\/b\]/is', '<strong>\\1</strong>', $text);
    $text = preg_replace('/\[i\](.+?)\[\/i\]/is', '<em>\\1</em>', $text);
    $text = preg_replace('/\[u\](.+?)\[\/u\]/is', '<u>\\1</u>', $text);

    // 引用
    $text = preg_replace('/\[quote\](.+?)\[\/quote\]/is', '<blockquote>\\1</blockquote>', $text);

    // 簽名檔
    $text = preg_replace('/\[sig\](.+?)\[\/sig\]/is', '<div class="signature">\\1</div>', $text);

    // 表情符號(需自行實作 emot())
    $text = preg_replace_callback('/\[emot\](.+?)\[\/emot\]/is', function($m) {
        return emot($m[1]); // 自訂函式對應圖片
    }, $text);

    // Email
    $text = preg_replace('/\[email\](.+?)\[\/email\]/is', '<a href="mailto:\\1">\\1</a>', $text);

    return $text;
}

// 輔助函式範例
function emot($code) {
    $map = [':)' => 'smile.png', ':(' => 'sad.png'];
    return isset($map[$code]) ? '<img src="/emot/' . $map[$code] . '" alt="' . htmlspecialchars($code) . '">' : $code;
}
?>

安全強化重點

  • 移除 /e 修飾符:舊版使用 preg_replace(.../e) 執行任意程式碼,極度危險。本版全面改用 preg_replace_callback()。
  • 輸出轉義:htmlspecialchars() 處理程式碼區塊內容,防止 XSS。
  • 連結加強:target="_blank" 搭配 rel="noopener" 防止反向標籤攻擊。
  • 屬性過濾:[img=...] 允許自訂屬性,實際上線建議加入白名單過濾(如僅允許 width/height/alt)。

效能優化建議

  1. 編譯快取:將解析後的 HTML 快取至 Redis/Memcache,避免重複解析。
  2. 單次遍歷:若流量極大,可改用有限狀態機 (FSM) 或 Parsedown 類庫單次遍歷完成解析。
  3. 限制長度:前端輸入前限制字數(如 10000 字),防止 ReDoS 攻擊。

擴展範例:自訂標籤

<?php
// 新增 [spoiler] 隱藏內容標籤
$text = preg_replace_callback('/\[spoiler\](.+?)\[\/spoiler\]/is', function($m) {
    $id = 'spoiler_' . uniqid();
    return '<div class="spoiler">'
         . '<button onclick="document.getElementById(\'' . $id . '\').style.display=\'block\';this.remove()">顯示內容</button>'
         . '<div id="' . $id . '" style="display:none">' . $m[1] . '</div>'
         . '</div>';
}, $text);
?>
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved