HTML::Parserのタグ解釈をよりブラウザに近く

HTML::Parser は、タグのattributeの解釈が仕様に忠実で、クオートの閉じ忘れを正しく解釈する。結果として
<div style="background: white;><a href="http://google.com/">google</a></div>
というHTMLでdivのstyleには “background: white;><a href= という値がはいる。が、これは困る。ブラウザはクオート内に現れた > については、少し考えた上でクオートの閉じ忘れと解釈したりする。(昔mozillaのコードを読んだけど詳細は忘れた)
というわけでHTML::Parseをブラウザに近い動作をするように書き換えたかったのだけれど、処理はXSの中に入っていてCで書かないといけなかった。なので > よりあとを走査して < よりも先にクオートが見つかったら、クオート内に&gt;としてエスケープされずにはいっていた>として判断してそのまま、そうでなければ閉じ忘れとして判断するようにした。

--- hparser.org.c       2006-07-10 18:00:47.000000000 +0900
+++ hparser.c   2006-09-28 18:03:09.286069000 +0900
@@ -1341,8 +1341,24 @@
            if (*s == '"' || *s == '\\'') {
                char *str_beg = s;
                s++;
-               while (s < end && *s != *str_beg)
+               while (s < end && *s != *str_beg) {
+                       if ( *s == '>' ) {
+                               int found = 0;
+                               char *t = s;
+                               while ( t < end && *t != '<' ) {
+                                       if (*t == *str_beg ) {
+                                               found = 1;
+                                               break;
+                                       }
+                                       t++;
+                               }
+                               if ( ! found ) {
+                                       s--;
+                                       break;
+                               }
+                       }
                    s++;
+               }
                if (s == end)
                    goto PREMATURE;
                s++;

が、テスト t/parser でこける。ひどいHTMLのときにテストで規定されている解釈をしなくなっている模様だが、とりあえず気にしないことにする。


About this entry