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

PHP 實現 UBB 代碼轉 HTML:完整解析與可擴展的 ubb2xhtml 函數

     編輯:PHP 相關知識

UBB 碼轉 HTML:論壇、評論系統的核心需求

UBB (Universal Bulletin Board) 代碼是一種輕量級標記語言,廣泛用於論壇、博客評論、CMS 內容編輯,允許用戶通過簡單標籤(如 [b]粗體[/b]、[url=...]鏈接[/url])生成安全的 HTML,避免直接輸入 HTML 帶來的 XSS 風險。本文深度解析一個功能完整的 ubb2xhtml() 函數實現。

核心函數架構

函數採用 正則表達式替換 策略,定義匹配模式數組 $match,再配合 preg_replace() 批量處理。這種設計易於擴展新標籤,維護成本低。

<?php
/**
 * UBB 代碼轉換為 XHTML
 * @param string $ubb 包含 UBB 標籤的文本
 * @return string 轉換後的 XHTML
 */
function ubb2xhtml($ubb) {
    // 1. 定義 Flash 嵌入模板(使用 heredoc 便於多行)
    $flash = << '替換模板' 或 回調函數
    $patterns = [
        // [url=鏈接]文字[/url]
        '%\[url=([^\s\]]+)\](.*?)\[/url\]%s' => 
            '<a href="\1" target="_blank" rel="noopener">\2</a>',
        
        // [email=郵箱]文字[/email]
        '%\[email=([^\s\]]+)\](.*?)\[/email\]%i' => 
            '<a href="mailto:\1">\2</a>',
        
        // [img width=寬 height=高]圖片URL[/img]
        '%\[img\s+width=(\d+)\s+height=(\d+)\](.*?)\[/img\]%s' => 
            '<img src="\3" width="\1" height="\2" alt="" />',
        
        // [img=圖片URL]
        '%\[img=([^\s\]]+)\]%s' => 
            '<img src="\1" alt="" />',
        
        // [flash width=寬 height=高]SWF_URL[/flash] - 使用 sprintf 回調
        '%\[flash\s+width=(\d+)\s+height=(\d+)\](.*?)\[/flash\]%se' => 
            'sprintf($flash, \1, \2, "\3")',
        
        // 基礎文本格式:[b][i][u][strike][sup][sub]
        '%\[(b|i|u|strike|sup|sub)\](.*?)\[/\1\]%s' => 
            '<\1>\2</\1>',
        
        // 標題:[h1]...[/h1] 到 [h6]
        '%\[h([1-6])\](.*?)\[/h\1\]%s' => 
            '<h\1>\2</h\1>',
        
        // 分隔線:[hr/]
        '%\[hr/\]%s' => 
            '<hr />',
        
        // 顏色:[color=red]文字[/color]
        '%\[color=([^\s\]]+)\](.*?)\[/color\]%s' => 
            '<span style="color:\1">\2</span>',
        
        // 字體:[font=Arial]文字[/font]
        '%\[font=([^"\]]+)\](.*?)\[/font\]%s' => 
            '<span style="font-family:\1">\2</span>',
        
        // 字號:[size=14]文字[/size] (像素值)
        '%\[size=([^\s\]]+)\](.*?)\[/size\]%s' => 
            '<span style="font-size:\1px">\2</span>',
        
        // 對齊:[align=center]文字[/align]
        '%\[align=(center|right|left)\](.*?)\[/align\]%s' => 
            '<div style="text-align:\1">\2</div>',
        
        // 垂直對齊(表格單元格用)
        '%\[valign=(middle|top|bottom)\](.*?)\[/valign\]%s' => 
            '<div style="vertical-align:\1">\2</div>',
        
        // 表格相關(簡化版)
        '%\[table=([^\s\]]*)\](.*?)\[/table\]%s' => 
            '<table\1>\2</table>',
        '%\[caption\](.*?)\[/caption\]%s' => 
            '<caption>\1</caption>',
        '%\[tr=([^\s\]]*)\](.*?)\[/tr\]%s' => 
            '<tr\1>\2</tr>',
        '%\[th\](.*?)\[/th\]%s' => 
            '<th>\1</th>',
        '%\[td\](.*?)\[/td\]%s' => 
            '<td>\1</td>',
        
        // 註釋/引用/代碼塊
        '%\[note\](.*?)\[/note\]%s' => 
            '<div class="note">\1</div>',
        '%\[quote=(.*?)\](.*?)\[/quote\]%s' => 
            '<blockquote><cite>\1</cite>\2</blockquote>',
        '%\[code\](.*?)\[/code\]%s' => 
            '<pre><code>\1</code></pre>',
        
        // 雙空格保留
        '%[ ]{2}%s' => 
            '&nbsp;&nbsp;',
    ];

    // 3. 執行替換
    // 注意:順序很重要,巢狀標籤需從內向外或按優先級處理
    foreach ($patterns as $pattern => $replacement) {
        $ubb = preg_replace($pattern, $replacement, $ubb);
    }

    return $ubb;
}
?>

關鍵技術點解析

1. 正則模式設計原則

  • 非貪婪匹配:使用 (.*?) 而非 (.*),防止跨標籤匹配。
  • 字符類排除:[^\s\]]+ 匹配非空白、非右括號字符,精確捕獲屬性值。
  • 修飾符:s (DOTALL) 讓 . 匹配換行;i 忽略大小寫;e (已棄用) 執行替換代碼——現代寫法應改用 preg_replace_callback()。

2. Flash 模板與 sprintf() 回調

利用 %1\$d、%3\$s 等參數編號,配合 preg_replace() 的 e 修飾符(或回調函數)動態生成嵌入代碼。注意:PHP 7.0+ 移除了 /e 修飾符,必須遷移到 preg_replace_callback()。

3. 安全性考量

  • 屬性值過濾:實際項目中應對 URL、顏色、字體等屬性做白名單驗證,防止注入 javascript: 協議或惡意樣式。
  • 輸出轉義:轉換前對用戶輸入做 htmlspecialchars(),僅允許 UBB 標籤生成 HTML。
  • 嵌套處理:複雜嵌套(如 [b][i]文字[/i][/b])可能需要多輪替換或狀態機解析。

現代化重寫建議:使用 preg_replace_callback()

<?php
// 以 [url] 標籤為例
$ubb = preg_replace_callback(
    '%\[url=([^\s\]]+)\](.*?)\[/url\]%s',
    function ($matches) {
        // $matches[1] = URL, $matches[2] = 鏈接文本
        $url = htmlspecialchars($matches[1], ENT_QUOTES, 'UTF-8');
        $text = htmlspecialchars($matches[2], ENT_QUOTES, 'UTF-8');
        // 簡單協議白名單
        if (!preg_match('/^(https?|ftp):\/\//i', $url)) {
            return $matches[0]; // 不合法則保持原樣
        }
        return '<a href="' . $url . '" target="_blank" rel="noopener noreferrer">' . $text . '</a>';
    },
    $ubb
);
?>

擴展建議

  1. 列表標籤:啟用註釋掉的 [ul]、[ol]、[li],注意列表嵌套需狀態機處理。
  2. 視頻/音頻:添加 [video]、[audio] 標籤對接 HTML5 播放器。
  3. 代碼高亮:[code=php] 整合 Prism.js 或 highlight.js。
  4. 表情符號:[emoji:smile] 映射圖片或 Unicode。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved