![](http://oshiete.xgoo.jp/images/v2/pc/qa/question_title.png?e8efa67)
CGIプログラミング第2版を読みながらCGIを学習しています。
11章 "ステートの保持"の11.1 クエリ文字列とパス情報の例題ではまっております。。。
これはURLに識別子を埋め込んでユーザーを追跡するという、超ハイテクなスクリプトです。
とりあえず、記載されているとおりにスクリプトを作成してHTMLファイルも用意しました。
HTMLファイルの内容は超簡単で
<HTML><HEAD><TITLE>store</TITLE></HEAD><BODY><A href="abc.html">abc</A></BODY></HTML>
です。
これでユーザーがhttp://ウェブサーバー/store/下のファイルをリクエストすると、自動的にスクリプトが実行され、カスタマイズされたHTMLファイルが返されるという仕様です。
実際に返されたHTMLファイルを見てみると
<HTML><HEAD><TITLE>store</title></head><BODY>
なんと<A>タグ以降がばっさり切り落とされていました^^
しかもタグは全部大文字で書いたのに一部小文字になっていたりと、意味不明な状況です。
たぶんHTML::Parserなるものが、いろいろHTMLファイルを操作しているとは思うのですが、今回返されたHTMLはどう見ても壊れているような・・・。
No.1ベストアンサー
- 回答日時:
CGIプログラミングってオライリーの、表紙がネズミの本ですか?
だとするとこの本の邦訳は相当古いものになってしまっているので、
使っているHTML::Parserのバージョン違いによるものかもしれません。
><HTML><HEAD><TITLE>store</TITLE></HEAD><BODY><A href="abc.html">abc</A></BODY></HTML>
これはHTML4あたりだと不正なHTMLではないですか?
bodyのすぐ下に直接テキストを置くことはできなかったはずです。
HTML::Parserに対して想定するHTMLのバージョンを指定できたと
思うので、マニュアルを見て(perldoc HTML::Parser)、
2.0あたりのHTMLを指定して試してみてください。
この回答への補足
sakusaker7さん、ご返信ありがとうございます。
オライリーの本は表紙といい、内容といい、硬派な感じがして好きなのです^^
HTML::ParserでHTMLのバージョンを指定することは断念しましたが、
HTMLの構文チェックサイトの力を借りて、ちゃんとパースできるようにHTMLを修正しました。
これにより何とか意図どおりにカスタマイズされたHTMLが返ってくるようになりました!
しかし、そのページからリンク先へ飛ぶことができません。
多分スクリプトがURLに自動的に識別氏を埋め込んでしまい、そのようなアドレスが存在しないためだと思います。
<A href="/store/abc.html">
↓
<A href="/store/ウェブサーバーが生成したユニークな文字列/abc.html">
このようになってしまい、用意したabc.htmlへは飛べません!!
ここで失礼して禁断のコード貼り付けをさせてください。
まずはURLを操作するモジュール"UserTracker.pm"のソースコードです。
#!/usr/bin/perl -wT
#/----------------------------------------------------------------
# UserTrackerモジュール
#
# HTML::Parserを継承
#
#
package CGIBook::UserTracker;
push @ISA, "HTML::Parser";
use strict;
use URI;
use HTML::Parser;
1;
#/----------------------------------------------------------------
# Publicメソッド
#
sub new {
my( $class, $path ) = @_;
my $id;
if ( $ENV{PATH_INFO} and
$ENV{PATH_INFO} =~ s|^/\.([a-z0-9_.-]*)/|/|i ) {
$id = $1;
}
else {
$id ||= unique_id( );
}
my $self = $class->SUPER::new( );
$self->{user_id} = $id;
$self->{base_path} = defined( $path ) ? $path : "";
return $self;
}
sub base_path {
my( $self, $path ) = @_;
$self->{base_path} = $path if defined $path;
return $self->{base_path};
}
sub user_id {
my $self = shift;
return $self->{user_id};
}
#/----------------------------------------------------------------
# 内部(Private)サブルーチン
#
sub unique_id {
# Apacheのmod_unique_idが使用可能であればこれを使用する
return $ENV{UNIQUE_ID} if exists $ENV{UNIQUE_ID};
require Digest::MD5;
my $md5 = new Digest::MD5;
my $remote = $ENV{REMOTE_ADDR} . $ENV{REMOTE_PORT};
# 次のコードはユニークなIDの作成が目的(セキュアではない)
# 機密データのキー生成には使用しないこと
my $id = $md5->md5_base64( time, $$, $remote );
$id =~ tr|+/=|-_.|; # 非ワード文字をURLに使える文字に変換
return $id;
}
sub encode {
my( $self, $url ) = @_;
my $uri = new URI( $url, "http" );
my $id = $self->user_id( );
my $base = $self->base_path;
my $path = $uri->path;
$path =~ s|^$base|$base/.$id| or
die "設定されたベースパスが無効です\n";
$uri->path( $path );
return $uri->as_string;
}
#/----------------------------------------------------------------
# HTML::Parserのコールバックを実装するサブルーチン
#
sub start {
my ( $self, $tag, $attr, $attrseq, $origtext ) = @_;
my $new_text = $origtext;
my %relevant_pairs = (
frameset => "src",
a => "href",
area => "href",
form => "action",
# 画像データも追跡する場合は、次の2行の先頭の#を削除する
# img => "src",
# body => "background",
);
while ( my( $rel_tag, $rel_attr ) = each %relevant_pairs ) {
if ( $tag eq $rel_tag and $attr->{$rel_attr} ) {
$attr->{$rel_attr} = $self->encode( $attr->{$rel_attr} );
my @attribs = map { "$_=\"$attr->{$_}\"" } @$attrseq;
$new_text = "<$tag @attribs>";
}
}
# リフレッシュを指定するMETAタグは形式が異なるのでここで別に処理
if ( $tag eq "meta" and $attr->{"http-equiv"} eq "refresh" ) {
my( $delay, $url ) = split ";URL=", $attr->{content}, 2;
$attr->{content} = "$delay;URL=" . $self->encode( $url );
my @attribs = map { "$_=\"$attr->{$_}\"" } @$attrseq;
$new_text = "<$tag @attribs>";
}
print $new_text;
}
sub declaration {
my( $self, $decl ) = @_;
print $decl;
}
sub text {
my( $self, $text ) = @_;
print $text;
}
sub end {
my( $self, $tag ) = @_;
print "</$tag>";
}
sub comment {
my( $self, $comment ) = @_;
print "<!--$comment-->";
}
続いて、ユーザーがhttp://ウェブサーバー/store/下のファイルをリクエストしたときに自動的に実行されるCGIスクリプト"query_track.cgi"です。
#!/usr/bin/perl -wT
use strict;
use CGIBook::UserTracker;
local *FILE;
my $track = new CGIBook::UserTracker;
$track->base_path( "/store" );
my $requested_doc = $ENV{PATH_TRANSLATED};
unless ( -e $requested_doc ) {
print "Location: /errors/not_found.html\n\n";
}
open FILE, $requested_doc or die "$requested_docのオープンに失敗しました: $!";
my $doc = do {
local $/ = undef;
<FILE>;
};
close FILE;
# HTMLファイルのみを追跡することが前提
print "Content-type: text/html\n\n";
$track->parse( $doc );
続いて、私が作成したHTMLファイルです。
<html lang="ja">
<head>
<META http-equiv="Content-Type" content="text/html; charset=EUC-JP">
<title>store</title>
</head>
<body>
<a href="/store/abc.html">abc</a>
</body>
</html>
このページのabcというリンクをクリックすると/stroe/.XXXXXXXXXXXXXXXXXXXXXX/abc.htmlのような感じでリクエストしてしまい、ノットファウンドになってしまうのです。
sakusaker7さん、もしお暇な時間があれば、このスクリプトを叩いてもらって、どこが悪いか教えてほしいです!!!!!
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- HTML・CSS cssが効かなくて困ってます 1 2023/01/01 23:57
- PHP PHPプログラムの間違い 1 2022/10/06 14:33
- HTML・CSS HTMLタグのあるCSVファイルを利用する方法 4 2023/03/19 14:41
- PHP htmlspecialcharsが機能していないです。 バグですか? 1 2022/04/05 01:22
- HTML・CSS CSSが上手く反映されないみたいです 2 2022/11/21 16:19
- PHP php ログイン 1 2022/11/01 00:24
- JavaScript HTMLでJavaScriptを使ってパスワードの強化判定のプログラムを作成しています。 一通り作っ 2 2022/10/19 01:41
- JavaScript jqueryを使ったスムーススクロールのコードを書いたのですが、HTMLコード内にある、a butt 2 2022/04/14 10:59
- Excel(エクセル) PHPプログラムをエクセルに張り付けると検索ボックスがでてくる! 3 2022/05/08 07:10
- CGI perlで書いたcgiでsqliteの使い方を教えてください 2 2023/05/08 21:29
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
#include <Windows.h>というヘ...
-
.NETアプリを作ったときの .man...
-
アクセス 壊れた? 「ファイ...
-
binファイルを解凍したいの...
-
ファイルが開かれているかどう...
-
コマンドプロンプトで、指定し...
-
exeファイルの中身を見る方法は...
-
公文書のxmlファイルの開き方が...
-
2つのファイルのバイナリをコン...
-
jarファイル
-
エクセルファイルが複数同時に...
-
VBAのバイナリ出力について
-
C言語---ファイルに出力したデ...
-
Latexで図番号だけを「図1.1」...
-
「ブルーファイル」と「グリー...
-
CSSを1ページに1枚作るのって変...
-
VBで「.tif」または「.pdf」...
-
WebグループウェアのDB移行
-
warファイルをEclipseでプロジ...
-
ELFファイルを逆コンパイルした...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
アクセス 壊れた? 「ファイ...
-
C#でログファイルにファイルパ...
-
binファイルを解凍したいの...
-
#include <Windows.h>というヘ...
-
Latexで図番号だけを「図1.1」...
-
.NETアプリを作ったときの .man...
-
exeファイルの中身を見る方法は...
-
C言語---ファイルに出力したデ...
-
CSSを1ページに1枚作るのって変...
-
jarファイル
-
コマンドプロンプトで、指定し...
-
自分で作成した重要ファイルを...
-
コマンドプロンプトで作成日時...
-
バッチ処理で追記コピーしたい
-
ファイルが開かれているかどう...
-
VBSが起動しない
-
公文書のxmlファイルの開き方が...
-
監視ツールを入れさせられまし...
-
Seasar2のdiconファイルの読み方
-
ファイル名にドットを使ったフ...
おすすめ情報