2012-03-02 43 views
12

看起來HTML5 spec (and therefore ECMA262)允許<input type="text" pattern="[0-9]/[0-9]" />匹配字符串'0/0',即使正斜槓沒有轉義。 Web應用程序一樣的Drupal想提供瀏覽器服務器端驗證不喜歡的東西支持HTML5:什麼是在HTML5模式輸入元素屬性上使用的安全PCRE正則表達式分隔符?

<?php 
preg_match('/^(' . $pattern . ')$/', $value); 
?> 

不幸的是字符串「[0-9]/[0-9]」不是有效的PRCE正則表達式。看來,如果不是所有支持HTML5的瀏覽器同時支持pattern="[0-9]/[0-9]"pattern="[0-9]\/[0-9]"這引出了一個問題 - 我們有什麼可以用作爲分隔符在其上運行的Perl風格的正則表達式這種模式?

我們已經提交了bug report against the W3C spec但瀏覽器錯在這裏? HTML5規範是否需要澄清?有沒有可以在PHP中使用的解決方法?

+0

好的問題,但正如亞歷克斯指出的,沒有解決方案。作爲旁註,追加'^'和'$'字符可能已經破壞了模式,不是嗎?考慮'$ pattern =「(^ | foo)bar」'。 – FtDRbwLXw6 2012-03-02 02:43:40

+0

模式屬性的spec說假設它必須匹配整個字符串,而不僅僅是它的一部分,所以我認爲這將是一個無效模式? – 2012-03-02 05:47:28

回答

4

這是一個有效的正則表達式,如果你使用#,而不是/爲分隔符。例如:

preg_match('#^('.$pattern.')$#', $value); 
+0

似乎'#'在$ pattern中也是有效的。根據瀏覽器當前如何實現模式匹配,我可以使用'pattern =「\#[0-9]」'或'pattern =「#[0-9]」'並且它們都匹配字符串'#1'。 – 2012-03-02 01:45:29

+0

是的,這是一個有效的角色,我只是想說你可以用它來解決問題,因爲沒有*真正的*解決方案。 – 2012-03-02 01:46:09

2

一個與PCRE的問題是,幾乎所有分隔符是合法的開始和結束標記,這取決於是什麼讓的逃逸更容易休息。所以#foo#是合法的,/ foo /是合法的,!foo!是合法的(我認爲)等等。正如我所說,無限的正則表達式非常危險。這聽起來像它沒有指定的HTML5規格錯誤。

也許在PHP,掃描線,並選擇從白名單中不存在的字符串分隔符? (例如,如果沒有/使用,如果使用#,如果是有使用%等)

2

我覺得chr(0)會工作得很好。編輯:不。但chr(1)確實有效。

+0

'chr(1)'是有效的UTF-8字符,所以它可能以HTML格式出現。不太可能,但可能。我建議使用'「\ xFF」'字節,因爲UTF-8字符串不允許使用它,所以我們可以確定它不會發生。由於preg_match不理解UTF-8,所以不會造成麻煩。例子:'preg_match(「\ xFF $ pattern \ $ \ xFFADmsu」,$ subject);'(請注意'ADmsu'修飾符並添加''''u'修飾符只在模式中需要有效的UTF-8字節,但不是在周圍的分隔符。) – 2014-06-23 12:59:06

+0

你* absulutely *應該發佈這個答案,所以我們可以upvote和戴夫可以接受它。 – chx 2014-06-23 16:47:50

+0

好吧,那裏是...... – 2014-06-23 23:43:28

0

由於PHP應用程序(Drupal的在這種情況下)正在生成輸入字段,這似乎是一個解決辦法是做線沿線的東西:

$pattern = '[0-9]/[0-9]'; 
... 
$cleanPattern = preg_replace('/\//', '\\/', $pattern); 
preg_match('/' . $cleanPattern . '/', $subject, $matches); 

我想不出的在這種情況下不起作用的情況下,將/用作表達式中的文字。

HTML5規範推遲到ECMA262的法律模式規範:

如果指定,該屬性的值必須JavaScript的模式生產相匹配。 [ECMA262]

由於存在BNF在ECMA262中定義,一個完整的解析器(而不是使用PCRE)似乎是最安全的方法。

+0

那麼'\\//'應該和''\ /'匹配嗎?你的代碼會將它轉換爲與''/''匹配的''\ /',但不匹配預期的''\ /''。 – 2014-06-23 12:42:21

+0

我不認爲是這種情況,但在殼內測試令人沮喪。匹配輸入字段中不帶引號的'\ /'的HTML5模式值可以與PCRE'/^\\\/$ /'匹配。作爲一個測試說'$ pattern ='\\\\ /';'(兩個逃脫的反斜槓後跟一個轉義斜線)。上面的'pcre_replace'使'$ cleanPattern'評估爲'\\\ /',根據我的需要可以匹配。 – opello 2014-06-23 17:43:43

+0

由於匹配的簡單性,這也應該是'str_replace'而不是'preg_replace'。 – opello 2014-06-24 18:11:50

4

我推薦使用"\xFF"字節作爲模式分隔符,因爲它在UTF-8字符串中是不允許的,所以我們可以確定它不會出現在模式中。由於preg_match不理解UTF-8,所以不會造成麻煩。

例子:preg_match("\xFF$pattern\$\xFFADmsu", $subject);

請注意ADmsu改性劑和添加$u修飾符僅在模式中需要有效的UTF-8字節,但不是在分隔符周圍。

+0

最新的Firefox和Chrome都允許'\ xFF'的模式匹配文本輸入字段中的文字0xFF字節。 – opello 2014-06-25 22:52:26

+0

opello:我剛試過,但沒有奏效。我在輸入字段中添加了'pattern =「a \ xFFb」'屬性,然後輸入了這個字節序列(從hexeditor複製而來),並且Chromium表示它不匹配。我認爲這是正確的行爲,因爲它不是有效的UTF-8字符串。但是,我沒有在非UTF-8頁面上嘗試過。 – 2014-06-26 12:23:25

+0

我嘲笑了我在這裏測試過的東西:http://jsfiddle.net/4nngJ/,它仍然和我在Chrome和Firefox中看到的結果一樣。 – opello 2014-06-26 15:48:11

相關問題