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

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


キーワードは strip

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

speirs@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 からクエリ文字列を削除する、ひとつのパターンを学ぶことができました。


最終更新日: 2015年05月16日(土)


Back to top