| Tripletail documentation | Contained in the Tripletail distribution. |
Tripletail::Value - 値の検証や変換
my $value = $TL->newValue('null@example.org');
if ($value->isEmail) {
print $value->get . " is a valid email address.\n";
}
# null@example.org を表示
print $value->convWide->get . "\n";
セットした値1つの形式をチェックし、または形式を矯正する。
値を文字列として扱う場合は、常に UTF-8 である事が前提となる。
$TL->newValue$val = $TL->newValue $val = $TL->newValue($value)
Tripletail::Value オブジェクトを作成。 引数があれば、その引数で set が実行される。
$val->set($value)
値をセット。
$value = $val->get
矯正後の値を取得。
setDate$val->setDate($year, $month, $day)
年月日を指定してYYYY-MM-DD形式でセットする。 日付として不正である場合はundefがセットされる。
setDateTime$val->setDateTime($year, $month, $day, $hour, $min, $sec)
各値を指定して時刻をYYYY-MM-DD HH:MM:SS形式でセットする。 時刻として不正である場合はundefがセットされる。 $min、$secは省略でき、省略時は0が使用される。
setTime$val->setTime($hour, $min, $sec)
各値を指定して時刻をHH:MM:SS形式でセットする。 範囲は00:00:00~23:59:59までで、時刻として正しくない場合はundefがセットされる。 $min、$secは省略でき、省略時は0が使用される。
$n_bytes = $val->getLen
バイト数を返す。
$n_bytes = $val->getSjisLen
Shift_Jisでのバイト数を返す。
$n_chars = $val->getCharLen
文字数を返す。
$age = $val->getAge $age = $val->getAge($date)
YYYY-MM-DD形式の値として、$date の日付での年齢を返す。省略可能。 日付の形式が間違っている場合はundefを返す。
デフォルトは現在の日付。
$regexp = $val->getRegexp($type)
指定された$typeに対応する正規表現を返す。 対応する$typeは次の通り。
hira ひらがなに対応する正規表現を返す。
kata カタカナに対応する正規表現を返す。
numbernarrow 半角数字に対応する正規表現を返す。
numberwide 全角数字に対応する正規表現を返す。
$bool = $val->isEmpty
値が空(undefまたは0文字)なら1。 そうでなければundefを返す。
$bool = $val->isWhitespace
半角/全角スペース、タブのみで構成されていれば1。 そうでなければundefを返す。値が0文字やundefの場合もundefを返す。
$bool = $val->isBlank
値が空(undefまたは0文字)であるか、半角/全角スペース、タブのみで構成されていれば1。 そうでなければundefを返す。値が0文字やundefの場合もundefを返す。
$bool = $val->isPrintableAscii
文字列が制御コードを除くASCII文字のみで構成されているなら1。 そうでなければundefを返す。値が0文字やundefの場合もundefを返す。
$bool = $val->isWide
文字列が全角文字のみで構成されているなら1。 そうでなければundefを返す。値が0文字やundefの場合もundefを返す。
$bool = $val->isPassword $bool = $val->isPassword(@spec)
文字列がisPrintableAsciiを満たして且つ指定された要素を含んでいれば真を,
そうでなければ偽を返す.
指定された文字以外が入っていることに関しては考慮しない.
@spec に指定できるのは, alpha, ALPHA, digit, symbol の
いずれかの文字列若しくは文字を含んだ配列リファレンス.
指定しなかった場合のデフォルト値は, qw(alpha ALPHA digit symbol) となる.
記号に含まれるものは以下の32文字. (0.44以前では空白文字も含めた33文字でした)
! " # $ % & ' ( ) * + ' - . /
: ; < = > ? @ [ \ ] ^ _ ` { | } ~
$bool = $val->isZipCode
7桁の郵便番号(XXX-XXXX形式)なら1。 そうでなければundefを返す。
実在する郵便番号かどうかは確認しない。
$bool = $val->isTelNumber
電話番号(/^\d[\d-]+\d$/)なら1。 そうでなければundefを返す。
数字で始まり、数字で終わり、ハイフン(-)が一つ以上あり、その間が数字とハイフン(-)のみで構成されていれば電話番号とみなす。
$bool = $val->isEmail
メールアドレスとして正しい形式であれば1。 そうでなければundefを返す。
$bool = $val->isMobileEmail
メールアドレスとして正しい形式であれば1。 そうでなければundefを返す。
但し携帯電話のメールアドレスでは、アカウント名の末尾にピリオドを含んでいる場合がある為、これも正しい形式であるとみなす。
携帯電話キャリアのドメイン名を判別するわけではないため、通常のメールアドレスも 1 を返す。
$bool = $val->isInteger $bool = $val->isInteger($min,$max)
整数で、かつ$min以上$max以下なら1。$mix,$maxは省略可能。 そうでなければundefを返す。 空もしくはundefの場合は、undefを返す。
デフォルトでは、最大最小のチェックは行わなず整数であれば1を返す。
$bool = $val->isReal $bool = $val->isReal($min,$max)
整数もしくは小数で、かつ$min以上$max以下なら1。$mix,$maxは省略可能。 そうでなければundefを返す。 空もしくはundefの場合は、undefを返す。
デフォルトでは、最大最小のチェックは行わなず、整数もしくは小数であれば1を返す。
$bool = $val->isHira
平仮名だけが含まれている場合は1。 そうでなければundefを返す。値が0文字やundefの場合もundefを返す。
$bool = $val->isKata
片仮名だけが含まれている場合は1。 そうでなければundefを返す。値が0文字やundefの場合もundefを返す。
$bool = $val->isExistentDay
YYYY-MM-DDで設定された日付が実在するものなら1。 そうでなければundefを返す。
$bool = $val->isGif
$bool = $val->isJpeg
$bool = $val->isPng
それぞれの形式の画像なら1。 そうでなければundefを返す。
画像として厳密に正しい形式であるかどうかは確認しない。 ( file(1) 程度の判断のみ。)
$bool = $val->isHttpUrl
"http://" で始まる文字列なら1。 そうでなければundefを返す。
$bool = $val->isHttpsUrl
"https://" で始まる文字列なら1。 そうでなければundefを返す。
$bool = $val->isLen($min,$max)
バイト数の範囲が指定値以内かチェックする。$mix,$maxは省略可能。 範囲内であれば1、そうでなければundefを返す。
$bool = $val->isSjisLen($min,$max)
Shift-Jisでのバイト数の範囲が指定値以内かチェックする。$mix,$maxは省略可能。 範囲内であれば1、そうでなければundefを返す。
$bool = $val->isCharLen($min,$max)
文字数の範囲が指定値以内かチェックする。$mix,$maxは省略可能。 範囲内であれば1、そうでなければundefを返す。
$bool = $val->isPortable
機種依存文字以外のみで構成されていれば1。 そうでなければ(機種依存文字を含んでいれば)undefを返す。
値が0文字やundefの場合は1を返す。
機種依存文字は、以下の文字を指す。
Shift_JISコード上でのNEC選定IBM拡張文字(89-92区)、IBM拡張文字(115-119区)、特殊文字エリア、JIS外字エリア、MAC外字及び縦組用、 JIS領域外の13区の記号。 Unicode上でのプライベート領域(U+E000~U+F8FF、U+F0000~U+10FFFF)。
携帯絵文字も機種依存文字に含まれる。(文字コード変換によってUnicode上でのプライベート領域にマップされる)
$bool = $val->isPcPortable
携帯絵文字以外で構成されていれば1。 そうでなければ(携帯絵文字を含んでいれば)undefを返す。
携帯絵文字は、文字コード変換によって Unicode上のプライベート領域(U+FF000~U+FFFFF)に マップされます。この領域の文字があるかで判定を行います。
$bool = $val->isDomainName
ドメイン名として正当であれば 1 を返し、そうでなければ undef を返す。
$bool = $val->isIpAddress($checkmask)
$checkmaskに対して、設定されたIPアドレスが一致すれば1。そうでなければundef。
$checkmaskは空白で区切って複数個指定する事が可能。
例:'10.0.0.0/8 172.16.0.0/12 192.168.0.0/16 127.0.0.1 fe80::/10 ::1'。
$bool = $val->isDateString('%Y/%m/%d')
日付フォーマット文字列で指定された形式に沿っていれば1。そうでなければundef。 フォーマット文字列は Tripletail::DateTime#strFormat のものと同一である。
$bool = $val->isChar($format) $format ::= 'digit' | 'alpha' | 'loweralpha' | 'upperalpha' | ARRAYREF of char
指定された文字のみで構成されていれば 1 、そうでなければ undef 。
空文字列に対しては undef を返す。
$val->convHira
ひらがなに変換する。
$val->convKata
カタカナに変換する。
$val->convNumber
半角数字に変換する。
$val->convNarrow
全角文字を半角に変換する。
$val->convWide
半角文字を全角に変換する。
$val->convKanaNarrow
全角カタカナを半角に変換する。
$val->convKanaWide
半角カタカナを全角に変換する。
$val->convComma
半角数字を3桁区切りのカンマ表記に変換する。
$val->convLF
改行コードを LF (\n) に変換する。
$val->convBR
改行コードを <BR>\n に変換する。
$val->forceHira
ひらがな以外の文字は削除。
$val->forceKata
カタカナ以外の文字は削除。
$val->forceNumber
半角数字以外の文字は削除。
$val->forceMin($max,$val)
半角数字以外の文字を削除し、min未満なら$valをセットする。$val省略時はundefをセットする。
$val->forceMax($max,$val)
半角数字以外の文字を削除し、maxより大きければ$valをセットする。$val省略時はundefをセットする。
$val->forceMaxLen($max)
最大バイト数を指定。超える場合はそのバイト数までカットする。
$val->forceMaxUtf8Len($max)
UTF-8での最大バイト数を指定。 超える場合はそのバイト数以下まで UTF-8の文字単位でカットする。
$val->forceMaxSjisLen($max)
SJISでの最大バイト数を指定。超える場合はそのバイト数以下まで SJISの文字単位でカットする。
$val->forceMaxCharLen($max)
最大文字数を指定。超える場合はその文字数以下までカットする。
$val->forcePortable
機種依存文字を削除。(携帯絵文字も機種依存文字に含む)
詳しい判定条件は isPortable メソッドを参照。
$val->forcePcPortable
携帯絵文字を削除。
詳しい判定条件は isPcPortable メソッドを参照。
$val->trimWhitespace
値の前後に付いている半角/全角スペース、タブを削除する。
全角/半角スペースで単語に区切った時の個数を返す。
@str = $val->strCut($charanum)
指定された文字数で文字列を区切り、配列に格納する。
@str = $val->strCutSjis($charanum)
Shift_JISコードに変換した際に、指定されたバイト数以下になるように 文字列を区切り、配列に格納する。
@str = $val->strCutUtf8($charanum)
UTF-8コードに変換した際に、指定されたバイト数以下になるように 文字列を区切り、配列に格納する。
$randomstring = $val->genRandomString($length) $randomstring = $val->genRandomString($length, \@types)
$length で指定された文字列長のランダムな文字列を生成する。
使用する文字の種類は配列リファレンスで指定する。
小文字アルファベット、大文字アルファベット、数値に関してはそれぞれ、
alpha、ALPHA、num で指定が可能。
文字種を省略した時にデフォルトで使われる文字は以下の通り:
2 3 4 5 6 7 8 a c d e f g h m n p r t u v w x y z A B C D E F G H J K L M N P R S T U V W X Y Z
$charset = $val->detectMobileAgent()
User-Agent 文字列から携帯電話の文字コード名を判別して返す。返される文字列は 'sjis-au' のような Unicode::Japanese の文字コード名になる。判別できなかった場合は undef を返す。
判別に使われる規則は次の通り。
UserAgent が DoCoMo で始まる → sjis-imode ASTEL で始まる → sjis-doti Vodafone で始まる → utf8-jsky Vemulator で始まる → utf8-jsky SoftBank で始まる → utf8-jsky Semulator で始まる → utf8-jsky MOT- で始まる → utf8-jsky J-PHONE で始まる → sjis-jsky J-EMULATOR で始まる → sjis-jsky UP.Browser で始まる → sjis-au
Copyright 2006 YMIRLINK Inc.
This framework is free software; you can redistribute it and/or modify it under the same terms as Perl itself
このフレームワークはフリーソフトウェアです。あなたは Perl と同じライセンスの 元で再配布及び変更を行うことが出来ます。
Address bug reports and comments to: tl@tripletail.jp
HP : http://tripletail.jp/
| Tripletail documentation | Contained in the Tripletail distribution. |
# ----------------------------------------------------------------------------- # Tripletail::Value - å¤ã®æ¤è¨¼ã夿 # ----------------------------------------------------------------------------- package Tripletail::Value; use strict; use warnings; use Tripletail; #---------------------------------- æ£è¦è¡¨ç¾ my $atext = qr{[\w\!\#\$\%\&\'\*\+\-\/\=\?\^\_\`\{\|\}\~]+}; my $dotString = qr{[\w\!\#\$\%\&\'\*\+\-\/\=\?\^\_\`\{\|\}\~\.]*}; my $pcmailexp = qr{^ ((?: (?:$atext(?:\.?$atext)*) # Dot-string | (?:"(\\[\x20-\x7f]|[\x21\x23-\x5b\x5d-\x7e])+") # Quoted-string )) # Local-part \@ ([\w\-]+(?:\.[\w\-]+)+) # Domain-part \z}x; my $mobilemailexp = qr{^ ((?: (?:$atext(?:$dotString)) # Dot-string | (?:"(\\[\x20-\x7f]|[\x21\x23-\x5b\x5d-\x7e])+") # Quoted-string )) # Local-part \@ ([\w\-]+(?:\.[\w\-]+)+) # Domain-part \z}x; my $re_hira = qr/\xe3(?:\x81[\x81-\xbf]|\x82[\x80-\x93]|\x83\xbc)/; # xa-mi,mu-n,ã¼ my $re_kata = qr/\xe3(?:\x82[\xa1-\xbf]|\x83[\x80-\xb3]|\x83\xbc)/; # xa-ta,da-n,ã¼ my $re_char = qr/[\x00-\x7f]|[\xc0-\xdf][\x80-\xbf]|[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xf7][\x80-\xbf]{3}|[\xf8-\xfb][\x80-\xbf]{4}|[\xfc-\xfd][\x80-\xbf]{5}/; my $re_widenum = qr/\xef\xbc[\x90-\x99]/; my $re_ipv4_addr = qr{^ (?: :: (?:f{4}:)? )? ( (?: 0* (?: 2[0-4]\d | 25[0-5] | [01]?\d\d | \d) \.){3} 0* (?: 2[0-4]\d | 25[0-5] | [01]?\d\d | \d) ) $}ix; # IPv4 å°å½± IPv6 ã¢ãã¬ã¹ ã¯æªãµãã¼ã my $re_ipv6_addr = qr{^ [:a-fA-F0-9]{2,39} $}x; # ãã¡ã¤ã³ my $re_domain = do { my $letter = qr{ [a-zA-Z] }x; my $letter_digit = qr{ [a-zA-Z0-9] }x; my $letter_digit_hyphen = qr{ [a-zA-Z0-9\-] }x; # RFC ã§ã¯ã©ãã«ã®å é ã«æ°åãæ¥ãäºãç¦æ¢ãã¦ããããå®éã«ã¯ãã®ãããªãã¡ # ã¤ã³ãåå¨ããã my $label = qr{ ${letter_digit} # RFC ã¨ãã¦ã¯ãã㯠${letter} ãæ£ããã (?: ${letter_digit_hyphen} {0,61} # ã©ãã«ã¯1æå以ä¸63æå以å ã ${letter_digit} )? }x; my $domain = qr{^ $label (?: \. $label)* $}x; $domain; }; my @MOBILE_AGENTS = ( # [æ£è¦è¡¨ç¾, UniJP ã®æåã³ã¼ãå] [qr/^DoCoMo/i , 'sjis-imode'], [qr/^ASTEL/i , 'sjis-doti' ], [qr/^Vodafone/i , 'utf8-jsky' ], [qr/^Vemulator/i , 'utf8-jsky' ], [qr/^SoftBank/i , 'utf8-jsky' ], [qr/^Semulator/i , 'utf8-jsky' ], [qr/^MOT-/i , 'utf8-jsky' ], [qr/^J-PHONE/i , 'sjis-jsky' ], [qr/^J-EMULATOR/i, 'sjis-jsky' ], # Softbank端æ«ãã¤UP.Browserãå«ããã®ãããã®ã§Softbankã®å¾ã«å¤å¥ããã㨠[qr/UP\.Browser/i, 'sjis-au' ], ); 1; #---------------------------------- ä¸è¬ sub _new { my $class = shift; my $this = bless {} => $class; $this->{value} = undef; if(@_) { $this->set(@_); } $this; } sub set { my $this = shift; my $value = shift; if(ref($value)) { die __PACKAGE__."#set: arg[1] is a reference. [$value] (第1弿°ããªãã¡ã¬ã³ã¹ã§ã)\n"; } $this->{value} = $value; $this; } sub get { my $this = shift; $this->{value}; } #---------------------------------- setç³» sub setDate { my $this = shift; my $year = shift; my $mon = shift; my $day = shift; if($this->_isExistentDay($year, $mon, $day)) { $this->{value} = sprintf '%04d-%02d-%02d', $year, $mon, $day; } else { $this->{value} = undef; } $this; } sub setDateTime { my $this = shift; my $year = shift; my $mon = shift; my $day = shift; my $hour = shift; my $min = shift || 0; my $sec = shift || 0; if($this->_isExistentDay($year, $mon, $day) && $this->_isExistentTime($hour, $min, $sec)) { $this->{value} = sprintf( '%04d-%02d-%02d %02d:%02d:%02d', $year, $mon, $day, $hour, $min, $sec, ); } else { $this->{value} = undef; } $this; } sub setTime { my $this = shift; my $hour = shift; my $min = shift || 0; my $sec = shift || 0; if($this->_isExistentTime($hour, $min, $sec)) { $this->{value} = sprintf '%02d:%02d:%02d', $hour, $min, $sec; } else { $this->{value} = undef; } $this; } #---------------------------------- getç³» sub getLen { my $this = shift; length $this->{value}; } sub getSjisLen { my $this = shift; length Unicode::Japanese->new($this->{value})->sjis; } sub getCharLen { my $this = shift; my @chars = grep {defined && length} split /($re_char)/, $this->{value}; scalar @chars; } sub getAge { my $this = shift; my $date = shift; my @from = $this->_parseDate($this->{value}); my @to = do { if(defined($date)) { $this->_parseDate($date); } else { my @lt = localtime; $lt[5] += 1900; $lt[4]++; @lt[5, 4, 3]; } }; if(!@to || !$this->_isExistentDay(@to)) { return undef; } my $age = $to[0] - $from[0]; if($to[1] < $from[1] || ($to[1] == $from[1] && $to[2] < $from[2])) { $age--; } $age; } sub getRegexp { my $this = shift; my $type = shift; if(!defined($type)) { die __PACKAGE__."#getRegexp: arg[1] is not defined. (第1弿°ãæå®ããã¦ãã¾ãã)\n"; } elsif(ref($type)) { die __PACKAGE__."#getRegexp: arg[1] is a reference. [$type] (第1弿°ããªãã¡ã¬ã³ã¹ã§ã)\n"; } my $regexp; $type = lc($type); if($type eq 'hira') { $regexp = $re_hira; } elsif($type eq 'kata') { $regexp = $re_kata; } elsif($type eq 'numbernarrow') { $regexp = qr{\d}; } elsif($type eq 'numberwide') { $regexp = $re_widenum; } else { die __PACKAGE__."#getRegexp: arg[1] is an invalid type. [$type] (æå®ãããæ£è¦è¡¨ç¾ã¯åå¨ãã¾ãã)\n"; } $regexp; } #---------------------------------- isç³» sub isEmpty { my $this = shift; not length $this->{value}; } sub isWhitespace { # åè§/å ¨è§ã¹ãã¼ã¹ãã¿ãã®ã¿ã§æ§æããã¦ãããªã1ã # 空æååãundefãªãundefã my $this = shift; if(length($this->{value})) { $this->{value} =~ /\A(?:\s|ã)+\z/ ? 1 : undef; } else { undef; } } sub isBlank { my $this = shift; if($this->isEmpty || $this->isWhitespace) { 1; } else { undef; } } sub isPrintableAscii { my $this = shift; if(length($this->{value})) { $this->{value} =~ /\A[\x20-\x7e]*\z/ ? 1 : undef; } else { undef; } } sub isWide { my $this = shift; if(length($this->{value})) { my $sjisvalue = $TL->charconv($this->{value}, 'UTF-8' => 'Shift_JIS'); my $re_char = '[\x81-\x9f\xe0-\xef\xfa-\xfc][\x40-\x7e\x80-\xfc]|[\xa1-\xdf]|[\x00-\x7f]'; my @chars = grep {defined && length} split /($re_char)/, $sjisvalue; !grep { length($_) == 1 } @chars; } else { undef; } } sub isPassword { my $this = shift; if(!defined($this->{value})) { return undef; } if(!$this->isPrintableAscii() ) { return undef; } my $deftypes = ['alpha', 'ALPHA', 'digit', 'symbol']; my $matcher = { alpha => qr/[a-z]/, ALPHA => qr/[A-Z]/, digit => qr/[0-9]/, symbol => qr/[\x21-\x2f\x3a-\x40\x5b-\x60\x7b-\x7e]/, # ! " # $ % & ' ( ) * + ' - . / # : ; < = > ? @ [ \ ] ^ _ ` { | } ~ }; my $tokens = @_ ? [@_] : $deftypes; my $tmp = $this->{value}; foreach my $token (@$tokens) { my $re = $matcher->{$token}; if( !$re && ref($token) eq 'ARRAY' ) { $re = join('|', @$token); } $re or die __PACKAGE__."#isPassword: invalid argument. [$token] (ç¡å¹ãªå¤ã§ã)\n"; if( $tmp !~ s/$re//g ) { return undef; } } 1; # accepted. } sub isZipCode { my $this = shift; if(!defined($this->{value})) { return undef; } $this->{value} =~ /\A\d{3}-\d{4}\z/ ? 1 : undef; } sub isTelNumber { my $this = shift; if(!defined($this->{value})) { return undef; } $this->{value} =~ /\A\d[\d-]+\d\z/ ? 1 : undef; } sub isEmail { my $this = shift; if(!defined($this->{value})) { return undef; } $this->{value} =~ /$pcmailexp/ ? 1 : undef; } sub isMobileEmail { my $this = shift; if(!defined($this->{value})) { return undef; } $this->{value} =~ /$mobilemailexp/ ? 1 : undef; } sub isInteger { my $this = shift; my $min = shift; my $max = shift; if(!defined($this->{value})) { return undef; } if($this->{value} =~ m/\A-?\d+\z/) { if(defined($min)) { $this->{value} >= $min or return undef; } if(defined($max)) { $this->{value} <= $max or return undef; } 1; } else { undef; } } sub isReal { my $this = shift; my $min = shift; my $max = shift; if(!defined($this->{value})) { return undef; } if($this->{value} =~ m/\A-?\d+(?:\.\d+)?\z/) { if(defined($min)) { $this->{value} >= $min or return undef; } if(defined($max)) { $this->{value} <= $max or return undef; } 1; } else { undef; } } sub isHira { my $this = shift; if(!defined($this->{value})) { return undef; } $this->{value} =~ m/\A$re_hira+\z/ ? 1 : undef; } sub isKata { my $this = shift; if(!defined($this->{value})) { return undef; } $this->{value} =~ m/\A$re_kata+\z/ ? 1 : undef; } sub isExistentDay { # YYYY-MM-DD ãã®æ¥ãåå¨ãããªã1 my $this = shift; if(!defined($this->{value})) { return undef; } my @date = $this->_parseDate($this->{value}); @date ? $this->_isExistentDay(@date) : undef; } sub isGif { my $this = shift; if(!defined($this->{value})) { return undef; } $this->{value} =~ /\AGIF8[79]a/ ? 1 : undef; } sub isJpeg { my $this = shift; if(!defined($this->{value})) { return undef; } $this->{value} =~ /\A\xFF\xD8/ ? 1 : undef; } sub isPng { my $this = shift; if(!defined($this->{value})) { return undef; } $this->{value} =~ /\A\x89PNG\x0D\x0A\x1A\x0A/ ? 1 : undef; } sub isHttpUrl { my $this = shift; if(!defined($this->{value})) { return undef; } $this->{value} =~ m!\Ahttp://! ? 1 : undef; } sub isHttpsUrl { my $this = shift; if(!defined($this->{value})) { return undef; } $this->{value} =~ m!\Ahttps://! ? 1 : undef; } sub isLen { my $this = shift; my $min = shift; my $max = shift; if(!defined($this->{value})) { return undef; } my $len = $this->getLen; if(defined($min)) { $len >= $min or return undef; } if(defined($max)) { $len <= $max or return undef; } 1; } sub isSjisLen { my $this = shift; my $min = shift; my $max = shift; if(!defined($this->{value})) { return undef; } my $len = $this->getSjisLen; if(defined($min)) { $len >= $min or return undef; } if(defined($max)) { $len <= $max or return undef; } 1; } sub isCharLen { my $this = shift; my $min = shift; my $max = shift; if(!defined($this->{value})) { return undef; } my $len = $this->getCharLen; if(defined($min)) { $len >= $min or return undef; } if(defined($max)) { $len <= $max or return undef; } 1; } sub isPortable { # æ©ç¨®ä¾åæåãå«ãã§ããªããªã1 my $this = shift; my $str = $this->{value}; if(!defined($this->{value})) { return undef; } my $unijp = Unicode::Japanese->new; my @chars = grep {defined && length} split /($re_char)/, $this->{value}; # æ©ç¨®ä¾åæå my $dep_regex = '\xED[\x40-\xFF]|\xEE[\x00-\xFC]' # NECé¸å®IBMæ¡å¼µæå(89-92åº) . '|[\xFA\xFB][\x40-\xFF]|\xFC[\x40-\x4B]' # IBMæ¡å¼µæå(115-119åº) . '|[\x85-\x87][\x40-\xFF]|\x88[\x40-\x9E]' # ç¹æ®æåã¨ãªã¢ . '|[\xF0-\xF8][\x40-\xFF]|\xF9[\x40-\xFC]' # JISå¤åã¨ãªã¢ . '|\xEA[\xA5-\xFF]|[\xEB-\xFB][\x40-\xFF]|\xFC[\x40-\xFC]' # MACå¤ååã³ç¸¦çµç¨ . '|\x81[\xBE\xBF\xDA\xDB\xDF\xE0\xE3\xE6\xE7]'; # JISé åå¤ã®13åºã®è¨å· # SJIS foreach my $str (@chars) { my $str_sjis = $unijp->set($str, 'utf8')->sjis; return undef if($str_sjis =~ m/\A(?:$dep_regex)\z/o); } # Unicodeã®ãã©ã¤ãã¼ãé åå¤å®ï¼U+E000ï½U+F8FFãU+F0000ï½U+10FFFFï¼ foreach my $str (@chars) { my $str_ucs4 = $unijp->set($str, 'utf8')->ucs4; return undef if($str_ucs4 =~ m/\A\x00\x00[\xe0-\xf8][\x00-\xff]\z/o); return undef if($str_ucs4 =~ m/\A\x00[\x0f-\x10][\x00-\xff][\x00-\xff]\z/o); } return 1; } sub isPcPortable { # æºå¸¯çµµæåãå«ãã§ããªããªã1 my $this = shift; my $str = $this->{value}; if(!defined($this->{value})) { return undef; } my $unijp = Unicode::Japanese->new; my @chars = grep {defined && length} split /($re_char)/, $this->{value}; # Unicodeã®ãã©ã¤ãã¼ãé åå¤å®ï¼U+FE000ï½U+FFFFFï¼ foreach my $str (@chars) { my $str_ucs4 = $unijp->set($str, 'utf8')->ucs4; return undef if($str_ucs4 =~ m/\A\x00\x0f[\xe0-\xff][\x00-\xff]\z/o); } return 1; } sub isDomainName { my $this = shift; if (defined $this->{value}) { return length($this->{value}) <= 255 && $this->{value} =~ m/$re_domain/o; } else { return; } } sub isIpAddress { my $this = shift; my $checkmask = shift; my $checkip = $this->{value}; if(!defined($this->{value})) { return undef; } if(!defined($checkmask)) { return undef; } elsif(ref($checkmask)) { return undef; } my @masks = split /\s+/, $checkmask; my @ip = $this->_parse_addr($checkip); if(@ip != 4 && @ip != 16) { # ãã¼ã¹å¤±æ return undef; } else { foreach my $mask (@masks) { my $bits; if($mask =~ s!/(\d+)$!!) { $bits = $1; } my @mask = $this->_parse_addr($mask); if(@mask != 4 and @mask != 16) { # ãã¼ã¹å¤±æ return undef; } if(@mask != @ip) { # IPãã¼ã¸ã§ã³éã next; } # ãããæ°ãæå®ããããªãã£ãå ´å㯠/32 ã¾ã㯠/128 ã¨è¦åãã defined $bits or $bits = (@mask == 4 ? 32 : 128); if($this->_ip_match(\@ip, \@mask, $bits)) { # ããããã return 1; } } # ã©ãã«ããããããªãã£ãã return undef; } } sub isDateString { my $this = shift; my $format = shift; if (!defined $this->{value}) { return; } eval { local $SIG{__DIE__} = 'DEFAULT'; $TL->newDateTime->parseFormat($format, $this->{value}); }; if (my $err = $@) { # è¯ããªãããä»ã«æ¹æ³ãç¡ãã if ($err =~ m/does not match to/) { return; } else { die $@; } } else { return 1; } } sub isChar { my $this = shift; if( !@_ ) { die __PACKAGE__."#isChar, no arguments specified. (弿°ãæå®ããã¦ãã¾ãã)\n"; } my @chars; foreach my $i (1..@_) { my $val = $_[$i-1]; if( !defined($val) ) { die __PACKAGE__."#isChar, arg[$i] is not defined. (第$i弿°ãæå®ããã¦ãã¾ãã)\n"; } if( ref($val) ) { if( ref($val) ne 'ARRAY' ) { die __PACKAGE__."#isChar, arg[$i] is not array-ref. (第$i弿°ã¯é åãªãã¡ã¬ã³ã¹ã§ã¯ããã¾ãã)\n"; } push(@chars, $val); }else { our $MAPS ||= { digit => [0..9], loweralpha => ['a'..'z'], upperalpha => ['A'..'Z'], alpha => ['a'..'z', 'A'..'Z'], '-' => ['-'], '_' => ['_'], }; foreach my $name (map{lc($_)} split(/[\s,]+/, $val)) { my $list = $MAPS->{$name}; if( !$list ) { die __PACKAGE__."#isChar, invalid name [$name]. (ç¡å¹ãªå¤ã§ã [$name])\n"; } push(@chars, $list); } } } if( !defined($this->{value}) ) { # undefined is not acceptable. return; } if( $this->{value} eq '' ) { # empty is not acceptable. return; } foreach my $ch (split(//, $this->{value})) { my $accepted; foreach my $list (@chars) { if( grep { $_ eq $ch } @$list ) { $accepted = 1; last; } } if( !$accepted ) { # rejected. return undef; } } # all accepted. return 1; } #---------------------------------- convç³» sub convHira { my $this = shift; if(!defined($this->{value})) { return $this; } my $unijp = Unicode::Japanese->new($this->{value}); $this->{value} = $unijp->kata2hira->get; $this; } sub convKata { my $this = shift; if(!defined($this->{value})) { return $this; } my $unijp = Unicode::Japanese->new($this->{value}); $this->{value} = $unijp->hira2kata->get; $this; } sub convNumber { my $this = shift; if(!defined($this->{value})) { return $this; } my $unijp = Unicode::Japanese->new($this->{value}); $this->{value} = $unijp->z2hNum->get; $this; } sub convNarrow { my $this = shift; if(!defined($this->{value})) { return $this; } my $unijp = Unicode::Japanese->new($this->{value}); $this->{value} = $unijp->z2h->get; $this; } sub convWide { my $this = shift; if(!defined($this->{value})) { return $this; } my $unijp = Unicode::Japanese->new($this->{value}); $this->{value} = $unijp->h2z->get; $this; } sub convKanaNarrow { my $this = shift; if(!defined($this->{value})) { return $this; } my $unijp = Unicode::Japanese->new($this->{value}); $this->{value} = $unijp->z2hKana->get; $this; } sub convKanaWide { my $this = shift; if(!defined($this->{value})) { return $this; } my $unijp = Unicode::Japanese->new($this->{value}); $this->{value} = $unijp->h2zKana->get; $this; } sub convComma { my $this = shift; if(!defined($this->{value})) { return $this; } $this->{value} =~ s/\G((?:^[-+])?\d{1,3})(?=(?:\d\d\d)+(?!\d))/$1,/g; $this; } sub convLF { my $this = shift; if(!defined($this->{value})) { return $this; } $this->{value} =~ s/\r\n/\n/g; $this->{value} =~ s/\r/\n/g; $this; } sub convBR { my $this = shift; if(!defined($this->{value})) { return $this; } $this->{value} =~ s/\r\n/\n/g; $this->{value} =~ s/\r/\n/g; $this->{value} =~ s/\n/<BR>\n/g; $this; } #---------------------------------- forceç³» sub forceHira { my $this = shift; if(!defined($this->{value})) { return $this; } $this->{value} = join('', $this->{value}=~/($re_hira+)/go); $this; } sub forceKata { # forceHiraã®é my $this = shift; if(!defined($this->{value})) { return $this; } $this->{value} = join('', $this->{value}=~/($re_kata+)/go); $this; } sub forceNumber { my $this = shift; if(!defined($this->{value})) { return $this; } $this->{value} = join('', $this->{value}=~/(\d+)/go); $this; } sub forceMin { my $this = shift; my $min = shift; my $val = shift; if(!defined($this->{value})) { return $this; } if(!defined($min)) { die __PACKAGE__."#forceMin: arg[1] is not defined. (第1弿°ãæå®ããã¦ãã¾ãã)\n"; } elsif(ref($min)) { die __PACKAGE__."#forceMin: arg[1] is a reference. [$min] (第1弿°ããªãã¡ã¬ã³ã¹ã§ã)\n"; } $this->forceNumber; if($this->{value} < $min) { $this->{value} = $val; } $this; } sub forceMax { my $this = shift; my $max = shift; my $val = shift; if(!defined($this->{value})) { return $this; } if(!defined($max)) { die __PACKAGE__."#forceMax: arg[1] is not defined. (第1弿°ãæå®ããã¦ãã¾ãã)\n"; } elsif(ref($max)) { die __PACKAGE__."#forceMax: arg[1] is a reference. [$max] (第1弿°ããªãã¡ã¬ã³ã¹ã§ã)\n"; } $this->forceNumber; if($this->{value} > $max) { $this->{value} = $val; } $this; } sub forceMaxLen { my $this = shift; my $maxlen = shift; if(!defined($this->{value})) { return $this; } if(length($this->{value}) > $maxlen) { substr($this->{value}, $maxlen) = ''; } $this; } sub forceMaxUtf8Len { my $this = shift; my $maxlen = shift; if(!defined($this->{value})) { return $this; } if(length($this->{value}) > $maxlen) { # $maxlenãã¤ãã«å ¥ãããã¾ã§ä¸æåãã¤å ¥ãã¦ãã my @chars = split /($re_char)/, $this->{value}; $this->{value} = ''; my $current_len = 0; foreach my $c (@chars) { if($current_len + length($c) <= $maxlen) { $this->{value} .= $c; $current_len += length($c); } else { # ãã以ä¸å ¥ããªã last; } } } $this; } sub forceMaxSjisLen { my $this = shift; my $maxlen = shift; if(!defined($this->{value})) { return $this; } my $unijp = Unicode::Japanese->new; if(length($unijp->set($this->{value})->sjis) > $maxlen) { # $maxlenãã¤ãã«å ¥ãããã¾ã§ä¸æåãã¤å ¥ãã¦ãã my @chars = split /($re_char)/, $this->{value}; $this->{value} = ''; my $current_len = 0; foreach my $c (@chars) { my $sjis_c = $unijp->set($c)->sjis; if($current_len + length($sjis_c) <= $maxlen) { $this->{value} .= $c; $current_len += length($sjis_c); } else { # ãã以ä¸å ¥ããªã last; } } } $this; } sub forceMaxCharLen { my $this = shift; my $maxlen = shift; if(!defined($this->{value})) { return $this; } my @chars = grep {defined && length} split /($re_char)/, $this->{value}; if(@chars > $maxlen) { splice @chars, $maxlen; $this->{value} = join '', @chars; } $this; } sub forcePortable { my $this = shift; if(!defined($this->{value})) { return $this; } my $v = $TL->newValue; my $newval = ''; my @chars = grep {defined && length} split /($re_char)/, $this->{value}; foreach my $ch (@chars) { if($v->set($ch)->isPortable) { $newval .= $ch; } } $this->{value} = $newval; $this; } sub forcePcPortable { my $this = shift; if(!defined($this->{value})) { return $this; } my $v = $TL->newValue; my $newval = ''; my @chars = grep {defined && length} split /($re_char)/, $this->{value}; foreach my $ch (@chars) { if($v->set($ch)->isPcPortable) { $newval .= $ch; } } $this->{value} = $newval; $this; } #---------------------------------- ãã®ä» sub trimWhitespace { # æåååå¾ã®åè§/å ¨è§ã¹ãã¼ã¹ãã¿ããåé¤ my $this = shift; if(!defined($this->{value})) { return $this; } $this->{value} =~ s/\A(?:\s|ã)+//; $this->{value} =~ s/(?:\s|ã)+\z//; $this; } sub countWords { my $this = shift; my @words = split /(?:\s|ã)+/, $this->{value}; scalar @words; } sub strCut { my $this = shift; my $charanum = shift; if(!defined($this->{value})) { return $this; } my $v = $TL->newValue; my $value = $this->{value}; my @output; while(length($value)) { $v->{value} = $value; my $temp = $v->forceMaxCharLen($charanum)->get; $value = substr($value,length($temp)); push(@output,$temp); } @output; } sub strCutSjis { my $this = shift; my $charanum = shift; if(!defined($this->{value})) { return $this; } my $v = $TL->newValue; my $value = $this->{value}; my @output; while(length($value)) { $v->{value} = $value; my $temp = $v->forceMaxSjisLen($charanum)->get; $value = substr($value,length($temp)); push(@output,$temp); } @output; } sub strCutUtf8 { my $this = shift; my $charanum = shift; if(!defined($this->{value})) { return $this; } my $v = $TL->newValue; my $value = $this->{value}; my @output; while(length($value)) { $v->{value} = $value; my $temp = $v->forceMaxUtf8Len($charanum)->get; $value = substr($value,length($temp)); push(@output,$temp); } @output; } sub genRandomString { my $this = shift; my $length = shift; my $type = shift; if(!defined($length)) { die __PACKAGE__."#genRandomString: arg[1] is not defined. (第1弿°ãæå®ããã¦ãã¾ãã)\n"; } elsif(ref($length)) { die __PACKAGE__."#genRandomString: arg[1] is a reference. [$length] (第1弿°ããªãã¡ã¬ã³ã¹ã§ã)\n"; } if(!defined($type)) { $type = ['std']; } elsif(ref($type) ne 'ARRAY') { die __PACKAGE__."#genRandomString: arg[2] is not an ARRAY Ref. (第2弿°ãé åã®ãªãã¡ã¬ã³ã¹ã§ã¯ããã¾ãã)\n"; } my @str; foreach my $key (@$type) { if($key eq 'alpha') { push(@str,'a'..'z'); } elsif($key eq 'ALPHA') { push(@str,'A'..'Z'); } elsif($key eq 'num' || $key eq 'NUM') { push(@str,'0'..'9'); } elsif($key eq 'std') { push(@str, qw( 2 3 4 5 6 7 8 ), qw(a c d e f g h m n p r t u v w x y z), qw(A B C D E F G H J K L M N P R S T U V W X Y Z), ); } elsif($TL->newValue($key)->isCharLen(1,1)) { push(@str,$key); } else { die __PACKAGE__."#genRandomString: arg[2] [$key] is an invalid type. (第2弿°ã® $key ã¯ãµãã¼ãããã¦ãã¾ãã)\n"; } } if(!@str) { die __PACKAGE__."#genRandomString: arg[2] is not defined. (第2弿°ãæå®ããã¦ãã¾ãã)\n"; } my $password = ''; for(1..$length) { $password .= $str[int(rand($#str+1))]; } $password; } sub detectMobileAgent { my $this = shift; if (defined $this->{value}) { foreach my $candidate (@MOBILE_AGENTS) { if ($this->{value} =~ m/$candidate->[0]/) { return $candidate->[1]; } } } return; } #---------------------------------- å é¨ã¡ã½ãã sub _isLeapYear { my $this = shift; my $y = shift; ($y % 4 == 0 && $y % 100 != 0) || $y % 400 == 0; } sub _isExistentDay { my $this = shift; my $year = shift; my $mon = shift; my $day = shift; if($mon < 1 || $mon > 12) { return 0; } my $maxday = do { if($this->_isLeapYear($year) && $mon == 2) { 29; } else { [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]->[$mon - 1]; } }; $day <= $maxday; } sub _isExistentTime { # ãããç§ã®ãã§ãã¯ã¯ããªããä¸è¦åã«æ¿å ¥ãããã®ã§äºæåºæ¥ãªãã my $this = shift; my $hour = shift; my $min = shift; my $sec = shift; $hour >= 0 && $hour <= 23 && $min >= 0 && $min <= 59 && $sec >= 0 && $sec <= 59; } sub _parseDate { my $this = shift; my $str = shift; if($str =~ m!^(\d{4})-(\d{2})-(\d{2})$!) { return ($1, $2, $3); } else { return (); } } sub _parse_addr { my $this = shift; my $addr = shift; if($addr =~ m/$re_ipv4_addr/) { # IPv4 $1 =~ m/\A(\d+)\.(\d+)\.(\d+)\.(\d+)\z/; ($1, $2, $3, $4); } elsif($addr =~ m/$re_ipv6_addr/) { # IPv6 my $word2bytes = sub { my $word = hex shift; (($word >> 8) & 0xff, $word & 0xff); }; if($addr =~ /::/) { # ç縮形å¼ãå±é my ($left, $right) = split /::/, $addr; my @left = split /:/, $left; my @right = split /:/, $right; foreach(scalar @left .. 7 - scalar @right) { push @left, 0 }; map { $word2bytes->($_) } (@left, @right); } else { map { $word2bytes->($_) } split /:/, $addr; } } else { (); } } sub _ip_match { my $this = shift; my $a = shift; my $b = shift; my $bits = shift; my $i = 0; # $bits == 0 ãªãã°ä½ã®æ¯è¼ãããã«ãä¸è´ãã¨ãã¦å¤å®ã # $bits == æå¤§å¤ ãªãã°å®å ¨ä¸è´ãããã©ããã§å¤å®ã while($bits > 0) { if($bits >= 8) { $a->[$i] != $b->[$i] and return 0; $bits -= 8; } else { # ä¸ä½ $bits ãããã®ã¿æ¯è¼ (($a->[$i] >> (8 - $bits)) & (2 ** $bits - 1)) != (($b->[$i] >> (8 - $bits)) & (2 ** $bits - 1)) and return 0; $bits = 0; } $i++; } 1; } __END__