SyntaxHighlighter

2011年10月20日木曜日

MySQL の文字コードメモ

確認

mysql> show variables like "char%";

UTF-8 に統一するには my.cnf に以下の記載を追加する。

[mysqld]
character-set-server=utf8
[mysql]
default-character-set=utf8

2011年10月16日日曜日

PHP の or メモ

or の後ろに使えないもの。

  • echo
  • return

マニュアルの論理演算子のページには return は関数じゃないからダメというようなことが書いてあるが、同じ言語構造でも die や print は OK。他にも見つけたら追記します。

2011年10月5日水曜日

制御文字を表す正規表現

決まった型のないデータ(例えば住所とか文章とか)を受け取る場合の入力値検証では、制御文字が含まれていないかというチェックを行う。 制御文字とは、16進表記で 00 ~ 1F と 7F の文字で、通常画面上には表示されない文字通り機器を制御するためのコード。 それぞれのコードがどのような意味かは以下のリンクを参照。
Wikipedia の ASCII 制御文字についての記事
許可する可能性のあるものだけ抜粋すると、タブ 09、改行 0A、復帰 0D。 住所などの単一行入力ではいずれも許可する必要なし。 文章であれば改行・復帰は許可する必要がある。タブを許可するかどうかは要件次第。

制御文字全てにマッチする正規表現 [\x00-\x1F\x7F]
タブ・改行・復帰以外の制御文字にマッチする正規表現 [\x00-\x08\x0B\x0C\x0E-\x1F\x7F]

例えば perl ならこんな感じで使う。

if ($freetext =~ /[\x00-\x1F\x7F]/) {
 print "制御文字が含まれています。\n";
 exit;
}

ここで注意。上記は『制御文字があったらはじく』例で、$freetext の末尾に改行があったとしても正常に検出してくれる。 ただし、逆に『制御文字以外で構成されていればOK』というコードとして以下のように書いた場合、末尾の改行は通過してしまう。

if ($freetext =~ /^[^\x00-\x1F\x7F]+$/) {
 print "OK\n";
}

これは perl の $ の仕様なので、厳密に判定するには ^$ ではなく \A\z を使えばよい。 以下の例であれば末尾の改行も正常に検出される。

if ($freetext =~ /\A[^\x00-\x1F\x7F]+\z/) {
 print "OK\n";
}

ちなみに上記の正規表現は JIS(ISO-2022-JP) では使えない。 JIS は文字種の切り替え時に ESC が出現するのでそれにひっかかってしまう。 改行などと同じように除外してやる方法もあるが、素直に EUC-JP か UTF-8 に変換してチェックしたほうが良い。
また、UTF-8 なら(?) \P{Cc} で制御文字以外を表せるらしいがよくわかってない。

メモ:POSIX 文字クラスの場合
制御文字 [[:cntrl:]]
制御文字以外 [[:^cntrl:]]
制御文字以外(タブ・改行・復帰は許す)  [[:^cntrl:]\t\n\r]

参考:日本語文字コード

2011年10月2日日曜日

CGI.pm を使わずにフォームデータを受け取って表示する

CGI.pm を使わずにフォームデータを受け取って表示するソースメモ。
チェックボックスやマルチセレクトのように複数の値が送られてくるものには対応しておらず、ファイルアップロードにも対応してません。 CGI のデータの入出力には CGI.pm を利用することを強く推奨します。これはあくまで習作です。

#!/usr/bin/perl

use strict;

print <<End_of_Header;
Content-Type: text/html; charset=euc-jp

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=euc-jp">
<title>CGI</title>
</head>
<body>
End_of_Header

my $query;
if ($ENV{'REQUEST_METHOD'} eq 'GET') {
 # GET
 $query = $ENV{'QUERY_STRING'};
} elsif ($ENV{'REQUEST_METHOD'} eq 'POST') {
 # POST
 if ($ENV{'CONTENT_LENGTH'} > 10240) { er("なげーよ。"); }
 read(STDIN,$query,$ENV{'CONTENT_LENGTH'});
} else {
 er("対応していないメソッドです。");
}

# split
my %data;
foreach (split /&/,$query) {
 my ($k,$v) = split /=/;
 $data{decode($k)} = decode($v);
}

# print
print "<table border=\"1\">\n";
print "<tr><th>KEY</th><td>VALUE</td></tr>\n";
foreach (keys %data) {
 print "<tr><th>" . escape($_) . "</th><td>" . escape($data{$_}) . "</td></tr>\n";
}
print "</table>\n";

footer();

# SUB
sub decode {
 my $data = shift;
 $data =~ tr/+/ /;
 $data =~ s/%([0-9A-Fa-f][0-9A-Fa-f])/pack('H2', $1)/eg;
 $data =~ s/\x0D\x0A/\n/g;
 $data =~ tr/\x0D\x0A/\n\n/;
 return $data;
}

sub escape {
 my $data = shift;
 $data =~ s/&/&amp;/g;
 $data =~ s/</&lt;/g;
 $data =~ s/>/&gt;/g;
 $data =~ s/"/&quot;/g;
 $data =~ s/'/&#39;/g;
 $data =~ s/\n/<br>/g;
 return $data;
}

sub er {
 my $msg = shift;
 print "<strong>$msg</strong>\n";
 footer();
}

sub footer {
 print "</body>\n</html>\n";
 exit;
}

2011年10月1日土曜日

CGI.pm

CGI.pm の使い方メモ

#!/usr/local/bin/perl

use strict;
use CGI;

my $obj = new CGI;

# name値のリストを得る
my @params = $obj->params;

# 単体の値を取得(text,password,textarea,radioなど)
my $value = $obj->param('name');
# fileの場合は$valueがファイル名兼ファイルハンドルになっている
open FH,">tmpfile" or die;
while (<$value>) { print FH; }
close FH;

# 複数の値を取得(checkbox,マルチselectなど)
my @values = $obj->param('name');

# 出力
$obj->escapeHTML($value);

exit;