;##################### ;# perl Library mycgi ;##################### package MyCGI; use Common; @ISA = qw(Common); use strict; use Jcode; use CGI; use DBI; use LWP; use LWP::Simple; use HTTP::Request::Common; use HTTP::Cookies; use MIME::Base64; use Utils; #=============================================== # デバッグ関係変数 #=============================================== my $Debug = 0; #=============================================== # 文字コード関係変数 #=============================================== # sjis, euc, jis, noconv, utf8 my $FileSystemCharCode = Deps::FileSystemCharCode(); my $PerlCharCode = Deps::PerlCharCode(); my $MySQLCharCode = Deps::MySQLCharCode(); my $WebCharCode = Deps::WebCharCode(); my $WebCharSet = Deps::WebCharSet(); #=============================================== # スクリプト大域変数 #=============================================== my $LF = Deps::LF(); my $DirectorySeparator = Deps::DirectorySeparator(); my $OS = Deps::OS(); BEGIN { } sub new { my ($module, $path) = @_; my $this = {}; bless $this; return $this; } sub DESTROY { my $this = shift; $this->Close(); } #=============================================== # 文字の正規表現 # http://www.din.or.jp/~ohzaki/perl.htm#Character #=============================================== # 半角スペース my $space = '\x20'; # 全角スペース my $Zspace = '(?:\xA1\xA1)'; # EUC-JP my $Zspace_sjis = '(?:\x81\x40)'; # SJIS # 全角数字 [0-9] my $Zdigit = '(?:\xA3[\xB0-\xB9])'; # EUC-JP my $Zdigit_sjis = '(?:\x82[\x4F-\x58])'; # SJIS # 全角大文字 [A-Z] my $Zuletter = '(?:\xA3[\xC1-\xDA])'; # EUC-JP my $Zuletter_sjis = '(?:\x82[\x60-\x79])'; # SJIS # 全角小文字 [a-z] my $Zlletter = '(?:\xA3[\xE1-\xFA])'; # EUC-JP my $Zlletter_sjis = '(?:\x82[\x81-\x9A])'; # SJIS # 全角アルファベット [A-Za-z] my $Zalphabet = '(?:\xA3[\xC1-\xDA\xE1-\xFA])'; # EUC-JP my $Zalphabet_sjis = '(?:\x82[\x60-\x79\x81-\x9A])'; # SJIS # 全角ひらがな [ぁ-ん] my $Zhiragana = '(?:\xA4[\xA1-\xF3])'; # EUC-JP my $Zhiragana_sjis = '(?:\x82[\x9F-\xF1])'; # SJIS # 全角ひらがな(拡張) [ぁ-ん゛゜ゝゞ] my $ZhiraganaExt = '(?:\xA4[\xA1-\xF3]|\xA1[\xAB\xAC\xB5\xB6])'; # EUC-JP my $ZhiraganaExt_sjis = '(?:\x82[\x9F-\xF1]|\x81[\x4A\x4B\x54\x55])'; # SJIS # 全角カタカナ [ァ-ヶ] my $Zkatakana = '(?:\xA5[\xA1-\xF6])'; # EUC-JP my $Zkatakana_sjis = '(?:\x83[\x40-\x96])'; # SJIS # 全角カタカナ(拡張) [ァ-ヶ・ーヽヾ] my $ZkatakanaExt = '(?:\xA5[\xA1-\xF6]|\xA1[\xA6\xBC\xB3\xB4])'; # EUC-JP my $ZkatakanaExt_sjis = '(?:\x83[\x40-\x96]|\x81[\x45\x5B\x52\x53])'; # SJIS # 半角カタカナ [ヲ-゜] my $Hkatakana = '(?:\x8E[\xA6-\xDF])'; # EUC-JP my $Hkatakana_sjis = '[\xA6-\xDF]'; # SJIS # EUC-JP文字 my $ascii = '[\x00-\x7F]'; # 1バイト EUC-JP文字 my $twoBytes = '(?:[\x8E\xA1-\xFE][\xA1-\xFE])'; # 2バイト EUC-JP文字 my $threeBytes = '(?:\x8F[\xA1-\xFE][\xA1-\xFE])'; # 3バイト EUC-JP文字 my $character = "(?:$ascii|$twoBytes|$threeBytes)"; # EUC-JP文字 # EUC-JP文字(機種依存文字・未定義領域・3バイト文字を含まない) my $character_strict = '(?:[\x00-\x7F]|' # ASCII . '\x8E[\xA1-\xDF]|' # 半角カタカナ . '[\xA1\xB0-\xCE\xD0-\xF3][\xA1-\xFE]|' # 1,16-46,48-83区 . '\xA2[\xA1-\xAE\xBA-\xC1\xCA-\xD0\xDC-\xEA\xF2-\xF9\xFE]|' # 2区 . '\xA3[\xB0-\xB9\xC1-\xDA\xE1-\xFA]|' # 3区 . '\xA4[\xA1-\xF3]|' # 4区 . '\xA5[\xA1-\xF6]|' # 5区 . '\xA6[\xA1-\xB8\xC1-\xD8]|' # 6区 . '\xA7[\xA1-\xC1\xD1-\xF1]|' # 7区 . '\xA8[\xA1-\xC0]|' # 8区 . '\xCF[\xA1-\xD3]|' # 47区 . '\xF4[\xA1-\xA6])'; # 84区 # EUC-JP未定義文字(機種依存文字・3バイト文字を含む) my $character_undef = '(?:[\xA9-\xAF\xF5-\xFE][\xA1-\xFE]|' # 9-15,85-94区 . '\x8E[\xE0-\xFE]|' # 半角カタカナ . '\xA2[\xAF-\xB9\xC2-\xC9\xD1-\xDB\xEB-\xF1\xFA-\xFD]|' # 2区 . '\xA3[\XA1-\xAF\xBA-\xC0\xDB-\xE0\xFB-\xFE]|' # 3区 . '\xA4[\xF4-\xFE]|' # 4区 . '\xA5[\xF7-\xFE]|' # 5区 . '\xA6[\xB9-\xC0\xD9-\xFE]|' # 6区 . '\xA7[\xC2-\xD0\xF2-\xFE]|' # 7区 . '\xA8[\xC1-\xFE]|' # 8区 . '\xCF[\xD4-\xFE]|' # 47区 . '\xF4[\xA7-\xFE]|' # 84区 . '\x8F[\xA1-\xFE][\xA1-\xFE])'; # 3バイト文字 # SJIS文字 my $oneByte_sjis = '[\x00-\x7F\xA1-\xDF]'; # 1バイト SJIS文字 my $twoBytes_sjis = '(?:[\x81-\x9F\xE0-\xFC][\x40-\x7E\x80-\xFC])'; # 2バイト SJIS文字 my $character_sjis = "(?:$oneByte_sjis|$twoBytes_sjis)"; # SJIS文字 # SJIS文字(機種依存文字・未定義領域を含まない) my $character_sjis_strict = '(?:[\x00-\x7F\xA1-\xDF]|' # ASCII,半角カタカナ . '[\x89-\x97\x99-\x9F\xE0-\xE9][\x40-\x7E\x80-\xFC]|' # 17-46,49-82区 . '\x81[\x40-\x7E\x80-\xAC\xB8-\xBF\xC8-\xCE\xDA-\xE8\xF0-\xF7\xFC]|' # 1,2区 . '\x82[\x4F-\x58\x60-\x79\x81-\x9A\x9F-\xF1]|' # 3,4区 . '\x83[\x40-\x7E\x80-\x96\x9F-\xB6\xBF-\xD6]|' # 5,6区 . '\x84[\x40-\x60\x70-\x7E\x80-\x91\x9F-\xBE]|' # 7,8区 . '\x88[\x9F-\xFC]|' # 15,16区 . '\x98[\x40-\x72\x9F-\xFC]|' # 47,48区 . '\xEA[\x40-\x7E\x80-\xA4])'; # 83,84区 # SJIS未定義文字(機種依存文字を含む) my $character_sjis_undef = '(?:[\x85-\x87\xEB-\xFC][\x40-\x7E\x80-\xFC]|' # 9-14,85-120区 . '\x81[\xAD-\xB7\xC0-\xC7\xCF-\xD9\xE9-\xEF\xF8-\xFB]|' # 1,2区 . '\x82[\x40-\x4E\x59-\x5F\x7A-\x7E\x80\x9B-\x9E\xF2-\xFC]|' # 3,4区 . '\x83[\x97-\x9E\xB7-\xBE\xD7-\xFC]|' # 5,6区 . '\x84[\x61-\x6F\x92-\x9E\xBF-\xFC]|' # 7,8区 . '\x88[\x40-\x7E\x80-\x9E]|' # 15,16区 . '\x98[\x73-\x7E\x80-\x9E]|' # 47,48区 . '\xEA[\xA5-\xFC])'; # 83,84区 # iモード対応 絵文字 my $iPictograph_base = '(?:\xF8[\x9F-\xFC]|' # 基本絵文字(SJIS) . '\xF9[\x40-\x49\x50-\x52\x55-\x57\x5B-\x5E\x72-\x7E\x80-\xB0])'; my $iPictograph_ext = '(?:\xF9[\xB1-\xFC])'; # 拡張絵文字(SJIS) my $iPictograph = '(?:$iPictograph_base|$iPictograph_ext)'; # iモード対応 絵文字(SJIS) #改行コードを統一する sub ChangeCRLF { # $target = "\n", "\r\n", "\r", "
\n", "" my ($s, $target) = @_; $s =~ s/\x0D\x0A|\x0D|\x0A/$target/g; return $s; } #数値を3桁ごとにカンマで区切る sub AddComma3 { my $s = @_; 1 while($s =~ s/^([-+]?\d+)(\d{3})/$1,$2/); return $s; } # $num を四捨五入して小数点以下 $decimals桁にする sub round { my ($num, $decimals) = @_; my ($format, $magic); $format = '%.' . $decimals . 'f'; $magic = ($num > 0) ? 0.5 : -0.5; sprintf($format, int(($num * (10 ** $decimals)) + $magic) / (10 ** $decimals)); } # $num を切り上げて小数点以下 $decimals桁にする sub ceil { my ($num, $decimals) = @_; my ($format, $tmp1, $tmp2); $format = '%.' . $decimals . 'f'; $tmp1 = $num * (10 ** $decimals); $tmp2 += $tmp1 <=> ($tmp2 = int($tmp1)); sprintf($format, $tmp2 / (10 ** $decimals)); } # HTMLタグの正規表現 $tag_regex my $tag_regex_ = q{[^"'<>]*(?:"[^"]*"[^"'<>]*|'[^']*'[^"'<>]*)*(?:>|(?=<)|$(?!\n))}; #'}}}}; my $comment_tag_regex = '-]*(?:-[^>-]+)*?)??)*(?:>|$(?!\n)|--.*$)'; my $tag_regex = qq{$comment_tag_regex|<$tag_regex_}; # $uri が正しい URI か判定する sub CheckURI { my $uri = @_; my $digit = q{[0-9]}; my $upalpha = q{[A-Z]}; my $lowalpha = q{[a-z]}; my $alpha = qq{(?:$lowalpha|$upalpha)}; my $alphanum = qq{(?:$alpha|$digit)}; my $hex = qq{(?:$digit|[A-Fa-f])}; my $escaped = qq{%$hex$hex}; my $mark = q{[-_.!~*'()]}; my $unreserved = qq{(?:$alphanum|$mark)}; my $reserved = q{[;/?:@&=+$,]}; my $uric = qq{(?:$reserved|$unreserved|$escaped)}; my $fragment = qq{$uric*}; my $query = qq{$uric*}; my $pchar = qq{(?:$unreserved|$escaped|} . q{[:@&=+$,])}; my $param = qq{$pchar*}; my $segment = qq{$pchar*(?:;$param)*}; my $path_segments = qq{$segment(?:/$segment)*}; my $abs_path = qq{/$path_segments}; my $uric_no_slash = qq{(?:$unreserved|$escaped|} . q{[;?:@&=+$,])}; my $opaque_part = qq{$uric_no_slash$uric*}; my $path = qq{(?:$abs_path|$opaque_part)?}; my $port = qq{$digit*}; my $IPv4address = qq{$digit+\\.$digit+\\.$digit+\\.$digit+}; my $toplabel = qq{(?:$alpha|$alpha(?:$alphanum|-)*$alphanum)}; my $domainlabel = qq{(?:$alphanum|$alphanum(?:$alphanum|-)*$alphanum)}; my $hostname = qq{(?:$domainlabel\\.)*$toplabel\\.?}; my $host = qq{(?:$hostname|$IPv4address)}; my $hostport = qq{$host(?::$port)?}; my $userinfo = qq{(?:$unreserved|$escaped|} . q{[;:&=+$,])*}; my $server = qq{(?:(?:$userinfo\@)?$hostport)?}; my $reg_name = qq{(?:$unreserved|$escaped|} . q{[$,;:@&=+])+}; my $authority = qq{(?:$server|$reg_name)}; my $scheme = qq{$alpha(?:$alpha|$digit|[-+.])*}; my $rel_segment = qq{(?:$unreserved|$escaped|} . q{[;@&=+$,])+}; my $rel_path = qq{$rel_segment(?:$abs_path)?}; my $net_path = qq{//$authority(?:$abs_path)?}; my $hier_part = qq{(?:$net_path|$abs_path)(?:\\?$query)?}; my $relativeURI = qq{(?:$net_path|$abs_path|$rel_path)(?:\\?$query)?}; my $absoluteURI = qq{$scheme:(?:$hier_part|$opaque_part)}; my $URI_reference = qq{(?:$absoluteURI|$relativeURI)?(?:#$fragment)?}; my $pattern = $URI_reference; return 1 if $uri =~ /^$pattern$/o; return 0; } # $http が正しい http URL か判定する sub CheckHTTPURL { my $http = @_; my $digit = q{[0-9]}; my $upalpha = q{[A-Z]}; my $lowalpha = q{[a-z]}; my $alpha = qq{(?:$lowalpha|$upalpha)}; my $alphanum = qq{(?:$alpha|$digit)}; my $hex = qq{(?:$digit|[A-Fa-f])}; my $escaped = qq{%$hex$hex}; my $mark = q{[-_.!~*'()]}; my $unreserved = qq{(?:$alphanum|$mark)}; my $reserved = q{[;/?:@&=+$,]}; my $uric = qq{(?:$reserved|$unreserved|$escaped)}; my $query = qq{$uric*}; my $pchar = qq{(?:$unreserved|$escaped|} . q{[:@&=+$,])}; my $param = qq{$pchar*}; my $segment = qq{$pchar*(?:;$param)*}; my $path_segments = qq{$segment(?:/$segment)*}; my $abs_path = qq{/$path_segments}; my $port = qq{$digit*}; my $IPv4address = qq{$digit+\\.$digit+\\.$digit+\\.$digit+}; my $toplabel = qq{(?:$alpha|$alpha(?:$alphanum|-)*$alphanum)}; my $domainlabel = qq{(?:$alphanum|$alphanum(?:$alphanum|-)*$alphanum)}; my $hostname = qq{(?:$domainlabel\\.)*$toplabel\\.?}; my $host = qq{(?:$hostname|$IPv4address)}; my $http_URL = qq{http://$host(?::$port)?(?:$abs_path(?:\\?$query)?)?}; my $pattern = $http_URL; return 1if $http =~ /^$pattern$/; return 0; } # ftp URL の正規表現 $ftp_URL_regex sub CheckFTPURL { my $ftp = @_; my $digit = q{[0-9]}; my $alpha = q{[a-zA-Z]}; my $alphanum = q{[a-zA-Z0-9]}; my $hex = q{[0-9A-Fa-f]}; my $escaped = qq{%$hex$hex}; my $uric = q{(?:[-_.!~*'()a-zA-Z0-9;/?:@&=+$,]} . qq{|$escaped)}; my $fragment = qq{$uric*}; my $query = qq{$uric*}; my $pchar = q{(?:[-_.!~*'()a-zA-Z0-9:@&=+$,]} . qq{|$escaped)}; my $segment = qq{$pchar*}; my $ftptype = q{[AIDaid]}; my $path_segments = qq{$segment(?:/$segment)*(?:;type=$ftptype)?}; my $abs_path = qq{/$path_segments}; my $port = qq{$digit*}; my $IPv4address = qq{$digit+\\.$digit+\\.$digit+\\.$digit+}; my $toplabel = qq{$alpha(?:} . q{[-a-zA-Z0-9]*} . qq{$alphanum)?}; my $domainlabel = qq{$alphanum(?:} . q{[-a-zA-Z0-9]*} . qq{$alphanum)?}; my $hostname = qq{(?:$domainlabel\\.)*$toplabel\\.?}; my $host = qq{(?:$hostname|$IPv4address)}; my $hostport = qq{$host(?::$port)?}; my $user = q{(?:[-_.!~*'()a-zA-Z0-9;&=+$,]|} . qq{$escaped)*}; my $password = $user; my $userinfo = qq{$user(?::$password)?}; my $server = qq{(?:$userinfo\@)?$hostport}; my $authority = qq{$server}; my $scheme = q{ftp}; my $net_path = qq{//$authority(?:$abs_path)?}; my $hier_part = qq{$net_path(?:\\?$query)?}; my $absoluteURI = qq{$scheme:$hier_part}; my $URI_reference = qq{$absoluteURI(?:#$fragment)?}; my $ftp_URL_regex = q{\b} . $URI_reference; return 1if $ftp =~ /^$ftp_URL_regex$/; return 0; } # $email が正しいメールアドレス(From用、"T. Kamiya "もOK)か判定する sub CheckEMailAddress { my $email = @_; my $esc = '\\\\'; my $Period = '\.'; my $space = '\040'; my $tab = '\t'; my $OpenBR = '\['; my $CloseBR = '\]'; my $OpenParen = '\('; my $CloseParen = '\)'; my $NonASCII = '\x80-\xff'; my $ctrl = '\000-\037'; my $CRlist = '\n\015'; my $qtext = qq/[^$esc$NonASCII$CRlist\"]/; my $dtext = qq/[^$esc$NonASCII$CRlist$OpenBR$CloseBR]/; my $quoted_pair = qq<${esc}[^$NonASCII]>; my $ctext = qq<[^$esc$NonASCII$CRlist()]>; my $Cnested = qq<$OpenParen$ctext*(?:$quoted_pair$ctext*)*$CloseParen>; my $comment = qq<$OpenParen$ctext*(?:(?:$quoted_pair|$Cnested)$ctext*)*$CloseParen>; my $X = qq<[$space$tab]*(?:${comment}[$space$tab]*)*>; my $atom_char = qq/[^($space)<>\@,;:\".$esc$OpenBR$CloseBR$ctrl$NonASCII]/; my $atom = qq<$atom_char+(?!$atom_char)>; my $quoted_str = qq<\"$qtext*(?:$quoted_pair$qtext*)*\">; my $word = qq<(?:$atom|$quoted_str)>; my $domain_ref = $atom; my $domain_lit = qq<$OpenBR(?:$dtext|$quoted_pair)*$CloseBR>; my $sub_domain = qq<(?:$domain_ref|$domain_lit)$X>; my $domain = qq<$sub_domain(?:$Period$X$sub_domain)*>; my $route = qq<\@$X$domain(?:,$X\@$X$domain)*:$X>; my $local_part = qq<$word$X(?:$Period$X$word$X)*>; my $addr_spec = qq<$local_part\@$X$domain>; my $route_addr = qq[<$X(?:$route)?$addr_spec>]; my $phrase_ctrl = '\000-\010\012-\037'; my $phrase_char = qq/[^()<>\@,;:\".$esc$OpenBR$CloseBR$NonASCII$phrase_ctrl]/; my $phrase = qq<$word$phrase_char*(?:(?:$comment|$quoted_str)$phrase_char*)*>; my $mailbox = qq<$X(?:$addr_spec|$phrase$route_addr)>; return 1 if $email =~ /^$mailbox$/o; return 0; } # メールアドレス(addr-spec)のみの正規表現 $mail_regex sub CheckEMailAddrSpec { my $email = @_; my $esc = '\\\\'; my $Period = '\.'; my $space = '\040'; my $OpenBR = '\['; my $CloseBR = '\]'; my $NonASCII = '\x80-\xff'; my $ctrl = '\000-\037'; my $CRlist = '\n\015'; my $qtext = qq/[^$esc$NonASCII$CRlist\"]/; my $dtext = qq/[^$esc$NonASCII$CRlist$OpenBR$CloseBR]/; my $quoted_pair = qq<${esc}[^$NonASCII]>; my $atom_char = qq/[^($space)<>\@,;:\".$esc$OpenBR$CloseBR$ctrl$NonASCII]/; my $atom = qq<$atom_char+(?!$atom_char)>; my $quoted_str = qq<\"$qtext*(?:$quoted_pair$qtext*)*\">; my $word = qq<(?:$atom|$quoted_str)>; my $domain_ref = $atom; my $domain_lit = qq<$OpenBR(?:$dtext|$quoted_pair)*$CloseBR>; my $sub_domain = qq<(?:$domain_ref|$domain_lit)>; my $domain = qq<$sub_domain(?:$Period$sub_domain)*>; my $local_part = qq<$word(?:$Period$word)*>; my $addr_spec = qq<$local_part\@$domain>; my $mail_regex = $addr_spec; return 1 if($email =~ /^$mail_regex$/o); return 0; } #=============================================== # 暗号化関係 #=============================================== my $salt = ".b"; sub crypt { my ($str) = @_; my $ostr = crypt($str,$salt); $ostr =~ s/[&+?=]/@/g; return $ostr; } sub IsAllowedIPAddress { my ($IPAddress, @allowed) = @_; foreach my $exp (@allowed) { return 1 if($IPAddress =~ /$exp/i); } return 0; } #========================================== # require "mycgi.pl"; # print &mycgi'InitHTML('Welcome to our HP'); #========================================== sub PrintHTMLHeader { my($CharSet) = (@_); if($CharSet eq '') { $CharSet = 'x-sjis'; } print "Content-type: text/html; charset=$CharSet\n\n"; } sub InitHTML { my($WebTitle, $CharSet, $LinkTarget) = (@_); if($WebTitle eq ''){ $WebTitle = "No title"; } if($CharSet eq '') { $CharSet = 'x-sjis'; } if($LinkTarget eq '') { $LinkTarget = '_blank'; } &PrintHTMLHeader($CharSet); print "\n"; print "\n"; print "\n"; print " \n"; print " $WebTitle\n"; print " \n"; print "\n"; print "\n"; } sub EndHTML { print "\n"; print "\n"; } sub GetHTMLParagraph { my ($str) = (@_); $str =~ /^([\w\W\n]*?)(

)([\w\W]*)$/mi; my $line = $1; my $paragraph = $2; my $len = length($line) + length($paragraph); my $content = substr($str, $len); # print "strlen: " . length($str) . " " . $len . " " . length($content) . "\n"; # print "str1: ". substr($str, 0, 200) . "\n"; # print "line1: $line\n"; # print "para1: $paragraph\n"; # my $cont1 = substr($content, 0, 200); # print "cont1: $cont1\n"; return ($line, $paragraph, $content); } sub DequoteXML { my ($str,$DoDecode) = (@_); $str =~ s/<[\w\W]*?>//gmi; $str =~ s/\n//gm; if($DoDecode) { $str =~ s/"/\"/gmi; # $str =~ s/</\/gmi; $str =~ s/&nbps;/ /gmi; } return $_[0] = $str; } sub GetIPAddress { my($ip) = (@_); $ip = $ENV{'REMOTE_ADDR'}; return $ip; } sub IsJapanese { my($str) = (@_); Jcode::convert(\$str, 'euc'); if($str =~ /[\x8E\xA1-\xFE]/) { return 1; } return 0; } #========================================== # Decode / Encode #========================================== sub MySQLQuote { my($str,$mysqlcharcode) = (@_); #print "s: $str
\n"; Jcode::convert(\$str, $mysqlcharcode) if($mysqlcharcode ne ''); $str =~ s/\\/\\\\/g; # \ ## $str =~ s/\c[/\\\c[/g; # ESC # $str =~ s/\//\\\//g; # \ $str =~ s/\"/\\\"/g; # $str =~ s/\'/\\\'/g; # $str =~ s/\:/\\\:/g; # $str =~ s/\(/\\\(/g; # $str =~ s/\)/\\\)/g; ## $str =~ s/\[([^\c[])/\\\[\1/g; # $str =~ s/\[/\\\[/g; ## $str =~ s/\]/\\\]/g; #print "s: $str
\n"; return $str; } sub URLEncode { my ($s) = (@_); $s =~ s/([^\w ])/'%' . unpack('H2', $1)/eg; $s =~ tr/ /+/; return $s; } sub URLDecode { my ($s2) = (@_); #print "s0: $s2
\n"; $s2 =~ tr/+/ /; $s2 =~ s/%([0-9A-Fa-f][0-9A-Fa-f])/pack('H2', $1)/eg; #print "s1: $s2
\n"; return $s2; } #16進コード sub StrToHex { my ($s) = @_; $s =~ s/(.)/'\\x' . uc unpack('H2', $1)/eg; return $s; } sub RecoverHTMLChar { my ($s, $charset) = @_; $s =~ s/&#([0-9]+);/pack('I', $1)/eg; Jcode::convert(\$s, $charset) if($charset ne ''); return $s; } sub StringToHex { my ($s) = @_; $s = '='.unpack("H2",$s); tr/a-f/A-F/; return $s; } sub QPEncode { my ($string) = (@_); $string =~ s/=/=3D/g; $string =~ s/\t$/=09/; $string =~ s/ $/=20/; $string =~ s/([^!-" \t])/&StringToHex($1)/eg; return $string; } sub QPDecode { my ($string) = (@_); $string =~ s/=\r\n//g; $string =~ s/=\n//g; $string =~ s/=\r//g; $string =~ s/=([0-9a-z]{2})/pack("C",hex($1))/gei; return $string; } my $Base64Alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'. 'abcdefghijklmnopqrstuvwxyz'. '0123456789+/'; # and '=' my $Base64Pad = '='; # b64decodesub -- takes some characters in the base64 alphabet and # returns the raw bytes that they represent. sub Base64DecodeSub { local ($_) = @_[0]; # translate each char to a value in the range 0 to 63 eval qq{ tr!$Base64Alphabet!\0-\77!; }; # keep 6 bits out of every 8, and pack them together $_ = unpack('B*', $_); # look at the bits s/(..)(......)/$2/g; # keep 6 bits of every 8 s/((........)*)(.*)/$1/; # throw away spare bits (not multiple of 8) $_ = pack('B*', $_); # turn the bits back into bytes $_; # return } sub Base64Decode2 { my ($str) = (@_); my $leftover = ''; # ignore illegal characters $str =~ s/[^$Base64Alphabet]//go; # insert the leftover stuff from last time $str = $leftover . $str; # if there are not a multiple of 4 bytes, keep the leftovers for later $str =~ m/^((....)*)/; $str = $&; $leftover = $'; # turn each group of 4 values into 3 bytes $str =~ s/(....)/&Base64DecodeSub($1)/eg; # special processing at EOF for last few bytes if (eof) { $str .= &Base64DecodeSub($leftover); $leftover = ''; } # output it return $str; } sub Base64Decode { return decode_base64($_[0]); } sub Base64Encode { return encode_base64($_[0]); } #========================================== # Directory #========================================== my $DirectorySeparator = "\\"; sub CopyFile { my ($infile, $outfile) = (@_); open(IN, "<$infile") or return -1; open(OUT, ">$outfile") or return -2; my @content = ; print OUT @content; close(OUT); close(IN); } sub DelSpace { my ($s) = @_; $s =~ s/^\s*//; $s =~ s/\s*$//; return $_[0] = $s; } sub DelQuote { my ($s) = @_; chomp($s); $s =~ s/^\s*//; $s =~ /^(.)(.*)(.)$/; my $firstchar = $1; my $restchar = $2; my $lastchar = $3; if($firstchar eq '"' and $lastchar eq '"') { return $restchar } return $restchar if($firstchar eq '\'' and $lastchar eq '\''); return $_[0]; } #========================================== # require "mycgi.pl"; # # &mycgi'PrintWithReplaced($infile, $outfile, "{EMail}", $a, "{Code}", $b); # ex. $infile = '-', 'a.in', $outfile="> a.out", ">> a.append", ">-" #========================================== sub PrintWithReplaced { my $narg = @_; my @a = @_; my $infile = $a[0]; my $outfile = $a[1]; my($org,$target); #print "narg: $narg : infile: $infile
\n"; open(INFILE, $infile) or die "$infile: $!"; open(OUTFILE, $outfile) or die "$outfile: $!"; my($line); while(defined($line = )){ for(my $i = 2 ; $i < $narg ; $i += 2){ if($Debug) { print "change($i):
\n"; # [" . $a[$i] . "] to [" . $a[$i+1] . "]
\n"; } $line =~ s/$a[$i]/$a[$i+1]/g; } print OUTFILE $line; } close(INFILE); close(OUTFILE); } #========================================== # require "mycgi.pl"; # # &mycgi'PrintStringWithReplaced($str, $outfile, "{EMail}", $a, "{Code}", $b); # ex. $infile = '-', 'a.in', $outfile="> a.out", ">> a.append", ">-" #========================================== sub PrintStringWithReplaced { my $narg = @_; my @a = @_; my $str = $a[0]; my $outfile = $a[1]; my($org,$target); open(OUTFILE, $outfile) or die "$outfile: $!"; for(my $i = 2 ; $i < $narg ; $i += 2){ $str =~ s/$a[$i]/$a[$i+1]/g; } print OUTFILE $str; close(OUTFILE); } #========================================== # &mycgi'ConvertString($str, "{EMail}", $a, "{Code}", $b); #========================================== sub ConvertString { my $narg = @_; my @a = @_; my $str = $a[0]; for(my $i = 1 ; $i < $narg ; $i += 2){ $str =~ s/$a[$i]/$a[$i+1]/g; } return $_[0] = $str; } sub IsValidPassword { my ($password) = (@_); if($password =~ /^[a-zA-Z0-9_]+$/){ return 1; } return 0; } sub IsValidEMailAddress { my ($email) = (@_); if($email =~ /^[a-zA-Z0-9._\-+\%\$#!&~]+@[a-zA-Z0-9._\-+]+$/){ return 1; } return 0; } sub BuildDateString { my ($time) = (@_); my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime($time); $year += 1900; $mon++; my $str = sprintf("%02d/%02d/%02d %02d:%02d:%02d", $year, $mon, $mday, $hour, $min, $sec); return $str; } sub GetFileSize { my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size, $atime,$mtime,$ctime,$blksize,$blocks) = stat($_[0]); return $size; } sub GetWriteDate { my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size, $atime,$mtime,$ctime,$blksize,$blocks) = stat($_[0]); return $mtime; } #========================================== # DB subroutines #========================================== sub OpenDB { my ($DBServer, $DBUser, $DBPassword, $DBName) = @_; my $db; my $sth; $db = DBI->connect('DBI:mysql:'.$DBName.':'.$DBServer, $DBUser, $DBPassword); if(!$db){ print "Unable to connect to $DBName
\n"; return 0; } $sth = $db->prepare("use $DBName;\n"); my $result = $sth->execute; if(!$result){ print "use: SQL execution error
\n"; return 0; } #print "db:$db $sth
\n"; return ($db,$sth); } sub CloseDB { my ($db, $sth) = @_; $sth->finish; $db->disconnect; } sub DBExecute { my ($db, $sth, $command) = @_; $sth = $db->prepare($command); my $ret = $sth->execute; return ($sth,$ret); } #=============================================== # HTML / Cookie関係 #=============================================== my %COOKIE; my $CGIFiles = "(\.cgi|\.pl|\.php)[^/]*\$"; my @IndexFiles = ("index.html", "index.htm", "Index.html", "Index.htm", "Default.htm", "Default.html", "default.htm", "default.html"); # # Cookieの値を読み出す # sub getCookie { my($xx, $name, $value); foreach my $xx (split(/; */, $ENV{'HTTP_COOKIE'})) { ($name, $value) = split(/=/, $xx); $value =~ s/%([0-9A-Fa-f][0-9A-Fa-f])/pack("C", hex($1))/eg; $COOKIE{$name} = $value; } } # # Cookieに値を書き込むためのSet-Cookie:ヘッダを生成する # sub setCookie { my($tmp, $val); $val = $_[1]; $val =~ s/(\W)/sprintf("%%%02X", unpack("C", $1))/eg; $tmp = "Set-Cookie: "; $tmp .= "$_[0]=$val; "; $tmp .= "expires=Tue, 1-Jan-2030 00:00:00 GMT;"; return($tmp); } # # Cookieを削除するためのSet-Cookie:ヘッダを生成する # sub clearCookie { my $tmp = "Set-Cookie: "; $tmp .= "$_[0]=xx; "; $tmp .= " expires=Tue, 1-Jan-1980 00:00:00 GMT;"; return($tmp); } sub ConvertHTMLToFullURL { my ($Content, $SourceURL, $Debug) = (@_); my $res; my $ConvContent; $res = $Content; $ConvContent = ""; while(1) { my $count = ($res =~ /^(.*?)(\)(.*?)(\<\/a.*?\>)(.*)$/si); if($count == 0) { $ConvContent .= $res; last; } my $header = $1; my $tag1 = $2; my $linkurl = $3; my $tag2 = $4; my $linkstr = $5; my $tag3 = $6; $res = $7; if($Debug) { print " URL: $linkurl\n"; } my $convurl = &ConvertURLtoFullURL($linkurl, $SourceURL); if($Debug) { print "ConvURL: $convurl\n"; } $ConvContent .= "$1$2$convurl$4$5$6"; } $res = $ConvContent; $ConvContent = ""; while(1) { my $count = ($res =~ /^(.*?(background|image|src)\s*=\s*\")(.*?)(\".*)$/si); if($count == 0) { $ConvContent .= $res; last; } my $header = $1; my $linkurl = $3; $res = $4; if($Debug) { print " URL: $linkurl\n"; } my $convurl = &ConvertURLtoFullURL($linkurl, $SourceURL); if($Debug) { print "ConvURL: $convurl\n"; } $ConvContent .= "$1$convurl"; } return $_[0] = $ConvContent;; } sub ConvertURLtoFullURL { my ($linkurl, $url) = (@_); my $convurl; return $linkurl if($linkurl =~ /:\/\//i); my $protocol; my $server; my $directory; my $filename; # $url =~ /^(.*?:\/\/)([^\/]+?)([^\?\&]*?)([^\/]*?)$/i; $url =~ /^(.*?:\/\/)([^\/]+?)(\/|$)(.*?)([^\/]*?)$/i; $protocol = $1; $server = $2; $directory = "/$4"; $filename = $5; if($directory =~ /[\?\&]/) { $directory =~ /^(.*?)([\?\&].*$)/; $directory = $1; my $res1 = $2; $directory =~ /^(.*)\/([^\/]*?)$/; $directory = $1; my $res2 = $2; $filename = "$res2$res1$filename"; } #print "URL : $url\n"; #print "pro : $protocol\n"; #print "server: $server\n"; #print "dir : $directory\n"; #print "file : $filename\n"; my $path; if($linkurl =~ /^\//) { $path = Utils::MakePath($server, $linkurl, "/", 0); } else { $path = Utils::MakePath($server, $directory, "/", 0); $path = Utils::MakePath($path, $linkurl, "/", 0); &ReduceDirectory($path); } #print "path: $path\n"; $convurl = "$protocol$path"; return $convurl; } sub GetURLwithoutFilePath { my ($url) = @_; my $ret; #CGIの場合はそのままreturn return 1 if($url =~ /$CGIFiles/i or $url =~ /[\?\&]/); for(my $i = 0 ; $i < @IndexFiles ; $i++) { my $s = Utils::MakePath($url, $IndexFiles[$i], "/", 0); #print "url: $s\n"; $ret = head($s); # $ret = get($s); if($ret) { $_[0] = $s; return $ret; } } return $ret; } sub DownloadFromURL { my ($url) = @_; my $Content; my $agent = LWP::UserAgent->new; my $newagent = 'Mozilla/4.7 [en] (PalmOS)'; $agent->agent($newagent); my $jar = $agent->cookie_jar(new HTTP::Cookies); my $request = HTTP::Request->new(GET => $url); my $response = $agent->request($request); unless($response->is_success) { my $s = $response->message; print "Error: $s!
\n"; return -1; } $Content = $response->content; &ConvertHTMLToFullURL($Content, $url, 0); return $Content; } sub ExtractHTMLBody { my ($Content) = @_; $Content =~ /\(.*)\<\/body\>/si; return $1; } #========================================== # 「Ultimate Perl」、ソシム発行 #========================================== sub ReadFile { my $fname = @_; open(FILE, "<$fname") or return -1; my $str = do { local $/; ; }; close(FILE); return $str; } #12文字ごとにファイルを読み込み、" "で区切って返す sub ReadFixedColumnFile { my $fname = @_; open(FILE, "<$fname") or return -1; local $/ = \12; local $\ = "\n"; my $str = ""; while() { $str .= " $_"; } close(FILE); return $str; } #リストをタブ区切りで出力 sub PrintWithTab1 { my @list = @_; local ($") = "\t"; print "@list\n"; } sub PrintWithTab1 { my @list = @_; local ($,) = "\t"; print @list . "\n"; } #文字列を固定長で区切る sub SplitToFixedStrs { my $s = @_; my @list; $s =~ s/(.{1,8})/push(@list,$1)/eg; return @list; } #括弧で囲まれた部分をきちんと抽出 sub ExtractByParentheses { my $str = @_; my $balance; $balance = qr/\([^()]*(?:(??{$balance})[^()]*)*\)/; my $ret = ""; while($str =~ /($balance)/g) { $ret .= "$1\n"; } return $ret; } #クレジットカードの番号をチェック sub CheckCreditCardNumber { $_ = shift @_; s/[ -]//g && split //; return "Wrong number" if(/\D/ || (length) |~ /^1[356]$/); my $x; map { $x = 0; map { $x += $_ } split //, $_[$_]*2; $_[$_] = $x; } map { $_%2 ?() : $_; } (length)%2..(length)-1; $x = 0; map { $x += $_ } @_; return $x % 10 ? "Wrong nubmer" : "Correct number"; } #タグの外側だけを置換 sub ReplaceHTMLBodyOnly { my ($str, $source, $target) = @_; $str =~ s/((?:\G|>)[^<]*?)$source/$1$target/g; return $str; } #OSの判定 sub GetOSName { reuturn $^O; } #Configの表示 sub PrintConfig { use Config; for my $key (keys(%Config)) { print "$key : $Config{$key}\n"; } } #コマンドをサブルーチンでつかう #sub AUTOLOAD #{ # my $program = $AUTOLOAD; ##パッケージ名をはずす # $program =~ s/.*:://; # qx/$program @_/; #} #関数のオーバーライド #use subs qw(lc uc); など #データ中のHTMLタグを無力化 sub InvalidateHTMLTags { my ($input) = @_; $input =~ s/&/&/g; $input =~ s//>/g; $input =~ s/"/"/g; $input =~ s/'/'/g; return $input; } #URLから危険な要素を排除 sub GetSafeURL { my $url = @_; return '' if($url =~ m|[^;/?:@&=+\$,A-Za-z0-9\-_.!~*'()%]|); if($url =~ /^([A-Za-z][A-Za-z0-9+\-.]*):/) { my $scheme = lc($1); my $allowed = 0; $allowed = 1 if($scheme eq 'http'); $allowed = 1 if($scheme eq 'https'); $allowed = 1 if($scheme eq 'mailto'); return '' if(not $allowed); } $url =~ s/&/&/g; $url =~ s/'/'/g; return $url; } #ファイル名のチェック(ヌル文字がある場合、ディレクトリィトラバーサルがある場合は0 sub CheckSecureFileName { my $fname = @_; return 0 if($fname =~ <\.\./>); return 0 if($fname =~ /\0/); return 1; } #タイムアウトの設定 #alarm(20); #20秒 #SIG{ALRM} = 'time_out'; #sub time_out { # print "Time out\n"; # return; #} 1;