綾小路龍之介の素人思考

Perl > Perl実験室でWeb雑考

このページでは、Webを漁りながら思ったことを書き留めていきます。


目次


1.1 imgタグのsrc属性に画像ファイルへのLocationヘッダを出力するcgiを指定する

よくあるアクセス解析は画像ファイルを読み込んで、Content-Type宣言とともに標準出力。ならばLocationヘッダで画像ファイルに飛ばせないかと考えた。まぁ世の中には賢い人がいるもので、この技術はすでにPerlで書かれた各種ダウンロードカウンタで上手くいくことが実証済みだった。要はアクセス解析なんてのは訪問者の知らないところで画像をダウンロードさせることでカウントしているわけ。ダウンロードカウンタの場合は訪問者のダウンロード要求を待ってダウンロードさせてるわけ。これを使えば別にわざわざcgiが画像ファイルを読み込んで云々する必要なんてどこにもないじゃないか。

もっと言ってしまえば、cgiの使えるサーバでなおかつLocationヘッダも出力できるなら、aタグのhref属性、cssの外部ファイル、JavaScriptの外部ファイル、とかもLocationヘッダを出力するcgiへのリンクにして、とにかく訪問者が自分のWebページ内で何をやったか全てを記録できてしまうんじゃないかと考えた。まぁここは実験室なんでそんなこともいいかなと。動作確認は取れていないけれどこんなところだろう。

open OUT,">>access.log";
print OUT join'',map{"$_ $ENV{$_}\n"}sort keys %ENV;
close OUT;

my %u = (
  'Gif'        => 'test_gif.gif',
  'Index'      => 'test_html.html',
  'JavaScript' => 'test_js.js',
  'CSS'        => 'test_css.css'
);

if (defined $ARGV[0] && defined $u{$ARGV[0]}){
  print "Location: $u{$ARGV[0]}";
} else {
  print "Location: $u{Index}";
}

結論から言えば、上のスクリプトは自分の環境(isweb,Windows Me,Internet Exprorer 6.0)のもとでは期待通りの挙動を示す。実際にこのサイトにあるいくつかのファイルは上のようなアクセスログ取得cgiを噛ませてブラウザに取得させている(上と全く同じではない)。言い換えれば、あるHTMLファイルに中に上の4つのファイルへのリンクがあった場合、これらをcgiファイルと対応した引数で書き換えることで、元のHTMLファイルをブラウザで開いた場合と全く同じように見えるということだ。これが効果的なものかどうかを検証せねばならない。アクセスログが取れるという点を除けば全く効果的ではない。100個のHTMLファイルに同じスタイルシートを適応した場合、このスタイルシートに向けてリンクが張られる。スタイルを変更する場合は現在適応されているスタイルシートを直接編集すればよいのであって、わざわざ上のようにして変更するメリットはないだろう。これは、JavaScriptや画像ファイルについても同様である。

上のようなスクリプトを介して実際のコンテンツに訪問者を誘導することは、HTMLファイルに含まれるimgタグ、scriptタグ、metaタグ、のような訪問者の許可無しにリンク先の内容をダウンロードさせるタグの回数だけcgiが呼び出されることになる。サーバーの仕事は2倍になるわけで、特にHTTP/1.0のConection: closeでコンテンツをダウンロードさせるようなブラウザを使っている場合、サーバに高負荷をかけることになるかもしれない

それでもなおメリットを探すとすれば、多少の取りこぼしはあるものの、サーバに記録されるのと同じようなアクセスログが取れるという点だろう。まともな解析を行えば、画像、JavaScript、スタイルシート、これらを訪問者がどのように処理しているかもおおよそのところわかる。例えば、あるHTMLファイル中に含まれるリンク(aタグのhref属性にはcgiを指定)を辿って別のHTMLファイルに移動し、移動先のHTMLファイルに画像(imgタグ)、JavaScript(scriptタグ)、スタイルシート(metaタグ)、をcgiを指定して仕込んでおいた場合、非常に短い時間間隔で同一のIPアドレスから4回cgiにアクセスがあれば、訪問者は画像、JavaScript、スタイルシート、を全て許可していることになる。

iswebが提供しているアクセス解析のログ保存期間は確か3ヶ月程度だと思ったが、このcgiスクリプトを噛ませると、ディスクスペースの許す限りアクセスログの保存ができる。上の例では環境変数をログファイルに保存するだけだが、例えばここでApacheのアクセスログと同じフォーマットを適応させれば、世の中に数多く存在するApacheのアクセス解析ソフトにアクセスログを読み込ませることができる。


1.2 適当なContent-Typeヘッダを吐くcgiを作ることでtextコンテンツをcgiから出力できるか

例えば、cgiからcssを出力する場合、Content-Typeを指定しなければならない。例えば、サーバーが適切にcssを処理できる場合、telnetを使ってしかるべき方法でcssファイルを取得すると、cssに対応したMIMEタイプがわかる(Content-Typeから始まる1行がhttpヘッダに付けられている。)。

telnet zatugakuou.hp.infoseek.co.jp 80
GET /cgi-bin/link2/test_css.css HTTP/1.0
Host: zatugakuou.hp.infoseek.co.jp

HTTP/1.1 200 OK
Date: Thu, 23 Feb 2006 16:50:19 GMT
Server: Apache
Last-Modified: Thu, 23 Feb 2006 08:36:45 GMT
ETag: "c69b1b-d8-43fd741d"
Accept-Ranges: bytes
Content-Length: 216
Connection: close
Content-Type: text/css

*{margin:0px;padding:0px;border:1px solid red;white-space: normal;}
body{background-color:Black;}
br{z-index:10;white-space:nowrap;letter-spacing: 0;clear: left; display:inline;position:absolute; top:0px; left:0px;}

ちなみに上のように入力しないと目的のコンテンツは得られない。というのも、共有サーバ上のデータなのでhostが必須となのである(あぁバーチャルホストの悲しさ)。試しにhost無しでGETを実行するとlocationヘッダとともに301が返される。加えて接続するホストをinfoseek.co.jpやwww.infoseek.co.jpに変えると、Host込みでgetを実行しても目的のコンテンツは得られない。また、infoseek.co.jpやwww.infoseek.co.jpはHTTP/1.0を返す。


1.3 URLエンコードと文字コードのお話GiRLFRieND


1.4 Googleトップページをtelnetで取るには?どうやらGoogleの認めたUser-Agentを吐かないとまずいらしい

telnet google.co.jp 80
GET / HTTP/1.1
Host: www.google.co.jp
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90)

telnet google.co.jp 80
GET http://www.google.co.jp/ HTTP/1.0
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Win 9x 4.90)

telnet zatugakuou.hp.infoseek.co.jp 80
GET / HTTP/1.1
Host: zatugakuou.hp.infoseek.co.jp
  1. メモ:PerlでURLエンコード・デコードはURI::Escapeを使う - hylom の日記

1.5 Jcode.pmで出力文字コードを引数で渡せないというのは本当か。

多分、半分本当で半分嘘だと思う。無料版iswebはJcode.pmを標準で実装していないので(Jcodeは設置済みでした(Jcode.pm v2.06)。use Jcode;で使えます。)Jcode.pm0.88をおいて実験してみたところ、次のようなことがわかった。1、出力文字コードは文字列または文字列を内容として持つスカラ変数で渡さねばならない。2、配列要素として渡すとエラーが生じる。つまり、下のように書いた場合は思ったとおりの結果が得られる。

my $str = '文字コード変換テスト';
my $OutCode = 'utf8';
print Jcode->new($str)->h2z->$OutCode;

ただし、次のように書いた場合は思い通りの結果が得られない($strをutf8に変換してくれない。)。エラーが生じる。

my $str = '文字コード変換テスト';
my $OutCode[0] = 'utf8';
print Jcode->new($str)->h2z->$OutCode[0];

例えば、引数を2つ要求する文字コード変換プログラムで、第1引数に変改対象のファイル名、第2引数に出力文字コード、がセットされているとする。このとき、下のようなコードを書いてみると上手くいかない。最初のセクションは引数の存在チェックと存在しない場合の初期値の設定である。第1引数がセットされていればこれを変換対象のファイルとし、そうでない場合は自分自身。第2引数がセットされていればこれを出力文字コードとし、そうでない場合はutf8。2番目のセクションで変換対象ファイルからデータをもらい$strに格納。3番目のセクションで文字コード変換を行って出力。

$ARGV[0] = defined $ARGV[0] ? $ARGV[0] : $0;
$ARGV[1] = defined $ARGV[1] ? $ARGV[1] : 'utf8';

open IN,$ARGV[0];
my $str = join'',<IN>;
close IN;

print "Content-Type: text/html\n\n";
print Jcode->new($str)->h2z->$ARGV[1];

この場合最後の行でエラーが生じる。これを回避するには前述のようにutf8などの出力文字コードを含む変数をスカラ変数として、配列要素とすることが肝心である。例えば以下のように書き換えれば思ったとおりに動く。これの欠点をあげるとするならば、メモリ上に余分な変数を作ることだろう。たった1回しか使わない$codeを全く同じ内容をもつ$ARGV[1]のコピーとしてわざわざ再定義するは、無駄なメモリを消費することにはならないのだろうか。

my $name = defined $ARGV[0] ? $ARGV[0] : $0;
my $code = defined $ARGV[1] ? $ARGV[1] : 'utf8';

open IN,$name;
my $str = join'',<IN>;
close IN;

print "Content-Type: text/html\n\n";
print Jcode->new($str)->h2z->$code;

Jcode.pmが内部でどのように動いているかはよく知らないが、少なくとも上で述べた問題を解決する策を一つ知っている。それはjcode.plで使われていたインターフェイスを使うことだ。例えば下のように。すると自分で定義した変数は$strだけとなり、メモリを余分に消費することもないと思う(もちろん引数に何が含まれているかを覚えておかねばならないが。)。

$ARGV[0] = defined $ARGV[0] ? $ARGV[0] : $0;
$ARGV[1] = defined $ARGV[1] ? $ARGV[1] : 'utf8';

open IN,$ARGV[0];
my $str = join'',<IN>;
close IN;

print "Content-Type: text/html\n\n";
print Jcode::convert(\$str, $ARGV[1]);

1.6 エラートラップ


1.7 ダイヤモンド演算子の中身は文字列でなければならないというのは本当かな


サイトマップ

  1. CSS > Webサイトのレイアウトの話
  2. DVDリッピングしてaviファイルにするときの計算方法
  3. Debian > インストールメモ
  4. Memo > One Line Diary
  5. Memo > To-Doリスト
  6. Memo > iswebの自動挿入広告の文字コードに関する考察
  7. Memo > リンクとメモ
  8. Memo > 物理屋の独り言
  9. Misc > High Performance Computing(HPC)
  10. PC過去の遺物集
  11. Perl > 1行スクリプト覚書 with Active Perl
  12. Perl > Perl実験室でWeb雑考
  13. Perl > XML::TreePPでXMLサイトマップファイルを生成
  14. Perl > e.cgi のページ ProjectRotation8
  15. Perl > クエリを連想配列で受け取るスマートな方法
  16. Perl > サーバーにアップロードしたcgiのエラーチェック
  17. Perl > ブリコラージュ的 cgi
  18. Programing > プログラムの素人が不思議に思ったこと
  19. Services > Gmail Tips
  20. Services > YourFileHostダウンローダ
  21. Services > twitterはじめました。
  22. Tech > MathMLを使ってみる
  23. Tech > Windows 2000 Professional でLaTeX組版システムを使う
  24. Tech > coLinuxの導入
  25. Tech > サイトのミラーリング
  26. Terapadで作るLaTeX統合環境
  27. Tools > Opera > 設定の諸々
  28. Tools > bashのメモ
  29. Tools > lit2ptoのページ
  30. Tools > vimの設定とtips
  31. Tools > よく使う機能のメモと設定のメモ
  32. VMware > ホストOSがWindows XP Home SP2でゲストOSがVine Linux 4.1
  33. Vine > SSHの暗号化経路を経由してSambaサーバの共有ディレクトリをマウント
  34. Vine Linux > LaTeXでpdf文書作成
  35. Vine Linux > Libretto L1に載せる
  36. Vine Linux > SSH関係の諸々メモ
  37. Vine Linux > サーバを立てたときのメモ
  38. Vine Linux > ソフトウェアRAID
  39. Vine Linux > デスクトップとして使う場合に必要な設定
  40. Wanderlust > inter7でIMAP4
  41. Web Etcetera > サーバー上でファイルを直接編集することについて
  42. Web Etcetera > 検索エンジンが自分のサイトをどのように認識しているか
  43. Web Etcetera > 無料ホームページスペースの広告削除は真か偽か
  44. Winamp > StreamRipperで全自動リッピング
  45. Winamp > タスクマネージャを使って目覚まし時計
  46. Windows > robocopyでフォルダ間同期
  47. Windows > 手動でコーデックをインストールする
  48. gnuplotのプロットギャラリー
  49. rsyncでディレクトリの内容を同期する
  50. wgetのメモ
  51. ネットワーク上にメモ帳を置く
  52. ハードウェア > HDDの再利用
  53. ハードウェア > 安定で快適なマシンはハードから
  54. ブリコラージュ的メールマガジン一括登録解除方法
  55. 初めに
  56. 情報基礎演習UNIX
  57. 窓たちと正く付き合うにはショートカットキーから

コメント


pin

[PR]ÓeOȂœ܂񂩁H:S19@tŌtقW