みんなの「教えて(疑問・質問)」にみんなで「答える」Q&Aコミュニティ

こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

perl cgi文字化け解消方法と[1~][11~][21~][最新10件]のようなリンクを付ける方法。

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;

よろしくお願いします。

投稿日時 - 2010-04-16 23:42:56

QNo.5831164

すぐに回答ほしいです

質問者が選んだベストアンサー

<つづき>

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__

投稿日時 - 2010-04-22 09:31:29

このQ&Aは役に立ちましたか?

14人が「このQ&Aが役に立った」と投票しています

回答(3)

ANo.2

文字化けの原因は 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

<つづく>

投稿日時 - 2010-04-22 09:29:51

ANo.1

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

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


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

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

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

投稿日時 - 2010-04-17 10:03:17

補足

回答ありがとうございます。早速教えていただいた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:14

あなたにオススメの質問