package HTML; use Common; @ISA = qw(Common); #公開したいサブルーチン #@EXPORT = qw(DelSpace Reduce01 MakePath RegExpQuote); use strict; use Jcode; use Deps; sub GetUploadFileContent { my ($App, $pUploadFile, $pAllowTypes, $pAllowExtensions) = @_; my $path = $$pUploadFile; $path = Utils::ConvertDirectorySeparator($path, '\\', '/', 0); my $form = $App->CGIForm(); #ファイルが転送されていなかったら、$$pUploadFile は 未定義値となっている #フォーム上でファイルを選択しない場合は、$$pUploadFile は空文字列 if(!defined $$pUploadFile){ my $error = $form->cgi_error; $App->print("Error: Can't upload [$path]: $error\n"); return; } # ファイルが転送されていない場合$UploadFileは偽 if(!$$pUploadFile) { $App->print("Error: [$path] was not be upload.\n"); } #ファイルタイプのチェックをしてからuploadする my $info = $form->uploadInfo($$pUploadFile); #print "info: $info
\n"; my $type = $info->{'Content-Type'}; #print "type: $type
\n"; my $IsAllowed = 0; if(defined $pAllowTypes and @$pAllowTypes > 0) { for(my $i = 0 ; $i < @$pAllowTypes ; $i++) { my $s = $pAllowTypes->[$i]; if($type =~ /$s/i) { $IsAllowed = 1; last; } } if(!$IsAllowed) { $App->print("Error: Type [$type] is not allowed for upload.\n"); return undef; } } $IsAllowed = 0; if(defined $pAllowExtensions and @$pAllowExtensions > 0) { for(my $i = 0 ; $i < @$pAllowExtensions ; $i++) { my $s = $pAllowExtensions->[$i]; if($path =~ /\.$s$/i) { $IsAllowed = 1; last; } } if(!$IsAllowed) { $App->print("Error: Extension of [$path] is not allowed for upload.\n"); return undef; } } # $$pUploadFile から内容を読み出して保存用ファイルに書き出す #この場合、変数 $$pUploadFile はファイルハンドルとして機能する my $content = ''; my $buffer; while (read($$pUploadFile,$buffer,1024)) { $content .= $buffer; } return $content; } sub DownloadFile { my ($App, $path, $filename) = @_; my $form = $App->CGIForm(); my $in = new JFile(); my $Contents = $in->ReadFile($path, "", "rb"); if(!defined $Contents) { $App->H2("Error: Can not read [$path]"); return; } my $FileURL = $filename; my $Length = length $Contents; #print "
length: $Length
"; #ファイル用のヘッダを書き出し #$FileURL はアスキー文字で構成されている必要がある。 #日本語が含まれているとうまくいかない可能性が高い #ブラウザのバージョンや設定によって、期待した動作とならない場合もある print ( $form->header( -Content_Disposition => "attachment; filename=$filename", -Content_Length => $Length, -type => "application/octet-stream", ) ); print($Contents); return 1; } sub ShowURL { my ($URL, $Second, $Target, $CharSet) = @_; $Second = 0 if($Second <= 0); $Target = '_self' if($Target eq ''); $CharSet = 'x-sjis' if($CharSet eq ''); print < Forwarded to $URL

Fowarded to $URL in $Second seconds

EOT1 return 1; } sub GetIPAddress { return $ENV{'REMOTE_ADDR'}; } 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; } 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; } 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]; local ($_) = @_; # 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]); } 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, $CSS) = (@_); 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"; if(defined $CSS and $CSS ne '') { print " \n"; print " \n"; print " \n"; } else { print " \n"; } print " $WebTitle\n"; print " \n"; print "\n"; print "\n"; } sub EndHTML { print "\n"; print "\n"; } sub RecoverHTMLChar { my ($s, $charset) = @_; $s =~ s/&#([0-9]+);/pack('I', $1)/eg; Jcode::convert(\$s, $charset) if($charset ne ''); return $s; } sub ConvertHTMLSpecialCharacters { my ($s, $ConvMiddot) = @_; if($ConvMiddot) { $_[0] =~ s/\·\;/×<\/span>/ig; } $_[0] =~ s/\&Ordm\;/o<\/sup>/ig; $_[0] =~ s/ / /g; $_[0] =~ s/&/&/g; $_[0] =~ s/<//g; $_[0] =~ s/%20/ /g; return $_[0]; } sub ConvertHTMLSpecialCharactersMinimum { my ($s, $ConvMiddot) = @_; if($ConvMiddot) { $_[0] =~ s/\·\;/×<\/span>/ig; } $_[0] =~ s/\&Ordm\;/o<\/sup>/ig; $_[0] =~ s/%20/ /g; return $_[0]; } sub ConvertToHTMLString { my ($s) = @_; $s =~ s/\r\n/\n/g; $s =~ s/\n\r/\n/g; $s =~ s/\\n/\n/gi; $s =~ s/&/&/g; $s =~ s//>/g; $s =~ s/"/"/g; $s =~ s/'/'/g; $s =~ s/\n/
\n/g; $s =~ s/ /  /g; return $s; } 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); 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/&nbps;/ /gmi; } return $_[0] = $str; } #=============================================== # 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); } # Cookieの値を読み出す # sub MyGetCookie { #print "Env: ", $ENV{'HTTP_COOKIE'}, "
\n"; foreach my $xx (split(/; */, $ENV{'HTTP_COOKIE'})) { #print "xx: $xx
\n"; my ($name, $value) = split(/=/, $xx); $value =~ s/%([0-9A-Fa-f][0-9A-Fa-f])/pack("C", hex($1))/eg; $COOKIE{$name} = $value if $COOKIE{$name} eq ''; #print "Name: $name, ", $COOKIE{$name}, "
\n"; } } 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 = &MakePath($server, $linkurl, "/", 0); } else { $path = &MakePath($server, $directory, "/", 0); $path = &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 = &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; } #タグの外側だけを置換 sub ReplaceHTMLBodyOnly { my ($str, $source, $target) = @_; $str =~ s/((?:\G|>)[^<]*?)$source/$1$target/g; return $str; } #データ中のHTMLタグを無力化 sub InvalidateHTMLTags { my ($input, $DoUpdate) = @_; $DoUpdate = 1 if(!defined $DoUpdate); $input =~ s/&/&/g; $input =~ s//>/g; $input =~ s/"/"/g; $input =~ s/'/'/g; $_[0] = $input if($DoUpdate); 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; } 1;