URL からクエリ文字列を削除する

URL からクエリ文字列を削除する方法を探ってみましたた。クエリ文字列とは CGI スクリプトなどにパラメータを渡す部分の事です。URL 中に ? で連結された ?word=portion のような部分を指します。

コード リーディングの対象はアクセスログ解析ソフトの AWFFull 3.4.3 です。C言語で書かれています。

キーワードは strip

まずは、「削除する」から連想される英単語を用いて、grep でソースファイル内を検索しました。1回目の "strip" というキーワードでコメントがヒットし、満足のいく結果が得られました。

sjv@gentoo ~/src/awffull-3.4.3/src $ grep -n strip *.c
awffull.c:483:            /* strip query portion of cgi scripts */
awffull.c:496:            /* strip off index.html (or any aliases) */
awffull.c:529:            /* strip query portion of cgi referrals */
awffull.c:2049:    /* strip invalid chars */
linklist.c:150:    /* make local copy of string & strip quotes */
parser.c:496:    /* strip trailing space(s) */

なぜ "strip" が連想されるのかというと、「消し去ってしまう」というより「余計なものを取り除く」といったイメージだからです。"delete" や "erase" はブラックホールへ放りこむ感じで、1度消し去ってしまえば取り返しがつかないことを意味します。他にも、Python では文字列から余計なホワイトスペースを削除するメソッドが strip() なので習慣的に「文字列の不必要な部分を取り除くのは "strip" なのだ」と体に染み着いていたりします。

英単語を連想するっていうのは英語に慣れていないと難しかったりしますが、「連想キーワードで grep する」 はコード リーディングでは常套手段なので覚えておきましょう。

URL では無い文字

ソースコードの該当部分に目星がついたところで、grep で得られた1つ目の結果 awffull.c:483: /* strip query portion of cgi scripts */ の前後を見てみたところ、「URL 文字列を1文字ずつ読み込んで URL では無い文字を URL 文字列の終了(=クエリの開始)と判断して break 」という具合になっていました。

483             /* strip query portion of cgi scripts */
484             cp1 = log_rec.url;
485             while (*cp1 != '\0')
486                 if (!isurlchar(*cp1)) {
487                     *cp1 = '\0';
488                     break;
489                 } else
490                     cp1++;
491             if (log_rec.url[0] == '\0') {
492                 log_rec.url[0] = '/';
493                 log_rec.url[1] = '\0';
494             }

あとは URL では無い文字をどのように判定しているかを知るだけです。上記のソースで486行目の isurlchar(*cp1) が文字の判定を行っている箇所であることは、関数の名前から容易に推測できます。

URL です - isurlchar()

isurlchar() の中身を確認します。isurlchar()awffull.c の1899行目から定義されています。ソースコードから isurlchar() を探し出すには vim のタグジャンプを使うとすぐに見付かります。

1899 /*********************************************/
1900 /* ISURLCHAR - checks for valid URL chars    */
1901 /*********************************************/
1902
1903 int
1904 isurlchar(unsigned char ch)
1905 {
1906     if (isalnum((int) ch))
1907         return 1;                               /* allow letters, numbers...    */
1908     if (ch > 127)
1909         return 1;                               /* allow extended chars...      */
1910     return (strchr(":/\\.,' *-+_@~()[]", ch) != NULL);  /* and a few special ones */
1911 }

isurlchar() は見出しのコメントにあるように URL として妥当な文字かをチェックする関数です。URL 文字なら 1 を返しています。クエリの開始を表す ? は URL として妥当な文字とは判定されず、0 が返ります。


以上で URL からクエリ文字列を削除する、ひとつのパターンを学ぶことができました。



$Date: 2008-06-28 00:27:19 +0900 (Sat, 28 Jun 2008) $