Home > Archives > 2009-03
2009-03
Exif情報確認君はじめりです
- 2009-03-31 (火)
- webservice
Exif情報確認君はじめりです。
今期、新たな試みとして社内でチームを2つつくってそれぞれサービスを1個づつ作ろう!とやってみた。が、日々の作業に忙殺されて結局作れないまま3月が終わろうとして、これは言いだしっぺとしてまずいと思い適当にExif情報確認君なるものをでっちあげてみた。
これはなに?
JPG画像をメールで送るとその画像に含まれるExif情報をメールで返送してくれるサービスです。さらにExif情報を削除した画像が添付されます。
Exif?
Exchangeable image file formatの略称。カメラの機種や撮影時の条件情報を画像に埋め込んだデータ(のフォーマット)。詳しくは
Exchangeable image file formatを。
そのた
もしかしてSPAMの踏み台になる恐れがあるかも。本当にそうなってきたら対策考える。
まぁそういうわけで、来期はもうすこしまともなサービスを作りたいです。尚、弊社ではプログラマを絶賛募集中です。興味のある方は募集要項をご覧になってjoin@geminium.comまでご連絡くださいです。Perlが好きな人大歓迎です。
- Comments: 2
- Trackbacks: 0
主要CPANモジュールのメールアドレスの正規表現
- 2009-03-22 (日)
- perl
use strict;
use Encode;
use Email::Address;
use Email::Valid;
use Email::Valid::Loose;
use Email::Find::addrspec;
my $wsp = '[\x20\x09]';
my $vchar = '[\x21-\x7e]';
my $quoted_pair = "\\\\(?:$vchar|$wsp)";
my $qtext = '[\x21\x23-\x5b\x5d-\x7e]';
my $qcontent = "(?:$qtext|$quoted_pair)";
my $quoted_string = "\"$qcontent*\"";
my $atext = '[a-zA-Z0-9!#$%&\'*+\-\/\=?^_`{|}~]';
my $dot_atom_text = "$atext+(?:[.]$atext+)*";
my $dot_atom = $dot_atom_text;
my $local_part = "(?:$dot_atom|$quoted_string)";
my $domain = $dot_atom;
my $addr_spec = qr{${local_part}[@]$domain};
my %addr_specs = (
'mine' => $addr_spec,
'Email::Address' => $Email::Address::addr_spec,
'Email::Valid' => $Email::Valid::RFC822PAT,
'Email::Valid::Loose' => $Email::Valid::Loose::Addr_spec_re,
'Email::Find::addrspec' => $Email::Find::addrspec::Addr_spec_re,
);
use utf8;
my $input_addr_spec = 'hoge-hoge@example.com';
my $input_text = "ぼくの\@メールアドレスはbef\nore\x{7f}foo\@example.com\x{7f}afterです";
my $input_text_bytes = Encode::encode('utf-8', $input_text);
while ( my ( $package, $re ) = each %addr_specs ) {
print "$package:\n";
if ( $input_addr_spec =~ /\A$re\z/ ) {
print " valid addr-spec\n";
}
else {
print " invalid addr-spec\n";
}
print " flagged-utf8\n";
if ( $input_text =~ /($re)/ms ) {
print Encode::encode('utf-8', " My addr-spec is <$1>\n");
}
else {
print " no-match\n";
}
print " bytes-utf8\n";
if ( $input_text_bytes =~ /($re)/ms ) {
print " My addr-spec is <$1>\n";
}
else {
print " no-match\n";
}
}
の結果が
Email::Find::addrspec: valid addr-spec flagged-utf8 My addr-spec is <orefoo@example.com> bytes-utf8 My addr-spec is <orefoo@example.com> Email::Valid: valid addr-spec flagged-utf8 My addr-spec is <ぼくの@メールアドレスはbef> bytes-utf8 My addr-spec is <orefoo@example.comafter> mine: valid addr-spec flagged-utf8 My addr-spec is <foo@example.com> bytes-utf8 My addr-spec is <foo@example.com> Email::Valid::Loose: valid addr-spec flagged-utf8 My addr-spec is <ぼくの@メールアドレスはbef> bytes-utf8 My addr-spec is <orefoo@example.comafter> Email::Address: valid addr-spec flagged-utf8 My addr-spec is <ぼくの@メールアドレスはbef > bytes-utf8 My addr-spec is <ぼくの@メールアドレスはbef >
になる件。近いうちにパッチ作って送るかも。
- Comments: 0
- Trackbacks: 0
メールアドレス(addr-spec)の正規表現
能書き
前エントリを書いてからいろいろと調べていて驚いたんだけど、日本語のwebsiteで、それなりにまともにRFC822(RFC2822,RFC5322)に準拠した(もしくはきちんと意図的に準拠していない部分を選択している)正規表現はPerlだろうがPHPだろうがRubyだろうが軽くぐぐった程度では見当たらない。PerlのモジュールのEmail::AddressもEmail::Validも程度の差はあれ問題を抱えている。そこらへんの既存の出回ってる正規表現にどういった問題があるかなんてことは次回エントリにて。
というわけで、Perl、PHP、RubyでRFC5322準拠なメールアドレス(addr-spec)の正規表現を以下に示します。尚、addr-specの最終的な正規表現のみならずそれを作成するに至る部分も併記してあります。これは、最終的な正規表現だけでは難解すぎてとても理解できないからです。内容を理解せずにそのままコピペすることを否定はしませんが理解しようとしたときの助けとなるよう、コメントアウトでもよいのでコード中に併記しておくことをお勧めします。
方針
- RFC5322準拠が基本
- addr_spec_looseは..や.@を許容した正規表現(日本のモバイルキャリア用)
- ただしobsoleteなsyntaxは無視
- ただしdomain_literalは無視
- ただしCFWSは無視
- ただしFWSも無視
- 上記のように無視してるのが多いのは用途をweb入力のチェックやテキストからの抜き出し用途を想定しているため
- BNFのsymbolの変数移植はできるだけRFCに即しつつ-を_に
- 文字種の記述はできるだけRFCの順番にあわせる
- ASCIIをコードポイントで指定する場合は16進数で
- perlではflagged utf8でも処理できるように
- できるだけテストはしてありますが、完璧だとは思っていないのでミスを指摘してくださる方は大歓迎です。
無視多すぎて準拠じゃないじゃんという突っ込みがありそうですが、自分で宣言している場合はありという俺ルールで。
Perl
動作確認: 5.10.0
my $wsp = '[\x20\x09]';
my $vchar = '[\x21-\x7e]';
my $quoted_pair = "\\\\(?:$vchar|$wsp)";
my $qtext = '[\x21\x23-\x5b\x5d-\x7e]';
my $qcontent = "(?:$qtext|$quoted_pair)";
my $quoted_string = "\"$qcontent*\"";
my $atext = '[a-zA-Z0-9!#$%&\'*+\-\/\=?^_`{|}~]';
my $dot_atom_text = "$atext+(?:[.]$atext+)*";
my $dot_atom = $dot_atom_text;
my $local_part = "(?:$dot_atom|$quoted_string)";
my $domain = $dot_atom;
my $addr_spec = qr{${local_part}[@]$domain};
my $dot_atom_loose = "$atext+(?:[.]|$atext)*";
my $local_part_loose = "(?:$dot_atom_loose|$quoted_string)";
my $addr_spec_loose = qr{${local_part_loose}[@]$domain};
my $input_addr_spec = 'foo@example.com';
if ( $input_addr_spec =~ /\A$addr_spec\z/ ) {
print "valid addr-spec\n";
}
use utf8;
my $input_text = 'ぼくの@メールアドレスはfoo@example.comです';
if ( $input_text =~ /($addr_spec)/ ) {
print "My addr-spec is <$1>\n";
}
PHP
動作確認: 5.2.6
<?php
$wsp = '[\x20\x09]';
$vchar = '[\x21-\x7e]';
$quoted_pair = "\\\\(?:$vchar|$wsp)";
$qtext = '[\x21\x23-\x5b\x5d-\x7e]';
$qcontent = "(?:$qtext|$quoted_pair)";
$quoted_string = "\"$qcontent*\"";
$atext = '[a-zA-Z0-9!#$%&\'*+\-\/\=?^_`{|}~]';
$dot_atom_text = "$atext+(?:[.]$atext+)*";
$dot_atom = $dot_atom_text;
$local_part = "(?:$dot_atom|$quoted_string)";
$domain = $dot_atom;
$addr_spec = "${local_part}[@]$domain";
$dot_atom_loose = "$atext+(?:[.]|$atext)*";
$local_part_loose = "(?:$dot_atom_loose|$quoted_string)";
$addr_spec_loose = "${local_part_loose}[@]$domain";
$input_addr_spec = 'foo@example.com';
if ( preg_match("/\A$addr_spec\z/", $input_addr_spec) ) {
print "valid addr-spec\n";
}
$input_text = 'ぼくの@メールアドレスはfoo@example.comです';
if ( preg_match("/($addr_spec)/", $input_text, $matches) ) {
print "My addr-spec is <$matches[0]>\n";
}
?>
Ruby
動作確認: 1.8.7
wsp = '[\x20\x09]'
vchar = '[\x21-\x7e]'
quoted_pair = "\\\\(?:#{vchar}|#{wsp})"
qtext = '[\x21\x23-\x5b\x5d-\x7e]'
qcontent = "(?:#{qtext}|#{quoted_pair})"
quoted_string = "\"#{qcontent}*\""
atext = '[a-zA-Z0-9!#$%&\'*+\-\/\=?^_`{|}~]'
dot_atom_text = "#{atext}+(?:[.]#{atext}+)*"
dot_atom = dot_atom_text
local_part = "(?:#{dot_atom}|#{quoted_string})"
domain = dot_atom
addr_spec = "#{local_part}[@]#{domain}"
dot_atom_loose = "#{atext}+(?:[.]|#{atext})*"
local_part_loose = "(?:#{dot_atom_loose}|#{quoted_string})"
addr_spec_loose = "#{local_part_loose}[@]#{domain}"
input_addr_spec = 'foo@example.com'
if /\A#{addr_spec}\z/ =~ input_addr_spec then
puts "valid addr-spec"
end
input_text = 'ぼくの@メールアドレスはfoo@example.comです'
if /(#{addr_spec})/ =~ input_text then
puts "My addr-spec is <#{$1}>";
end
テストコードこみのコード
以下にテストコード付きのものを貼り付けます。検証したいかたはどうぞ。テストケースは全言語共通になってます。
Perl
#!/usr/bin/perl
use strict;
use Test::More;
my $wsp = '[\x20\x09]';
my $vchar = '[\x21-\x7e]';
my $quoted_pair = "\\\\(?:$vchar|$wsp)";
my $qtext = '[\x21\x23-\x5b\x5d-\x7e]';
my $qcontent = "(?:$qtext|$quoted_pair)";
my $quoted_string = "\"$qcontent*\"";
my $atext = '[a-zA-Z0-9!#$%&\'*+\-\/\=?^_`{|}~]';
my $dot_atom_text = "$atext+(?:[.]$atext+)*";
my $dot_atom = $dot_atom_text;
my $local_part = "(?:$dot_atom|$quoted_string)";
my $domain = $dot_atom;
my $addr_spec = qr{${local_part}[@]$domain};
print 'addr_spec: ' . $addr_spec, "\n";
my $dot_atom_loose = "$atext+(?:[.]|$atext)*";
my $local_part_loose = "(?:$dot_atom_loose|$quoted_string)";
my $addr_spec_loose = qr{${local_part_loose}[@]$domain};
print 'addr_spec_loose' . $addr_spec_loose, "\n";
my @valid = (
'foo@example.com', # normal
# local-part
# dot-atom
'foo.hoge@example.com',
'foo.bar.baz@example.com',
# quoted-string
'"foo"@example.com',
'"!"@example.com', # \x21
'"#"@example.com', # \x23
'"["@example.com', # \x5b
'"]"@example.com', # \x5d
'"["@example.com', # \x7e
# quoted-pair
'"\\ "@example.com', # \x20
"\"\\\x09\"\@example.com", # \x09 # php @
'"\\!"@example.com', # \x21
'"\\["@example.com', # \x7e
# domain
'foo.hoge@localhost',
'foo.hoge@sub.example.com',
);
my @valid_loose = (
'foo.@docomo.ne.jp',
'foo.foo.@docomo.ne.jp',
'foo..@docomo.ne.jp',
'foo..foo@docomo.ne.jp',
'foo..foo.@docomo.ne.jp',
);
my @invalid = (
'',
'foo',
'foo@',
'@foo',
# local-part
# dot-atom
'.foo@example.com',
'..foo@example.com',
'foo@@example.com',
'foo[@example.com',
'foo @example.com',
# quoted-string
"\"\x00\"\@example.com", # \x00 # php @
'" "@example.com', # \x20
'"""@example.com', # \x22
'"\\"@example.com', # \x5c
"\"\x7f\"\@example.com", # \x7f # php @
# quoted-pair
"\"\\\x1f\"\@example.com", # \x1f # php @
"\"\\\x7f\"\@example.com", # \x7f # php @
# \z check
"foo\@example.com\n", # php @
"foo\@example.com\nfoo\@example.com", # php @
# non-ascii
"\x80\@example.com",
"\"\x80\"\@example.com",
"\"\\\x80\"\@example.com",
# utf8
"\x100\@example.com",
"\"\x100\"\@example.com",
"\"\\\x100\"\@example.com",
);
plan tests => (@valid + @invalid + @valid_loose) * 2;
{
# normal
for (@valid) {
ok( m{\A$addr_spec\z}o , 'normal-valid - ' . $_ );
}
for (@invalid, @valid_loose) {
ok( !m{\A$addr_spec\z}o, 'normal-invalid - ' . $_ );
}
}
{
# loose
for (@valid, @valid_loose) {
ok( m{\A$addr_spec_loose\z}o , 'loose-valid - ' . $_ );
}
for (@invalid) {
ok( !m{\A$addr_spec_loose\z}o, 'loose-invalid - ' . $_ );
}
}
PHP
<?php
$count = 0;
$wsp = '[\x20\x09]';
$vchar = '[\x21-\x7e]';
$quoted_pair = "\\\\(?:$vchar|$wsp)";
$qtext = '[\x21\x23-\x5b\x5d-\x7e]';
$qcontent = "(?:$qtext|$quoted_pair)";
$quoted_string = "\"$qcontent*\"";
$atext = '[a-zA-Z0-9!#$%&\'*+\-\/\=?^_`{|}~]';
$dot_atom_text = "$atext+(?:[.]$atext+)*";
$dot_atom = $dot_atom_text;
$local_part = "(?:$dot_atom|$quoted_string)";
$domain = $dot_atom;
$addr_spec = "${local_part}[@]$domain";
echo 'addr_spec: ' . $addr_spec, "\n";
$dot_atom_loose = "$atext+(?:[.]|$atext)*";
$local_part_loose = "(?:$dot_atom_loose|$quoted_string)";
$addr_spec_loose = "${local_part_loose}[@]$domain";
echo 'addr_spec_loose: ' . $addr_spec_loose, "\n";
$valid = array(
'foo@example.com', # normal
# local-part
# dot-atom
'foo.hoge@example.com',
'foo.bar.baz@example.com',
# quoted-string
'"foo"@example.com',
'"!"@example.com', # \x21
'"#"@example.com', # \x23
'"["@example.com', # \x5b
'"]"@example.com', # \x5d
'"["@example.com', # \x7e
# quoted-pair
'"foo\\ "@example.com', # \x20
"\"foo\\\x09\"@example.com", # \x09 # php @
'"\\!"@example.com', # \x21
'"\\["@example.com', # \x7e
# domain
'foo.hoge@localhost',
'foo.hoge@sub.example.com',
);
$valid_loose = array(
'foo.@docomo.ne.jp',
'foo.foo.@docomo.ne.jp',
'foo..@docomo.ne.jp',
'foo..foo@docomo.ne.jp',
'foo..foo.@docomo.ne.jp',
);
$invalid = array(
'',
'foo',
'foo@',
'@foo',
# local-part
# dot-atom
'.foo@example.com',
'..foo@example.com',
'foo@@example.com',
'foo[@example.com',
'foo @example.com',
# quoted-string
"\"\x00\"@example.com", # \x00 # php @
'" "@example.com', # \x20
'"""@example.com', # \x22
'"\\"@example.com', # \x5c
"\"\x7f\"@example.com", # \x7f # php @
# quoted-pair
"\"\\\x1f\"@example.com", # \x1f # php @
"\"\\\x7f\"@example.com", # \x7f # php @
# \z check
"foo@example.com\n",
"foo@example.com\nfoo@example.com",
# non-ascii
"\x80@example.com",
"\"\x80\"@example.com",
"\"\\\x80\"@example.com",
# utf8
"\x100@example.com",
"\"\x100\"@example.com",
"\"\\\x100\"@example.com",
);
{
# normal
foreach ($valid as $addr) {
ok($addr_spec, $addr, 'normal-valid - ' . $addr);
}
foreach (array_merge($invalid, $valid_loose) as $addr) {
not_ok($addr_spec, $addr, 'normal-invalid - ' . $addr);
}
}
{
# loose
foreach (array_merge($valid, $valid_loose) as $addr) {
ok($addr_spec_loose, $addr, 'loose-valid - ' . $addr);
}
foreach ($invalid as $addr) {
not_ok($addr_spec_loose, $addr, 'loose-invalid - ' . $addr);
}
}
function ok($regexp, $addr, $desc, $xor = 0) {
global $count;
$count++;
if ( preg_match("/\A$regexp\z/", $addr) ^ $xor ) {
echo "ok $count - $desc\n";
}
else {
echo "not ok $count - $desc\n";
}
}
function not_ok($regexp, $addr, $desc) {
ok($regexp, $addr, $desc, 1);
}
?>
Ruby
#!/usr/bin/ruby
wsp = '[\x20\x09]'
vchar = '[\x21-\x7e]'
quoted_pair = "\\\\(?:#{vchar}|#{wsp})"
qtext = '[\x21\x23-\x5b\x5d-\x7e]'
qcontent = "(?:#{qtext}|#{quoted_pair})"
quoted_string = "\"#{qcontent}*\""
atext = '[a-zA-Z0-9!#$%&\'*+\-\/\=?^_`{|}~]'
dot_atom_text = "#{atext}+(?:[.]#{atext}+)*"
dot_atom = dot_atom_text
local_part = "(?:#{dot_atom}|#{quoted_string})"
domain = dot_atom
addr_spec = "#{local_part}[@]#{domain}"
puts 'addr_spec: ' + addr_spec
dot_atom_loose = "#{atext}+(?:[.]|#{atext})*"
local_part_loose = "(?:#{dot_atom_loose}|#{quoted_string})"
addr_spec_loose = "#{local_part_loose}[@]#{domain}"
puts 'addr_spec_loose: ' + addr_spec_loose
valid = [
'foo@example.com', # normal
# local-part
# dot-atom
'foo.hoge@example.com',
'foo.bar.baz@example.com',
# quoted-string
'"foo"@example.com',
'"!"@example.com', # \x21
'"#"@example.com', # \x23
'"["@example.com', # \x5b
'"]"@example.com', # \x5d
'"["@example.com', # \x7e
# quoted-pair
'"foo\\ "@example.com', # \x20
"\"foo\\\x09\"\@example.com", # \x09 # php @
'"\\!"@example.com', # \x21
'"\\["@example.com', # \x7e
# domain
'foo.hoge@localhost',
'foo.hoge@sub.example.com',
]
valid_loose = [
'foo.@docomo.ne.jp',
'foo.foo.@docomo.ne.jp',
'foo..@docomo.ne.jp',
'foo..foo@docomo.ne.jp',
'foo..foo.@docomo.ne.jp',
]
invalid = [
'',
'foo',
'foo@',
'@foo',
# local-part
# dot-atom
'.foo@example.com',
'..foo@example.com',
'foo@@example.com',
'foo[@example.com',
'foo @example.com',
# quoted-string
"\"\x00\"\@example.com", # \x00 # php @
'" "@example.com', # \x20
'"""@example.com', # \x22
'"\\"@example.com', # \x5c
"\"\x7f\"\@example.com", # \x7f # php @
# quoted-pair
"\"\\\x1f\"\@example.com", # \x1f # php @
"\"\\\x7f\"\@example.com", # \x7f # php @
# \z check
"foo@example.com\n",
"foo@example.com\nfoo@example.com",
# non-ascii
"\x80\@example.com",
"\"\x80\"\@example.com",
"\"\\\x80\"\@example.com",
# utf8
"\x100\@example.com",
"\"\x100\"\@example.com",
"\"\\\x100\"\@example.com",
]
$count = 0
def ok(regexp, addr, desc, xor = 0)
$count = $count + 1
if (/\A#{regexp}\z/ =~ addr) ^ xor then
puts "ok #{$count} - #{desc}";
else
puts "not ok #{$count} - #{desc}";
end
end
def not_ok(regexp, addr, desc)
ok(regexp, addr, desc, 1)
end
# normal
valid.each do |addr|
ok(addr_spec, addr, 'normal-valid - ' + addr);
end
(invalid + valid_loose).each do |addr|
not_ok(addr_spec, addr, 'normal-invalid - ' + addr);
end
# loose
(valid + valid_loose).each do |addr|
ok(addr_spec_loose, addr, 'loose-valid - ' + addr);
end
invalid.each do |addr|
not_ok(addr_spec_loose, addr, 'loose-invalid - ' + addr);
end
- Comments: 0
- Trackbacks: 0
「danコガいはもう正規表現をblogに書くな」と言わせないでくれ
- 2009-03-20 (金)
- perl
(タイトルはid:hasegawayosukeさんが言ってたよ)
ああ、まただよ…
「PHP使いはもう正規表現をblogに書くな」と言わせないでくれ
正規表現って、プログラミング言語間の差が少ないサブ言語なのに、なぜ「DAN」がつくとダメ正規表現ばかり登場するのか。うんざりだ。
飽きたので以下略。
簡潔に。(正規表現はdanさんのものからシングルクォートコンテキストにあわせてエスケープをしてあります)
<?php
$email = 'test@example.com' . "\n";
$re = '/^(?:(?:(?:(?:[a-zA-Z0-9_!#\$\%&\'*+\/=?\^`{}~|\-]+)(?:\.(?:[a-zA-Z0-9_!#\$\%&\'*+\/=?\^`{}~|\-]+))*)|(?:"(?:\\\\[^\r\n]|[^\\\\"])*")))\@(?:(?:(?:(?:[a-zA-Z0-9_!#\$\%&\'*+\/=?\^`{}~|\-]+)(?:\.(?:[a-zA-Z0-9_!#\$\%&\'*+\/=?\^`{}~|\-]+))*)|(?:\[(?:\\\\\S|[\x21-\x5a\x5e-\x7e])*\])))$/';
if (preg_match($re,$email)) {
echo "valid";
} else {
echo "invalid";
}
?>
これの結果が「valid」になる。当然rfc5322でdot-atomには改行は(CRであれLFであれ)許されていない。
対策はdanさん自身が^$でなくて\A\zを使おうで述べているとおり。
<?php
$email = 'test@example.com' . "\n";
$re = '/\A(?:(?:(?:(?:[a-zA-Z0-9_!#\$\%&\'*+\/=?\^`{}~|\-]+)(?:\.(?:[a-zA-Z0-9_!#\$\%&\'*+\/=?\^`{}~|\-]+))*)|(?:"(?:\\\\[^\r\n]|[^\\\\"])*")))\@(?:(?:(?:(?:[a-zA-Z0-9_!#\$\%&\'*+\/=?\^`{}~|\-]+)(?:\.(?:[a-zA-Z0-9_!#\$\%&\'*+\/=?\^`{}~|\-]+))*)|(?:\[(?:\\\\\S|[\x21-\x5a\x5e-\x7e])*\])))\z/';
if (preg_match($re,$email)) {
echo "valid";
} else {
echo "invalid";
}
?>
ただしjavascriptではmフラグをつけない限りは$は改行直前にはマッチしないので問題なかったりもする。
ところでこの正規表現には他にも問題が残っている。domain-literalで\\\Sにマッチするようになっているがこれはなんなのだろう。
<?php
$email = 'test@[127.0.0.1' . "\\\x1f]";
$re = '/\A(?:(?:(?:(?:[a-zA-Z0-9_!#\$\%&\'*+\/=?\^`{}~|\-]+)(?:\.(?:[a-zA-Z0-9_!#\$\%&\'*+\/=?\^`{}~|\-]+))*)|(?:"(?:\\\\[^\r\n]|[^\\\\"])*")))\@(?:(?:(?:(?:[a-zA-Z0-9_!#\$\%&\'*+\/=?\^`{}~|\-]+)(?:\.(?:[a-zA-Z0-9_!#\$\%&\'*+\/=?\^`{}~|\-]+))*)|(?:\[(?:\\\\\S|[\x21-\x5a\x5e-\x7e])*\])))\z/';
if (preg_match($re,$email)) {
echo "valid";
} else {
echo "invalid";
}
?>
おかげで上記のコードもvalidだ。なんてこった。domain-literalなんてそもそもはずしてもいいような気もするけど、対応するとしたらこれでいんじゃないだろうか。
<?php
$email = 'test@[127.0.0.1' . "\\\x1f]";
$re = '/\A(?:(?:(?:(?:[a-zA-Z0-9_!#\$\%&\'*+\/=?\^`{}~|\-]+)(?:\.(?:[a-zA-Z0-9_!#\$\%&\'*+\/=?\^`{}~|\-]+))*)|(?:"(?:\\\\[^\r\n]|[^\\\\"])*")))\@(?:(?:(?:(?:[a-zA-Z0-9_!#\$\%&\'*+\/=?\^`{}~|\-]+)(?:\.(?:[a-zA-Z0-9_!#\$\%&\'*+\/=?\^`{}~|\-]+))*)|(?:\[[\x21-\x5a\x5e-\x7e]*\])))\z/';
if (preg_match($re,$email)) {
echo "valid";
} else {
echo "invalid";
}
?>
\\\Sになんか意味があるんだったらすみません。知ってる人いたら教えてください。
追記1(2009/03/20 01:57): コード例の(html)エスケープがおかしかったのを直しました。
追記2(2009/03/20 05:36): \\\Sに関してdanさんより404 Blog Not Found:regexp – ‘test@[127.0.0.1' . "\\\x1f]" はRFC2822準拠で説明いただきました。ちなみにRFC5322にはquoted-pairはないかとおもってたら、obs-dtextの中にしっかり生き残ってた…。
- Comments: 0
- Trackbacks: 1
Home > Archives > 2009-03
- Search
- Feeds
- Meta