| 連想配列(ハッシュ)への取り込み |
| 0x00 から 0x20 のコントロール文字
0x7F から 0xFF のトップビットが立っているもの " # % ; < > ? { } | \ ^ ~ ` [ ] |
これらに加えて & = はデータの区切り文字に使われるので、これらがデータ中に現れる場合もエンコーディングされています。さらに空白文字は + に変換され、データ中の + はやはり16進数値にエンコーディングされています。
デコードする際は特にこれらの文字を気にせずに %XX が現れたら元の文字に変換します。
具体的には、例えばSJISの'あ'という文字は16進数値で0x82 0xA0であり、%82%A0とエンコードされています。これをデコードするには、
#!/usr/bin/perl
$before = '%82%A0'; # SJISの「あ」
# 先頭の%を除いて16進数を取り出す
@x = ($before =~ /%([A-Fa-f0-9][A-Fa-f0-9])/g);
# 16進数を10進数にする
@x = grep { $_ = hex } @x;
# 16進数値を文字に変換
$after = pack("cc", @x);
print "before=$before, after=$after\n";
|
これを一気に行うと
$_ = $before; $after =~s/%([A-Fa-f0-9][A-Fa-f0-9])/pack("c", hex($1))/;
|
とすることができます。
サンプルスクリプトでは、デコードしたものを
なお、日本語に関する処理は「日本語コードの取り扱い」の項を参照してください。
#
# parseInput(encoding)
# <IN> encoding: 日本語コード(jis|sjis|euc)
# <OUT> Name=>Val のハッシュ(グロブ)
#
sub parseInput
{
my($encoding) = @_;
my($method) = $ENV{'REQUEST_METHOD'};
local($query, @in, $key, $val);
# 日本語が必要な場合は jcode.pl を取り込む
require 'jcode.pl' if $encoding;
# GETメソッドかPOSTメソッドかを判別する
if ($method eq 'GET') {
$query = $ENV{'QUERY_STRING'};
}
elsif ($method eq 'POST') {
read(STDIN, $query, $ENV{'CONTENT_LENGTH'});
}
# 入力データを分解する
local(@query) = split(/&/, $query);
# Name=Val を $in{'Name'} = 'Val' のハッシュにする。
foreach (@query) {
# + を空白文字に変換
tr/+/ /;
# Name=Val を分ける
($key, $val) = split(/=/);
# %HH形式を元の文字にデコードする。
$key =~ s/%([A-Fa-f0-9][A-Fa-f0-9])/pack("c", hex($1))/ge;
$val =~ s/%([A-Fa-f0-9][A-Fa-f0-9])/pack("c", hex($1))/ge;
$val =~ s/\r\n/\n/g;
# 日本語コードが指定されている場合は変換する。
jcode'convert(*key, $encoding) if ($encoding);
jcode'convert(*val, $encoding) if ($encoding);
# 連想配列(ハッシュ)にセット
$in{$key} = $val;
}
# 連想配列のグロブを返す
return *in;
}
|