プロが教える店舗&オフィスのセキュリティ対策術

perlにてcgiを勉強しようと初掲示板を作ってみました。
しかし、日本語を入力すると文字化けしてしまいます。
また、入力フォームの下に[1~][11~][21~][最新10件]のようなリンクを付けたいです。
以上2点のやり方を教えて下さい。お願いします。

#!/usr/bin/perl -w

use strict;
use warnings;
use Encode;
use utf8;
use CGI;

print "location: ./bbs.html\n\n";
print "Content-type: text/html\n\n";

my $q = new CGI;
my $name = $q->param('name');
my $body = $q->param('body');

$name =~ s/</&lt;/g;
$name =~ s/>/&gt;/g;
$body =~ s/</&lt;/g;
$body =~ s/>/&gt;/g;
$body =~ s/\n/<br \/>/g;

my($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(time);
$year += 1900;
$mon += 1;
$wday = sprintf("%s", qw(日 月 火 水 木 金 土)[$wday]);
my $time = sprintf "$year/%02d/%02d($wday) %02d:%02d:%02d",$mon,$mday,$hour,$min,$sec;

open LOG, ">> log.txt";
print LOG "$time<>$name<>$body\n";
open LOG, "< log.txt";
my @log = <LOG>;
close LOG;

open HTML, "> bbs.html";
print HTML << "END";
<html>
<head>
<style>
body{background:#f0f0f0;}
span.name{color:blue;}
p.body{margin-left:32px;}
</style>
<script type="text/javascript">
<!--
function check(form){
function id(id){return(document.getElementById(id));}
if(form.name.value == "" || form.body.value == ""){
id('err').innerHTML = "入力に誤りがあります<br />";
id('err').style.color = "red";
return false;
}else{
return true;
}
}
//-->
</script>
<title>簡易掲示板</title>
</head>
<body>
<form action="bbs.cgi" method="post" onsubmit="return check(this)">
<fieldset>
<legend>入力フォーム</legend>
<span id="err"></span>
<label>名前</label><br />
<input type="text" name="name" /><br />
<label>本文</label><br />
<textarea name="body"></textarea><br />
<input type="submit" value="書き込み" />
</fieldset>
</form>
<hr />
END
close HTML;

open HTML, ">> bbs.html";
my $num = 0;
for(@log){
$num++;
chomp($_);
my @write = split /<>/, "$_";
print HTML "<p>$num:<span class='name'>$write[1]</span> $write[0]</p>\n<p class='body'>$write[2]</p>\n";
}

print HTML << "END";
<hr />
<a href="dammy">TOP</a>
</body>
</html>
END
close HTML;

exit;

よろしくお願いします。

A 回答 (3件)

考えられるのは


・CGI->paramで受け取った文字列の扱い方が正しくない
・ファイルの入出力が正しくない
の2点です。

前者は$name,$body両方を、バイト列からutf8フラグ付き文字列へと変換します。
次の記事が参考になると思います。
http://blog.livedoor.jp/dankogai/archives/512270 …


後者は、ファイル入出力時の文字コードを指定するようにします。
次の記事が参考になると思います。
http://www.rwds.net/kuroita/program/Perl_unicode …
特に「UTF8フラグとPerlIOレイヤ」「Wide character in print ...」が今回の件にあてはまるでしょう。

追加で
>print "Content-type: text/html\n\n";

print "Content-type: text/html;charset=utf-8\n\n";
として、文字コードを指定するといいかもしれません。

この回答への補足

回答ありがとうございます。早速教えていただいたURLを見ながらソースをいじってみたのですが、うまくいきませんでした…。

26行目の
$wday = sprintf("%s", qw(日 月 火 水 木 金 土)[$wday]);
この部分の、曜日を英語表記にして、

81行目の
print HTML "<p>$num:<span class='name'>$write[1]</span> $write[0]</p>\n<p class='body'>$write[2]</p>\n";
この部分の「:」を消せばフォームから送信した日本語もちゃんと文字化けしないで表示することができます。


ですが、曜日は日本語にしたいし「:」も消したくないので、教えて頂いたURLを参考に、
use open ":utf8";
を加えて、
print "Content-type: text/html;charset=utf-8\n\n";
にもしてみました。
$name = encode("utf-8",$name);
とかも試してみましたが、どれもうまくいきません。

これは何が原因なのでしょうか?
どうか教えて下さい。よろしくお願いします。

補足日時:2010/04/17 12:14
    • good
    • 0

文字化けの原因は utf8.pm にあります。

use utf8 は必要無いです。

#!/usr/bin/perl -w

use strict;
use warnings;
use Encode;
# use utf8;
use CGI;
print "location: ./bbs.html\n\n";
print "Content-type: text/html; charset=UTF-8\n\n";
my $q = new CGI;
my $name = $q->param('name');
my $body = $q->param('body');
if($name&&$body){
 $name =~ s/</&lt;/g;
 $name =~ s/>/&gt;/g;
 $body =~ s/</&lt;/g;
 $body =~ s/>/&gt;/g;
 $body =~ s/(\x0D\x0A|[\x0A\x0D])+$//;
 $body =~ s/\x0D\x0A|[\x0A\x0D]/<br>/g;
 my($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(time);
 $year += 1900;
 $mon += 1;
 $wday = sprintf("%s", qw(日 月 火 水 木 金 土)[$wday]);
 my $time = sprintf "$year/%02d/%02d($wday) %02d:%02d:%02d",$mon,$mday,$hour,$min,$sec;
 open LOG, ">> log.txt";
 print LOG "$time<>$name<>$body\n";
}
open LOG, "< log.txt";
my @log = <LOG>;
close LOG;
open HTML, "> bbs.html";
print HTML << "END";
<html>
<head>
<style>
body{background:#f0f0f0;}
span.name{color:blue;}
p.body{margin-left:32px;}
</style>
<script type="text/javascript">
<!--
 function check(form){
 function id(id){return(document.getElementById(id));}
 if(form.name.value == "" || form.body.value == ""){
  id('err').innerHTML = "入力に誤りがあります<br>";
  id('err').style.color = "red";
  return false;
 }else{
  return true;
 }
}
//-->
</script>
<title>簡易掲示板</title>
</head>
<body>
<form action="bbs.cgi" method="post" onsubmit="return check(this)">
<fieldset>
<legend>入力フォーム</legend>
<span id="err"></span>
<label>名前</label><br>
<input type="text" name="name"><br>
<label>本文</label><br>
<textarea name="body"></textarea><br>
<input type="submit" value="書き込み">
</fieldset>
</form>
<hr>
END

<つづく>
    • good
    • 0

<つづき>



my $num = 0;
my $p = int(@log/10);
if(@log%10){$p+=1}
my$index;
my$pg=1;
my$s=1;
my$l=10;
if(@log>10){
 $index=qq(<a href="bbs.html">[最新の10件]</a> );
 for(2..$p){
  $s+=10;$l=$_==$p?scalar(@log):$l+10;
  $index.=qq(<a href="bbs_$_.html">[$s‐$l]</a> );
 }
}
@log=reverse(@log);
for(@log){
 chomp;
 $num++;
 my @write = split /<>/;
 print HTML "<p>$num:<span class='name'>$write[1]</span> $write[0]</p><p class='body'>$write[2]</p>\n";
 unless($num%10&&$num!=scalar(@log)){
  print HTML << "END";
<hr>
$index
</body>
</html>
END
  close HTML;
  last if($pg==$p);
  $pg++;
  open HTML, "> bbs_$pg.html";
  print HTML << "END";
<html>
<head>
<style>
body{background:#f0f0f0;}
span.name{color:blue;}
p.body{margin-left:32px;}
</style>
<script type="text/javascript">
<!--
 function check(form){
 function id(id){return(document.getElementById(id));}
 if(form.name.value == "" || form.body.value == ""){
  id('err').innerHTML = "入力に誤りがあります<br>";
  id('err').style.color = "red";
  return false;
 }else{
  return true;
 }
}
//-->
</script>
<title>簡易掲示板</title>
</head>
<body>
<form action="bbs.cgi" method="post" onsubmit="return check(this)">
<fieldset>
<legend>入力フォーム</legend>
<span id="err"></span>
<label>名前</label><br>
<input type="text" name="name"><br>
<label>本文</label><br>
<textarea name="body"></textarea><br>
<input type="submit" value="書き込み">
</fieldset>
</form>
<hr>
END
 }
}
exit;

__END__
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!