リクエストヘッダとレスポンスヘッダの関係
リクエストヘッダとレスポンスヘッダは一つのコネクションにおいて対となっているため、$IHDR と $OHDR を併用したフィルタを作成することが可能。例えば User-Agent に "iTunes" という文字列を含み、かつレスポンスデータがイメージファイルの場合は
$OHDR(User-Agent:*iTunes*) $IHDR(Content-Type:image/*)
を IN のヘッダフィルタで有効にすればよい。
コマンドの否定
(^$command) という形式で指定することが出来る。
(^$IHDR(Content-Type:image/*))
上記は「レスポンスデータがイメージファイル以外」にマッチする。
$TST による文字列の部分取り出し (1)
以下の $TST コマンドは文字列の比較ではなく、マッチした文字列の代入を行う。
$SET(x=a:foo&b:bar)
$TST(x=a:\1\&b:\2)
\1 には "foo" が、\2 には "bar" がそれぞれ格納される。ただし以下の場合、"b:" がなく。マッチに失敗するため処理が途中で止まってしまう。
$SET(x=a:foo&c:bar)
$TST(x=a:\1\&b:\2)
$ALERT(\1)
$ALERT(\2)
これを $TST の実行結果に拘わらず処理を継続させたい場合は次のように書くと良い。
$SET(x=a:foo&c:bar)
($TST(x=a:\1\&b:\2)|)
$ALERT(\1)
$ALERT(\2)
$TST による文字列の部分取り出し (2)
たとえマッチに成功したとしても、マッチ部分が空文字列となるバッファ変数は更新されない。
$SET(x=ABC)
$SET(0=foobar)
($TST(x=\0)|)
$LOG(R\\0:\0)
$SET(x=ABC)
$SET(0=foobar)
($TST(x=A\0)|)
$LOG(R\\0:\0)
$SET(x=ABC)
$SET(0=foobar)
($TST(x=ABC\0)|)
$LOG(R\\0:\0)
最初の二つは期待通りに動作するが、最後の例では \0 は更新されず $TST 前の値が保持されている。よって空文字列の場合も同様に取り出したいのであれば、あらかじめ \0 を初期化しておく必要がある。
$SET(x=ABC)
$SET(0=)
($TST(x=\0)|)
$LOG(R\\0:\0)
$SET(x=ABC)
$SET(0=)
($TST(x=A\0)|)
$LOG(R\\0:\0)
$SET(x=ABC)
$SET(0=)
($TST(x=ABC\0)|)
$LOG(R\\0:\0)
ただしこれにはバグがあるので注意。詳細は次項にて。
$SET で初期化した値は $TST できない
以下は困った仕様である。\0 には "foobar" が格納されているのにもかからわずマッチしない。
$SET(0=foobar)
$LOG(R\\0:\0)
($TST(\0=foobar)$LOG(Rtrue)|$LOG(Rfalse))
次のような回りくどい方法を取ると正しく動作する。
$SET(s=foobar)
$TST(s=\0)
$LOG(R\\0:\0)
($TST(\0=foobar)$LOG(Rtrue)|$LOG(Rfalse))
しかし空文字列を指定すると $TST は false となる。
$SET(s=)
$TST(s=\0)
変数に格納された文字列を $TST で比較する
通常変数が格納するデータを受け取るには $GET(変数名) を使うが、$TST の検索文字列部には使用できない。この場合、$TST(変数名) とすることで変数内のデータを検索文字列の一部に使うことができる。
$SET(name=ptron)
$SET(text=xtron,ptron,wtron,ztron)
$TST(text=*$TST(name)*)
$JMUP と $RDIR の違い
$JUMP は Location ヘッダを返し、クライアントにリダイレクトさせる(非透過的)。
$RDIR は Ptron がリダイレクトし、その結果をクライアントに返す(透過的)。
$JUMP を用いた場合、以下のようなフィルタでは問題が起こる場合がある。
$URL((*foo=0*)\1) $JUMP(\1&bar=1)
クライアントにリダイレクトさせる URL には常に foo=0 が存在するため、
リダイレクトのたびに上記のフィルタがマッチしてしまう。
つまりクライアント側でリダイレクト回数の上限が設定されていない場合、
Ptoron とクライアント間でリダイレクトの永久ループが発生することになる。
通常はそのような問題を避けるため、$RDIR を使うほうが良さそうだ。
$URL((*foo=0*)\1) $RDIR(\1&bar=1)
$RDIR コマンドは Ptron がリダイレクト処理を行うため、
クライアントとの間でリダイレクトのループは発生しない。
コマンドの指定順
コマンドを使用するときに気をつけたいのはその指定順。例えば XXX という文字列を YYY という文字列に置換し、マッチするたびにダイアログを表示するフィルタを考えてみる。
[Patterns]
Name = "Test"
Active = TRUE
URL = "foobar.com"
Limit = 256
Match = "XXX $ALERT(matched!)"
Replace = "YYY"
上記は期待通りに動作するはずである。しかし Ptron は基本的にグローバルマッチのため、次のように書いてしまうとゼロ文字幅アサーションである $ALERT コマンドが常に空文字列とマッチしてしまい、何度もダイアログが表示されてしまう。
[Patterns]
Name = "Test"
Active = TRUE
URL = "foobar.com"
Limit = 256
Match = "$ALERT(matched!) XXX"
Replace = "YYY"
ただし空文字列とマッチした場合でも検索開始インデックスは 1バイトずつ進むようなので、永久ループに陥ることは無い。それでも 1KB のページであれば千回以上表示されるわけで、永久ループとほとんど変わりないことは事実である。
単に $ALERT を実行したいだけなら
$ALERT(TEST) $STOP()
と記述する方法もある。
$DTM
$DTM には2桁の月と日が用意されていないが、以下のフィルタを適用することで、それぞれ $GET(M) と $GET(D) で参照できるようになる。
$SET(M=$DTM(M)) ($TST(M=[#1-9]) $SET(M=0$GET(M)) |)
$SET(D=$DTM(D)) ($TST(D=[#1-9]) $SET(D=0$GET(D)) |)
$ALERT($DTM(Y)/$GET(M)/$GET(D) $DTM(T))
$UESC の仕様
半角スペースはデコードされないため %20 がそのまま残ってしまう。つまり
$UESC($ESC(%20 %20))
をテストすると
%20%20%20
が返される。誠にもって残念な仕様である。
はてな?
最終更新:2009年05月16日 11:45