SheepDev

編碼與字元集

將 Unicode 逸出與 HTML 字元參照還原為文字

使用工具

原本可讀文字變成反斜線或 & 開頭的序列,可能並未損壞,只是另一格式的表示。但 Unicode 跳脫、HTML 字元參照和 URL 百分號編碼各有規則,不能混用解碼器。

用 あ、表情和短 HTML 樣式文字檢查還原範圍。輸出按文字查看,不當 HTML 或 JavaScript 執行,即使看起來像程式碼也無需執行。始終確認來源格式。

把 \u3042 還原成一個字元

Unicode 跳脫輸入
\u3042

Unicode 解碼得到 あ,編碼則按選項輸出 \u3042 或 \u{3042}。兩者都指向字元,但接收格式不一定都支援,應區分 JSON 字串與 JavaScript 碼位表示。

日誌顯示 \u3042 可能只是把 あ 跳脫序列化。需確認實際值是六個字面字元,還是日誌如此展示一個字元,不能僅憑符號斷定儲存損壞。

一個表情可能需要兩組 \u

😀 的兩種表示
\u{1F600}
\uD83D\uDE00

第一行表示一個碼位,第二行表示 UTF-16 代理對。分別解碼都得到 😀,兩組不代表兩個表情。可見字元與 UTF-16 單元的區別也體現在跳脫表示中。

單獨 \uD83D 因代理不成對而失敗。不要為縮短或滿足長度限制刪掉半對,拆斷表示單位會製造無效資料。截斷策略必須明確單位。

& 是 & 的字元參照

HTML 實體解碼輸入
Tom & Jerry
<b>hello</b>

HTML 實體解碼得到文字 Tom & Jerry 和 <b>hello</b>,工具並非執行標籤使其粗體。查看還原文字與插入 DOM 的 HTML 不同,解碼成功不是安全插入許可。

目前命名參照支援 amp、lt、gt、quot、apos、nbsp,以及數值參照,並非完整 HTML 名稱表。不支援的名稱原樣保留,殘留參照可能是範圍問題而非資料損壞。

&amp;lt; 解一次不會變成 <

逐層解碼結果
&amp;lt; → &lt; → <

首次把 &amp; 還原為 &,留下 &lt;;再解才得到 <。但第二次不一定正確,原文可能就在解釋 &lt; 這種寫法。應確認序列化層數,不要解到所有跳脫消失。

HTML 文字嵌在 JSON 時,形式會疊加。應先解析外層 JSON 得到字串,再另行解 HTML 參照。一次大取代可能改壞引號或分隔符號,應為每一步定義小例子與預期。

%E3%81%82 與 &#12354; 也不是同一種解碼

表示 あ 的不同規則
Unicode: \u3042
HTML: &#12354; / &#x3042;
URL UTF-8: %E3%81%82

HTML 數值參照以十進位或十六進位表示碼位,URL 百分號表示 UTF-8 位元組。數字不同未必字元不同。按來源格式選工具;格式不明應查產生方,不只憑外觀猜。

目前 Unicode 解碼支援 \uXXXX、\u{X}、\xXX,不是包括 \n、\t 的通用字串解析器。完整 JSON 應用 JSON 整理驗證,不要強行取代未支援語法製造成功外觀。

還原後,輸出目的地的規則仍然存在

解碼推進了調查,但把結果放入 HTML 本文、屬性、JavaScript 或 URL 時,仍需對應上下文處理。一次跳脫不是到處安全,目標變化就要重新確認解讀規則。

報告應含原序列、解碼方式、次數和結果。「解一層 HTML 參照得到預期 &」比「修好亂碼」更具體。追蹤多餘層的來源,比反覆轉換到外觀正確更能防復發。

看到的反斜線是資料還是顯示方式?

日誌顯示 \u3042,可能原值是 あ 而僅顯示跳脫,也可能使用者輸入了六個字面字元。是否應解碼取決於複製了哪層。讀取 JSON 時先確認解析後的值,別為了可讀反覆取代,而忽略解析器已經處理了跳脫。

HTML 字元參照也一樣。要展示字面範例 &lt;,源文字可能需要 &amp;lt;,解碼兩次成為 < 就改變了範例。應按已知表示層數解碼,而不是一直到看得懂。工具不能推斷處理歷史,可讀不代表回到了正確層。

參考資料

使用工具

指南 →