perlの学習書のサンプルコードは実行できるが、僕が手入力した実行ファイルはソースがそのまま表示されて原因が分かりません
- 評価
- クリップ 0
- VIEW 1,578
お世話になっております。
ただいまperlを学習書を用いて勉強しているのですが、学習書のサンプルコードはレンタルサーバーにアップロードして動くのですが、僕が入力して作成したperlの実行ファイルはレンタルサーバーにアップロードして、ページを表示させると、多分途中まで動いているのではないかと思いますが、HTMLを吐く部分でソースがそのまま表示されてしまいます。ちなみにこの僕が自分で作成した実行ファイルですが、レンタルサーバーではなく、自分のパソコンのLinux上ではきちんとHTMLが表示されます。
改行コードの問題かとも思いましたので、一応エディタで改行コードをLF(UNIX)で保存して、バイナリモードでアップロードしました。しかし相変わらず、ソースが表示されてしまいます。
このソースが表示されてしまうファイル名が「6-4.cgi」という名前ですが、レンタルサーバー上でこのファイルと同一ディレクトリにある「6-3.cgi」という6-4.cgiより少し、コードが少ないcgiファイルは実行できます。
パーミッションの問題かと思いましたのでパーミッションをレンタルサーバーが推奨している値に変更しても駄目でした。
以下にコードの内容を載せます。
#!/usr/bin/perl
# 僕が本を見ながら手で入力したコードでファイル名は6-4.cgi
# ===================== ユーザー設定 ==============
$CHARSET = 'UTF-8'; #文字コード
$USERFILE = './users.dat'; #ユーザファイル
$ADMINPASS = 'goma'; # 管理パスワード
# ===================== メインプログラム ==========
loadFormdata();
if(not exists $FORM{'adminpass'}){
printGatePage();
}
elsif($FORM{'adminpass'} eq $ADMINPASS){
loadUserfile();
if($FORM{"mode"} eq "adduser"){
addUser();
}
elsif($FORM{'mode'} eq "deluser") {
deleteUser();
}
printAdminPage();
}
else{
printErrorPage("管理パスワードが違います。");
}
exit;
#======================= ユーザー追加 ==============
sub addUser
{
my ($name, $pass) = ($FORM{'user'}, $FORM{'pass'});
my ($salt, $saltset, $n1, $n2);
if(exists $USERS{$name}) {
printErrorPage("そのユーザ名はすでに存在しています。1");
}
$USERS{$name} = $pass;
# パスワードの暗号化
$saltset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789./";
$n1 = int(rand 64);
$n2 = ($n1 + time) % 64;
$salt = substr($saltset, $n1, 1) . substr($saltset, $n2, 1);
$pass = crypt($pass, $salt);
# ユーザーファイル書き込み
open(FILE, ">>$USERFILE")
or printErrorPage("ユーザーファイルが開けません。1");
print FILE "$name:$pass\n";
close(FILE);
}
#=========================== ユーザー削除 ==============
sub deleteUser
{
my ($key, $name);
foreach $key (keys %FORM) {
if($key =~ /del_(.+)/) {
delete $USERS{$1};
}
}
# ユーザーファイル書き込み
open(FILE, ">$USERFILE")
or printErrorPage("ユーザーファイルが開けません。2");
foreach $name (keys %USERS) {
print FILE "$name:$USERS{$name}\n";
}
close(FILE);
}
# ===================== ユーザーファイル読み込み ==
sub loadUserfile
{
my ($ln, $name, $pass);
open(FILE, "<$USERFILE")
or printErrorPage("ユーザーファイルが開けません。3");
while($ln = <FILE>) {
chomp $ln;
($name, $pass) = split(/:/, $ln);
$USERS{$name} = $pass;
}
close(FILE);
}
#======================= 管理パスワードページ出力 ==
sub printGatePage
{
# print "aaa";
print <<END;
Content-type: text/html;
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<head><title>ゆーざかんり</title></head>
<body>
<h1>ユーザ管理</h1>
<form acction="aaa" method="POST">
管理パスワード:<input type="password" name="adminpass"><br>
<input type="submit" value="決定">
</form>
</body>
</html>
END
}
#======================= ユーザ管理ページ出力 ======
sub printAdminPage
{
my $name;
print <<END;
Content-type: text/html; charset=$CHARSET
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<head><title>ゆーざかんり</title></head>
<body>
<h1>ユーザ管理</h1>
<h2>新規ユーザ登録</h2>
<form action="$ENV{'SCRIPT_NAME'}" method="POST">
ユーザ名:<input type="text" name="user"><br>
パスワード:<input type="password" name="pass"><br>
<input type="hidden" name="mode" value="adduser">
<input type="hidden" name="adminpass" value="$ADMINPASS">
<input type="submit" value="登録する">
</form>
<hr>
<h2>ユーザ削除</h2>
<form action="$ENV{'SCRIPT_NAME'}" method="POST">
<table border="1">
<tr><th>削除チェック</th><th>ユーザ名</th></tr>
END
foreach $name (sort keys %USERS) {
print "<tr><td><input type=\"checkbox\" name=\"del_$name\"></td><td>$name</td></tr>\n";
}
print <<END;
</table>
<input type="hidden" name="mode" value="deluser">
<input type="hidden" name="adminpass" value="$ADMINPASS">
<input type="submit" value="削除する">
</form>
</body>
</html>
END
}
#============================エラーページ出力========
sub printErrorPage
{
print <<END;
Content-type: text/html; charset=$CHARSET
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<head><title>ゆーざかんり</title></head>
<body>
<h1>エラー</h1>
<p>$_[0]</p>
</body>
</html>
END
exit;
}
#========================= フォームデータ取り込み =====
sub loadFormdata
{
my ($query, $pair);
if($ENV{'REQUEST_METHOD'} eq 'POST') {
read(STDIN, $query, $ENV{'CONTENT_LENGTH'});
}
else {
$query = $ENV{'QUERY_STRING'};
}
foreach $pair (split(/&/, $query)) {
my ($key, $value) = split(/=/, $pair);
$value =~ tr/+/ /;
$value =~ s/%([0-9a-fA-F][0-9a-fA-F])/chr(hex($1))/eg;
$FORM{$key} = $value;
}
}
コード
次は学習書についてた(実行できた)サンプルコード
#!/usr/bin/perl
#============================ ユーザー設定 ====
$CHARSET = 'Shift_JIS'; # 文字コード
$USERFILE = './users.dat'; # ユーザーファイル
$ADMINPASS = 'goma'; # 管理パスワード
#======================== メインプログラム ====
loadFormdata();
if(not exists $FORM{'adminpass'}) {
printGatePage();
}
elsif($FORM{'adminpass'} eq $ADMINPASS) {
loadUserfile();
if($FORM{"mode"} eq "adduser") {
addUser();
}
elsif($FORM{'mode'} eq "deluser") {
deleteUser();
}
printAdminPage();
}
else {
printErrorPage("管理パスワードが違います。");
}
exit;
#============================ ユーザー追加 ====
sub addUser
{
my ($name, $pass) = ($FORM{'user'}, $FORM{'pass'});
my ($salt, $saltset, $n1, $n2);
if(exists $USERS{$name}) {
printErrorPage("そのユーザー名はすでに存在しています。");
}
$USERS{$name} = $pass;
# パスワードの暗号化
$saltset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789./";
$n1 = int(rand 64);
$n2 = ($n1 + time) % 64;
$salt = substr($saltset, $n1, 1) . substr($saltset, $n2, 1);
# $pass = crypt($pass, $salt);
# ユーザーファイル書き込み
open(FILE, ">>$USERFILE")
or printErrorPage("ユーザーファイルが開けません。");
print FILE "$name:$pass\n";
close(FILE);
}
#============================ ユーザー削除 ====
sub deleteUser
{
my ($key, $name);
foreach $key (keys %FORM) {
if($key =~ /del_(.+)/) {
delete $USERS{$1};
}
}
# ユーザーファイル書き込み
open(FILE, ">$USERFILE")
or printErrorPage("ユーザーファイルが開けません。");
foreach $name (keys %USERS) {
print FILE "$name:$USERS{$name}\n";
}
close(FILE);
}
#================ ユーザーファイル読み込み ====
sub loadUserfile
{
my ($ln, $name, $pass);
open(FILE, "<$USERFILE")
or printErrorPage("ユーザーファイルが開けません。");
while($ln = <FILE>) {
chomp $ln;
($name, $pass) = split(/:/, $ln);
$USERS{$name} = $pass;
}
close(FILE);
}
#================ 管理パスワードページ出力 ====
sub printGatePage
{
print <<END;
Content-type: text/html; charset=$CHARSET
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<head><title>ゆーざーかんり</title></head>
<body>
<h1>ユーザー管理</h1>
<form action="$ENV{'SCRIPT_NAME'}" method="POST">
管理パスワード:<input type="password" name="adminpass"><br>
<input type="submit" value="決定">
</form>
</body>
</html>
END
}
#================== ユーザー管理ページ出力 ====
sub printAdminPage
{
my $name;
print <<END;
Content-type: text/html; charset=$CHARSET
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<head><title>ゆーざーかんり</title></head>
<body>
<h1>ユーザー管理</h1>
<h2>新規ユーザー登録</h2>
<form action="$ENV{'SCRIPT_NAME'}" method="POST">
ユーザー名:<input type="text" name="user"><br>
パスワード:<input type="password" name="pass"><br>
<input type="hidden" name="mode" value="adduser">
<input type="hidden" name="adminpass" value="$ADMINPASS">
<input type="submit" value="登録する">
</form>
<hr>
<h2>ユーザー削除</h2>
<form action="$ENV{'SCRIPT_NAME'}" method="POST">
<table border="1">
<tr><th>削除チェック</th><th>ユーザー名</th></tr>
END
foreach $name (sort keys %USERS) {
print "<tr><td><input type=\"checkbox\" name=\"del_$name\"></td><td>$name</td></tr>\n";
}
print <<END;
</table>
<input type="hidden" name="mode" value="deluser">
<input type="hidden" name="adminpass" value="$ADMINPASS">
<input type="submit" value="削除する">
</form>
</body>
</html>
END
}
#======================== エラーページ出力 ====
sub printErrorPage
{
print <<END;
Content-type: text/html; charset=$CHARSET
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<head><title>ゆーざーかんり</title></head>
<body>
<h1>エラー</h1>
<p>$_[0]</p>
</body>
</html>
END
exit;
}
#================== フォームデータ取り込み ====
sub loadFormdata
{
my ($query, $pair);
if($ENV{'REQUEST_METHOD'} eq 'POST') {
read(STDIN, $query, $ENV{'CONTENT_LENGTH'});
}
else {
$query = $ENV{'QUERY_STRING'};
}
foreach $pair (split(/&/, $query)) {
my ($key, $value) = split(/=/, $pair);
$value =~ tr/+/ /;
$value =~ s/%([0-9a-fA-F][0-9a-fA-F])/chr(hex($1))/eg;
$FORM{$key} = $value;
}
}
コード
具体的に何が違って自分の実行ファイルが実行できないのか(ソースが表示されてしまうのか)に興味があります。
ちなみにソースが表示されたときの画面をキャプチャしました。
ほかにも関連がありそうなこととして同一ディレクトリ内に.htaccessファイルがあります。.htaccessの内容は
Options -Indexes
<Files users.dat>
deny from all
</Files>
です。
やはり改行コードが原因かもしれないですが、ちょっと僕のほうではエディタでLFで保存してバイナリモードでアップするくらいしか対処が思い浮かばないです。
どなたか原因を思い当たる方がいれば教えていただければと思います。
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
checkベストアンサー
+1
print "Content-type: text/html; charset=utf-8\n\n";
print <<END;
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
以下略
っていう風にしてみてはどうでしょうか?
なんだかContent-typeの前の改行が良くないような気がします。
または、サーバーがutf-8に対応していない可能性も考えて
print "Content-type: text/html;charset=Shift_JIS\n\n";
print <<END;
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
というパターンも試してみたいです。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
+1
ざっと見たところでは、
print <<END;
とContent-type: text/html; charset=$CHARSET
の間に空行があるところが問題では。
空行があるのでヘッダーが無いとみなされてHTMLとして認識されず、ヘッダー無しでHTMLがテキストファイルとして送出されてしまっているのではないでしょうか。
Content-type: text/html
が重要で、このファイルがHTMLファイルであることをブラウザーに知らせています。
これが認識されないとHTMLとしてレンダリングされません。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.32%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
2016/05/28 02:04 編集
oskbt様のおっしゃった方法で見事HTMLページが表示されました。ちなみに下記のようにしました。
#======================= 管理パスワードページ出力 ==
sub printGatePage
{
print "Content-type: text/html; charset=utf-8\n\n";
print <<END;
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<head><title>ゆーざかんり</title></head>
自分のパソコンのLinux上ではうまく動くのにレンタルサーバーでは文法的に間違ってないっぽいのに動かない原因がちんぷんかんぷんなのですが、とりあえず、
Content-type: text/html; charset=utf-8
はしっかり送っとけというのが今回の質問の大きな収穫だったように思います。
どうもありがとうございました。
追記
>または、サーバーがutf-8に対応していない可能性も考えて
問題が解決されたことを確認しましたし、レンタルサーバーがutf-8で動作していることは確認済みなので、Shift_JISは確認しておりません。