#============================================================
# Utils
#============================================================
package Utils;
use Common;
@ISA = qw(Common);
#公開したいサブルーチン
#@EXPORT = qw(DelSpace Reduce01 MakePath MakePath2 RegExpQuote);
use strict;
use Digest::MD5 qw(md5_base64);
use Digest::SHA1 qw(sha1_base64);
use Jcode;
use Cwd;
use File::Find;
use HTTP::Request::Common;
use HTTP::Cookies;
use MIME::Base64;
use Hash::Util qw(lock_keys unlock_keys);
eval('use Crypt::RC4;');
use Time::Local;
#eval('use Email::Valid;');
use File::Copy;# (copy, move);
use File::Copy::Recursive qw(fcopy rcopy dircopy);
use Deps;
use JFile;
my @LeapYear = (0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
sub LeapYear { return @LeapYear; }
my @NormYear = (0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
sub NormYear { return @NormYear; }
#===============================================
# デバッグ関係変数
#===============================================
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();
sub IsCGI
{
my $method = $ENV{'REQUEST_METHOD'};
return 0 if(!defined $method);
return 1 if(uc $method eq 'POST' or uc $method eq 'GET');
return 0;
}
sub IsWindows
{
return 1 if($OS =~ /MSWin/i);
return 0;
}
sub IsLinux
{
return 1 if($OS =~ /Linux/i);
return 0;
}
sub IsUnix
{
return 1 if($OS =~ /Unix/i);
return 0;
}
sub sleep
{
my ($sec) = @_;
select(undef, undef, undef, $sec);
}
sub GetIPAddress
{
return $ENV{'REMOTE_ADDR'};
}
sub IsAllowedIPAddress
{
my ($IPAddress, @allowed) = @_;
foreach my $exp (@allowed) {
return 1 if($IPAddress =~ /$exp/i);
}
return 0;
}
sub Round
{
my ($v, $dec, $RaiseDecimal) = @_;
$dec = 4 unless($dec);
return 0.0 if(abs($v) < 1.0e-100);
my $k = 1.0;
my $av = abs($v);
my $i = 0;
while($av < 10) {
$av *= 10;
$k *= 10;
$i++;
last if($i > 20);
}
while(1 <= $av) {
$av *= 0.1;
$k *= 0.1;
}
#print "av=$av v=$v k=$k\n";
$v = $v * $k;
if($RaiseDecimal) {
my $coef = 1.0;
for(my $i = 0 ; $i < $dec ; $i++) {
$coef *= 0.1;
}
$RaiseDecimal -= $coef;
#print "v1=$v RD: $RaiseDecimal\n";
$v += $RaiseDecimal * $coef if($v > 0.0);
$v -= $RaiseDecimal * $coef if($v < 0.0);
#print "v2=$v\n";
}
if($v =~ /^[-+]/) {
$v = substr($v, 0, $dec+3);
}
else {
$v = substr($v, 0, $dec+2);
}
$v = $v / $k;
#print "v3=$v\n";
return $v;
}
sub RoundParameter
{
my ($x, $tol) = @_;
return $tol * int( ($x+0.1*$tol) / $tol );
}
sub ExtractUniqueElement
{
my ($pArray, $Sort) = @_;
my %hash;
foreach my $s (@$pArray) {
$hash{$s}++;
}
return sort keys %hash if($Sort);
return keys %hash;
}
sub IsIncludedInArray
{
my ($key, $pArray, $CaseSensitive) = @_;
$CaseSensitive = 0 if(!defined $CaseSensitive);
$key = uc $key if(!$CaseSensitive);
for(my $i = 0 ; $i < @$pArray ; $i++) {
if($CaseSensitive) {
return 1 if($pArray->[$i] eq $key);
}
else {
return 1 if(uc $pArray->[$i] eq $key);
}
}
return 0;
}
sub RemoveSpaceElement
{
my @array;
for(my $i = 0 ; $i < @_ ; $i++) {
my $s = $_[$i];
DelSpace($s);
push(@array, $_[$i]) if($s ne '');
}
return @array;
}
sub LockHashKeys
{
my ($pHash, $f) = @_;
$f = 1 if(!defined $f);
return lock_keys(%$pHash) if($f);
return unlock_keys(%$pHash);
}
sub MergeHashByCondition
{
my ($pTarget, $pHash, $NotExistOnly) = @_;
return $pTarget if($pTarget == $pHash);
$NotExistOnly = 1 if(!defined $NotExistOnly);
foreach my $key (keys %$pHash) {
if(!$NotExistOnly or !defined $pTarget->{$key}) {
$pTarget->{$key} = $pHash->{$key};
}
}
return $pTarget;
}
sub MergeHash
{
my (@pHash) = @_;
return $pHash[0] if(@pHash == 2 and $pHash[0] == $pHash[1]);
#print "h=", join(', ', @pHash, "\n");
my $ph0 = $pHash[0];
for(my $i = 1 ; $i < @pHash ; $i++) {
my $ph = $pHash[$i];
next if(!defined $ph);
foreach my $key (keys %$ph) {
$ph0->{$key} = $ph->{$key};
}
}
return $ph0;
}
sub RevertHash
{
my ($pHash) = @_;
my %NewHash;
foreach my $k (keys %$pHash) {
my $s = $pHash->{$k};
$NewHash{$s} = $k;
}
return %NewHash;
}
sub BuildHashFromHashArray
{
my ($pList, $pHash, $key) = @_;
return {} if(!$pList);
$pHash = {} if(!$pHash);
for(my $i = 0 ; $i < @$pList ; $i++) {
my $pi = $pList->[$i];
my $k = $pi->{$key};
$pHash->{$k} = $pi;
}
return $pHash;
}
sub MergeListHash
{
my ($App, @list) = @_;
my %hash;
my @List;
for(my $i = 0 ; $i < @list ; $i += 2) {
my $var = $list[$i];
my $varkey = ($var eq '')? ':blank:' : $var;
my $val = $list[$i+1];
#$App->print("var=[$varkey]\n");
if(!defined $hash{$varkey}) {
@List = (@List, $var, $val);
$hash{$varkey}++;
}
}
return @List;
}
sub MergeList
{
my (@list) = @_;
my %hash;
my @List;
for(my $i = 0 ; $i < @list ; $i++) {
if(!$hash{$list[$i]}) {
@List = (@List, $list[$i]);
$hash{$list[$i]}++;
}
}
return @List;
}
sub DeleteItemFromList
{
my ($plist, $pdeletelist) = @_;
my @List;
my %Registered;
for(my $i = 0 ; $i < @$plist ; $i++) {
my $key = $plist->[$i];
my $Delete = 0;
for(my $j = 0 ; $j < @$pdeletelist ; $j++) {
if($key eq $pdeletelist->[$j]) {
$Delete = 1;
last;
}
}
if(!$Delete and !defined $Registered{$key}) {
@List = (@List, $key);
$Registered{$key}++;
}
}
return @List;
}
sub ListToHash
{
my ($plist, $phash) = @_;
for(my $i = 0 ; $i < @$plist ; $i += 2) {
$phash->{$plist->[$i]} = $plist->[$i+1];
}
}
sub Split
{
my ($RegExp, $str, $RemoveBlank) = @_;
$RemoveBlank = 1 if(!defined $RemoveBlank);
my @a = split(/$RegExp/, $str);
@a = Utils::RemoveSpaceElement(@a) if($RemoveBlank);
return @a;
}
sub FindAll
{
my ($RegExp, $str) = @_;
my (@a, $found, $rest);
while(1) {
$rest = "";
($found, $rest) = ($str =~ /($RegExp)(.*)$/);
#print "f=$found, $rest [$str]\n";
push(@a, $found);
last if($rest eq '');
$str = $rest;
}
return Utils::RemoveSpaceElement(@a);
}
sub MergeName
{
my ($FirstName, $LastName) = @_;
return $FirstName if($LastName eq '');
return $LastName if($FirstName eq '');
my $Name;
if($LastName =~ /^[a-zA-Z\s\.\,\/\(\)]*$/ and $FirstName =~ /^[a-zA-Z\s\.\,\/\(\)]*$/) {
$Name = "$FirstName $LastName";
}
else {
$Name = "$LastName $FirstName";
}
Utils::DelSpace($Name);
return $Name;
}
sub SplitName
{
my ($Name) = @_;
&DelSpace($Name);
return ('', '') if($Name eq '');
my ($FirstName, $LastName);
my $code = Jcode::getcode($Name);
#print "code: $code
\n";
# if($Name =~ /^[a-zA-Z\s\.,\-+\~\/\(\)\*:]+$/) {
if($code =~ /ascii/i) {
# my @a = Utils::Split("\\s+", $Name);
if($Name =~ /,/) {
$Name =~ /^([\w\-\']+)[\s,]+(.*)\s*$/;
$FirstName = $2;
$LastName = $1;
}
elsif($Name =~ /^(.+)\s+([\w\-\']+)\s*$/) {
$FirstName = $1;
$LastName = $2;
}
elsif($Name =~ /^(.+)\s+(\S+)\s*$/) {
$FirstName = $1;
$LastName = $2;
}
else {
$FirstName = '';
$LastName = $Name;
}
}
else {
# my ($a, $b) = Utils::Split("\\s+", $Name);
# if($Name =~ /^([\w\.]+?)[\s,]+(.*)$/) {
if($Name =~ /^([\S]+?)[\s,]+(.*)$/) {
$FirstName = $2;
$LastName = $1;
}
else {
$FirstName = '';
$LastName = $Name;
}
}
Utils::DelSpace($FirstName);
Utils::DelSpace($LastName);
if($FirstName eq '' and $Name =~ /\./) {
$Name =~ /^(.*\.)\s*(.*?)$/;
$FirstName = $1;
$LastName = $2;
Utils::DelSpace($FirstName);
Utils::DelSpace($LastName);
}
return ($FirstName, $LastName);
}
sub Sort
{
return ($_[1], $_[0]) if($_[0] > $_[1]);
return ($_[0], $_[1]);
}
sub Swap
{
return ($_[1], $_[0]);
}
sub DelSpace($)
{
my ($s) = @_;
return $s unless(defined $s);
$s =~ s/[\r\n\s]+$//;
$s =~ s/^[\r\n\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 $_[0] = $restchar
}
if($firstchar eq '\'' and $lastchar eq '\'') {
return $_[0] = $restchar
}
return $restchar
if($firstchar eq '\'' and $lastchar eq '\'');
return $_[0];
}
sub Reduce01($)
{
my ($x) = @_;
while($x < 0.0) {
$x += 1.0;
}
while($x >= 1.0) {
$x -= 1.0;
}
return $x;
}
sub CalMinMax
{
my ($pArray, $CompareAbsoluteValue) = @_;
$CompareAbsoluteValue = 0 if(!defined $CompareAbsoluteValue);
my ($min, $max) = (1.0e99, -1.0e99);
if($CompareAbsoluteValue) {
for(my $i = 0 ; $i < @$pArray ; $i++) {
my $v = abs($pArray->[$i]);
$min = $v if($min > $v);
$max = $v if($max < $v);
}
}
else {
for(my $i = 0 ; $i < @$pArray ; $i++) {
my $v = $pArray->[$i];
$min = $v if($min > $v);
$max = $v if($max < $v);
}
}
return ($min, $max);
}
sub CalMinMaxStep
{
my ($pArray) = @_;
my $nData = @$pArray;
return 0.0 if($nData <= 1);
my ($min, $max) = (1.0e99, -1.0e99);
for(my $i = 0 ; $i < $nData -1 ; $i++) {
my $v = abs($pArray->[$i+1] - $pArray->[$i]);
$min = $v if($min > $v);
$max = $v if($max < $v);
}
return ($min, $max);
}
sub IsDecreasingArray
{
my ($pArray) = @_;
my $n = @$pArray;
for(my $i = 0 ; $i < $n-1 ; $i++) {
return 0 if($pArray->[$i] < $pArray->[$i+1]);
}
return 1;
}
sub IsIncreasingArray
{
my ($pArray) = @_;
my $n = @$pArray;
for(my $i = 0 ; $i < $n-1 ; $i++) {
return 0 if($pArray->[$i] > $pArray->[$i+1]);
}
return 1;
}
sub IsConstantStepArray
{
my ($pArray, $EPS) = @_;
$EPS = 1.0e-6 if(!defined $EPS);
return 1 if(@$pArray <= 2);
my $dX0 = $pArray->[1] - $pArray->[0];
return 0 if($dX0 == 0.0);
for(my $i = 1 ; $i < @$pArray - 1 ; $i++) {
my $dX = $pArray->[$i+1] - $pArray->[$i];
if(abs(($dX - $dX0) / $dX0) > $EPS) {
return 0;
}
}
return 1;
}
sub RegExpQuote
{
return Deps::RegExpQuote(@_);
}
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, $KeepSlash) = (@_);
$s =~ s/([^\w ])/'%' . unpack('H2', $1)/eg;
$s =~ tr/ /+/;
$s =~ s/%2f/\//g if($KeepSlash);
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;
}
sub ChrToHTMLCode
{
my ($char) = @_;
return sprintf("%03d;", unpack('c', $char));
}
sub HexDecode
{
my ($s2) = (@_);
$s2 =~ s/([0-9A-Fa-f][0-9A-Fa-f])/pack('H2', $1)/eg;
return $s2;
}
sub IntToAlpha
{
my ($i) = @_;
#for(my $i = 0 ; $i < 26 ; $i++) {
#my $a = chr($i + 97);
#my $a = $alphabet[$i];
#print "$i: $a\n";
#}
my $base = 26;
return 'a' if($i == 0);
my $n = int(log($i) / log($base));
my @A;
for(my $nn = $n ; $nn >= 1 ; $nn--) {
my $k = $base**$nn;
$A[$nn] = int($i / $k);
$i = $i - $A[$nn] * $k;
}
$A[0] = $i;
my $s = '';
for(my $i = $n ; $i >= 0 ; $i--) {
#print "$i: A=$A[$i]\n";
if($i > 0) {
$s = $s . chr($A[$i] + 97 - 1);
}
else {
$s = $s . chr($A[$i] + 97);
}
}
#print "s=$s\n";
#exit;
return $s;
}
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 Encode
{
my ($passphrase, $str, $method) = @_;
$method = "RC4:Base64" if(!defined $method);
my $dec;
if($method =~ /RC4/i) {
$dec = RC4($passphrase, $str);
}
else {
$dec = $str;
}
if($method =~ /Base64/i) {
$dec = Utils::Base64Encode($dec);
Utils::DelSpace($dec);
$dec =~ s/=+$//;
}
return $dec;
}
sub Decode
{
my ($passphrase, $str, $method) = @_;
$method = "RC4:Base64" if(!defined $method);
my $enc;
if($method =~ /Base64/i) {
$enc = Utils::Base64Decode($str);
}
else {
$enc = $str;
}
if($method =~ /RC4/i) {
$enc = RC4($passphrase, $enc);
}
return $enc;
}
sub CryptForHTPasswd
{
my ($pw) = @_;
my @salt_set = ('a'..'z','A'..'Z','0'..'9','.','/');
srand();
my $idx1 = int(rand(63));
my $idx2 = int(rand(63));
my $salt = $salt_set[$idx1] . $salt_set[$idx2];
my $encpw =crypt($pw, $salt);
return $encpw;
}
sub Crypt
{
my ($method, $key, @strings) = @_;
if($method =~ /plain/i) {
return $strings[0];
}
elsif($method =~ /md5/i) {
return md5_base64(@strings, $key);
}
elsif($method =~ /sha-?1/i) {
return sha1_base64(@strings, $key);
}
return crypt($strings[0], $key);
}
sub MakePath2
{
my ($dir, $pfnames, $separator, $DoTerminate, $QuotationMode) = @_;
$QuotationMode = '' if(!defined $QuotationMode);
return $dir if(!defined $pfnames or @$pfnames == 0);
my $path = &MakePath($dir, $pfnames->[0], $separator, $DoTerminate);
for(my $i = 1 ; $i < @$pfnames ; $i++) {
$path = &MakePath($path, $pfnames->[$i], $separator, $DoTerminate, "");
}
if($QuotationMode eq 'auto') {
$path = "\"$path\"" if($path =~ /\s/);
}
if($QuotationMode eq 'quote') {
$path = "\"$path\"";
}
return $path;
}
sub MakePath
{
my ($dir, $fname, $separator, $DoTerminate, $QuotationMode) = (@_);
$QuotationMode = '' if(!defined $QuotationMode);
if(ref $fname eq 'ARRAY') {
return &MakePath2($dir, $fname, $separator, $DoTerminate);
}
my $RegSep = &RegExpQuote($separator);
my $IsHeadSep = 0;
#print "[$dir] ($fname) : $RegSep : ";
$fname =~ s/^$RegSep//;
$fname =~ s/$RegSep$//;
#print "($fname)\n";
if($dir =~ /$RegSep$/) {
$dir .= $fname;
}
elsif($dir eq '') {
$dir = $fname;
}
else {
$dir .= $separator . $fname;
}
if($DoTerminate) {
unless($dir =~ /$RegSep$/) {
$dir .= $separator;
}
}
else {
if($dir ne '/' and $dir =~ /$RegSep$/) {
$dir =~ s/$RegSep$//;
}
}
if($QuotationMode eq 'auto') {
$dir = "\"$dir\"" if($dir =~ /\s/);
}
if($QuotationMode eq 'quote') {
$dir = "\"$dir\"";
}
return $dir;
}
sub ConvertDirectorySeparator
{
my ($path, $src, $target, $DoTerminate) = (@_);
Utils::DelSpace($path);
return $_[0] = $path if($path eq '');
$src = &RegExpQuote($src);
my $RegTarget = &RegExpQuote($target);
my $CharCodeConverted = 0;
my $code = Jcode::getcode($path);
if($code ne 'ascii' and $code ne 'euc') {
$CharCodeConverted = 1;
Jcode::convert(\$path, 'euc');
}
$path =~ s/$src/$target/g;
if($DoTerminate) {
unless($path =~ /$RegTarget$/) {
$path = "$path$target";
}
}
else {
if($path =~ /$RegTarget$/) {
$path =~ s/$target$//;
}
}
if($CharCodeConverted) {
Jcode::convert(\$path, $code, 'euc');
}
return $_[0] = $path;
}
sub ReduceDirectory {
my ($dir, $sep, $App) = @_;
#$App->print("dir[$dir]\n") if($App);
$sep = '/' if(!defined $sep);
my $RegSep = &RegExpQuote($sep);
my $code = Jcode::getcode($dir);
my $workcode = 'utf8';
Jcode::convert(\$dir, $workcode, $code) if($code ne '' and $code ne 'ascii');
if($dir eq '.') {
return cwd();
}
#$App->print("dir[$dir]\n") if($App);
my ($drive, $dir0) = ($dir =~ /^([a-zA-Z]:)?(.*)$/);
#$App->print("[$drive][$dir0]\n") if($App);
if($dir0 !~ /^[\\\/]/) {
$dir = Deps::MakePath(cwd(), $dir0);
if($drive ne '') {
$dir = "$drive$dir";
}
}
#$App->print("d[$dir]\n") if($App);
$dir =~ s/[\\\/]/$sep/g;
#$App->print("d[$dir]\n") if($App);
my $IsHeadSep = 0;
my $IsLastSep = 0;
$IsHeadSep = 1 if($dir =~ /^$RegSep/);
$IsLastSep = 1 if($dir =~ /$RegSep$/);
my @d = split(/$RegSep/, $dir);
my @d2;
for(my $i = 0 ; $i < @d ; $i++) {
next if($d[$i] eq '.');
if($d[$i] eq '..') {
pop(@d2);
next;
}
push(@d2, $d[$i]);
}
if($IsHeadSep) {
$dir = $sep;
}
else {
$dir = '';
}
foreach my $dd (@d2) {
if($dir eq '') {
$dir = $dd;
next;
}
next if($dd eq '');
$dir = Utils::MakePath($dir, $dd, $sep, 0);
}
$dir = Utils::MakePath($dir, $sep, $sep, 0) if($IsLastSep);
Jcode::convert(\$dir, $code, $workcode) if($code ne '' and $code ne 'ascii');
return $_[0] = $dir;
}
sub MakeRelativePath
{
my ($SourceURL, $ParentURL, $Separator, $ForceDir) = (@_);
$ForceDir = 0 if(!defined $ForceDir);
if(!defined $Separator or $Separator eq '') {
$Separator = $DirectorySeparator;
if($Separator ne '\\') {
$SourceURL =~ s/\\/$Separator/g;
$ParentURL =~ s/\\/$Separator/g;
}
elsif($Separator ne '/') {
$SourceURL =~ s/\//$Separator/g;
$ParentURL =~ s/\//$Separator/g;
}
}
my $RegSeparator = &RegExpQuote($Separator);
my $IsDir = ($ParentURL =~ /$RegSeparator$/ or -d $ParentURL)? 1 : 0;
$IsDir = 1 if($ForceDir);
my $HeadLevel = 1; #2;
$HeadLevel = 3 if($SourceURL =~ m|://|);
#$Debug=1;
if($Debug) {
print "*IsDir: $IsDir\n";
print "*HeadLevel: $HeadLevel\n";
print "*SourceURL: $SourceURL\n";
print "*ParentURL: $ParentURL\n";
print "*Separator: $Separator\n";
}
my @EachSourceStr = split(/$RegSeparator/, $SourceURL);
my @EachParentStr = split(/$RegSeparator/, $ParentURL);
my $pt = 0;
for(my $i = 0 ; $i < @EachSourceStr ; $i++) {
if($Debug) {
print " es[$i]: ", lc $EachSourceStr[$i], "\n";
print " ep[$i]: ", lc $EachParentStr[$i], "\n";
}
if(lc $EachSourceStr[$i] eq lc $EachParentStr[$i]) {
}
else {
$pt = $i;
last;
}
$pt = $i;
}
if($Debug) {
print "PT: $pt\n";
}
#絶対パスしかない場合
return "" if(($EachSourceStr[0] =~ /^\w:/ and $pt < $HeadLevel) or
($EachSourceStr[0] !~ /^\w:/ and $pt < $HeadLevel-1) );
my $TotalLevel = @EachParentStr - $pt - 1 + $IsDir;
if($Debug) {
print "TotalLevel: $TotalLevel\n";
}
my $RelPath = '';
for(my $i = 0 ; $i < $TotalLevel ; $i++) {
$RelPath = Utils::MakePath($RelPath, "..", $Separator, 0);
}
for(my $i = $pt ; $i < @EachSourceStr ; $i++) {
$RelPath = '.' if($RelPath eq '');
$RelPath = Utils::MakePath($RelPath, $EachSourceStr[$i], $Separator, 0);
}
if($Debug) {
print "*RelPath: $RelPath\n";
}
return $RelPath;
}
# 年、月
# その月の最初の曜日、その月の合計日数
# 基準: (Sun)10/17/1582
sub GetFirstWday
{
my ($yyyy, $mm) = @_;
my ($y, $m, $d);
my ($days, @ydays, $ydays, $wday);
if ($yyyy eq '') {
($yyyy, $mm) = getDate();
}
my ($leap) = 0;
@ydays = Utils::leap($yyyy) ? Utils::LeapYear() : Utils::NormYear();
my $l = Utils::leap($yyyy);
return Utils::getDayOfWeek($yyyy, $mm, 1), $ydays[$mm];
return Utils::getDayOfWeek($yyyy, $mm, 1), Utils::getDaysOfMonth($mm);
}
sub LocalTimeToTime
{
my ($year, $month, $mday, $hour, $min, $sec, $DiffHours, $StartYear) = @_;
$DiffHours = 0 if(!defined $DiffHours);
$StartYear = 1970 if(!defined $StartYear);
my $offset = 0;
# if($hour >= 24) {
# $offset = -$hour * 60 * 60;
# $hour = 0;
# }
my $hour1 = $hour - $DiffHours;
my $reshour = $hour1 % 24;
my $i24 = int($hour1 / 24);
#print "h: $hour, $hour1, $reshour, $i24
\n";
$year = 1970 if($year < 1970);
$month = 1 if($month < 1 or $month > 12);
my ($FirstDayOfMonday, $DaysInMonth) = Utils::GetFirstWday($year, $month);
$mday = 1 if($mday <= 0);
$mday = $DaysInMonth if($mday > $DaysInMonth);
$sec = 0 if($sec <= 0 or $sec > 60);
#print "dif=$DiffHours: $year/$month/$mday $hour:$min:$sec
\n";
my $time;
#print "m: $year/$month/$mday $hour1:$min:$sec\n";
$time = &timelocal($sec, $min, $reshour, $mday, $month-1, $year) + $i24*24*60*60 + $offset; #JST
# eval('$time = &timelocal($sec, $min, $hour1, $mday, $month-1, $year) + $offset'); #JST
return $time;
my $TotalDay = 0;
for(my $y = $StartYear ; $y <= $year - 1 ; $y++) {
my $IsLeapYear = Utils::leap($y);
for(my $m = 1 ; $m <= 12 ; $m++) {
$TotalDay += Utils::getDaysOfMonth($y, $m);
}
#print "$y: $IsLeapYear ($TotalDay)\n" if($y > 1990);
}
for(my $m = 1 ; $m <= $month-1 ; $m++) {
$TotalDay += Utils::getDaysOfMonth($year, $m);
}
$TotalDay += $mday - 1;
my $TotalSec = $TotalDay * 24 * 60 * 60 + $hour1 * 60 * 60 + $min * 60 + $sec;
#print "TotalSec: $TotalSec\n";
return $TotalSec;
}
sub Execute
{
my ($cmd, $IsPrint) = @_;
$IsPrint = 1 if(!defined $IsPrint);
print(" Execute [$cmd]...\n") if($IsPrint);
my $ret = system($cmd);
if($ret and $IsPrint) {
print(" Error: execute [$cmd] failed with ret=$ret\n");
}
return $ret;
}
sub ExecuteWithPipe
{
my ($cmd, $sourcecharcode, $targetcharcode, $LineByLine, $PrintCmdForError, $IsPrint, $App) = @_;
$sourcecharcode = 'sjis' if($sourcecharcode eq '');
$targetcharcode = 'sjis' if($targetcharcode eq '');
$LineByLine = 1 if(!defined $LineByLine);
$PrintCmdForError = 1 if(!defined $PrintCmdForError);
$IsPrint = 1 if(!defined $IsPrint);
print(" Execute [$cmd]...\n") if($IsPrint);
my $ret = open(IN, "$cmd |");
if($ret and $IsPrint) {
print(" Error: execute [$cmd] failed with ret=$ret\n");
return $ret;
}
my $s = '';
my $s0;
while(1) {
my $line = ;
last if(!defined $line);
Utils::DelSpace($line);
next if($line eq '');
if($PrintCmdForError and $line =~ /ERR/i) {
$s0 = "$line [$cmd]\n"
}
else {
$s0 = "$line\n";
}
if($LineByLine) {
Jcode::convert(\$line, $targetcharcode, $sourcecharcode);
if($App) {
$App->print($s0);
}
else {
print($s0);
}
}
else {
if($PrintCmdForError and $line =~ /ERR/i) {
$s .= $s0;
}
else {
$s .= $s0;
}
}
}
close(IN);
if(!$LineByLine) {
Jcode::convert(\$s, $targetcharcode, $sourcecharcode);
if($App) {
$App->print($s);
}
else {
print($s);
}
}
return 0;
}
sub DecomposeMailFrom
{
my ($From) = @_;
$From =~ s/"/\"/g;
$From =~ s/</\/g;
my ($EMail, $Sender) = ('', '');
if($From =~ /<(.*?\@.*?)>/) {
$EMail = $1;
$From =~ s/<(.*?\@.*?)>//;
DelSpace($EMail);
DelSpace($From);
DelQuote($From);
return ($EMail, $From);
}
if($From =~ /\((.*)\)/) {
$Sender = $1;
$From =~ s/\((.*)\)//;
DelSpace($Sender);
DelQuote($Sender);
DelSpace($From);
return ($From, $Sender);
}
DelSpace($From);
DelQuote($From);
return ($From, '');
}
sub MailDateToDateString
{
my ($date) = @_;
#Wed, 27 Aug 2008 07:08:21 +0900
my %MonthName = ("Jan" => 1, "Feb" => 2, "Mar" => 3, "Apr" => 4, "May" => 1, "Jun" => 6,
"Jul" => 7, "Aug" => 8, "Sep" => 9, "Oct" => 10, "Nov" => 11, "Dec" => 12);
my ($wday, $mday, $mon, $year, $hour, $min, $sec, $timediff) = Utils::Split("[\\s:,]+", $date);
return sprintf("%04d/%02d/%02d %02d:%02d:%02d", $year, $MonthName{$mon}, $mday, $hour, $min, $sec);
}
sub GetDateTime
{
my ($time, $UseGengo) = (@_);
$UseGengo = 1 if(!defined $UseGengo);
$time = time() if(!defined $time);
my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime($time);
$year += 1900;
$mon++;
if($UseGengo) {
if(($year == 2019 and $mon >= 5) or $year >= 2020) {
return ($year, $mon, $mday, $hour, $min, $sec, $year-2018, $wday, $yday, $isdst);
}
elsif($year >= 1989) {
return ($year, $mon, $mday, $hour, $min, $sec, $year-1988, $wday, $yday, $isdst);
}
}
return ($year, $mon, $mday, $hour, $min, $sec, $year, $wday, $yday, $isdst);
}
sub GetYear
{
my ($time, $UseGengo) = (@_);
my ($year, $mon, $mday, $hour, $min, $sec, $year2, $wday, $yday, $isdst) = &GetDateTime($time, $UseGengo);
return $year;
}
sub BuildDateString
{
my ($time, $language, $format) = (@_);
my @MonthName = ("Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec");
my @WeekDayName = ("Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat");
my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime($time);
$year += 1900;
$mon++;
if($time =~ /^\s*(\d+)\/(\d+)\/(\d+)\s+(\d+):(\d+):?(\d+)?/) { #2007/02/11 09:41:17
($year, $mon, $mday, $hour, $min, $sec) = ($1, $2, $3, $4, $5, $6);
$sec = 0 if(!defined $sec);
}
if($time =~ /^\s*(\d+)s*,\s*(\w+)s*,\s*(\d+)\s+(\d+):(\d+):?(\d+)?/) { #15, Mar, 2007 23:52:53
($mday, $mon, $year, $hour, $min, $sec) = ($1, $2, $3, $4, $5, $6);
for(my $i = 0 ; $i < 12 ; $i++) {
if($MonthName[$i] =~ /$mon/i) {
$mon = $i+1;
last;
}
}
$sec = 0 if(!defined $sec);
}
#print "t:$time [$year/$mon/$mday $hour:$min:$sec]
\n";
my $str;
if($format) {
$str = $format;
$str =~ s/{year}/$year/g;
$str =~ s/{month}/$mon/g;
$str =~ s/{monthZero}/sprintf("%02d", $mon)/eg;
$str =~ s/{day}/$mday/g;
$str =~ s/{dayZero}/sprintf("%02d", $mday)/eg;
$str =~ s/{hour}/$hour/g;
$str =~ s/{hourZero}/sprintf("%02d", $hour)/eg;
$str =~ s/{min}/$min/g;
$str =~ s/{minZero}/sprintf("%02d", $min)/eg;
$str =~ s/{sec}/$sec/g;
$str =~ s/{secZero}/sprintf("%02d", $sec)/eg;
}
elsif(defined $language and $language =~ /SMTP(.*)$/i) {
my $timediff = $1;
$str = sprintf("%s, %d %s %04d %02d:%02d:%02d %s",
$WeekDayName[$wday], $mday, $MonthName[$mon-1], $year,
$hour, $min, $sec, $timediff);
}
elsif(defined $language and $language =~ /British\s?English/i) {
$str = sprintf("%3s, %02d, %02d %02d:%02d:%02d",
$MonthName[$mon-1], $mday, $year, $hour, $min, $sec);
}
elsif(defined $language and $language =~ /English/i) {
$str = sprintf("%02d, %3s, %02d %02d:%02d:%02d",
$mday, $MonthName[$mon-1], $year, $hour, $min, $sec);
}
else {
$str = sprintf("%02d/%02d/%02d %02d:%02d:%02d",
$year, $mon, $mday, $hour, $min, $sec);
}
return $str;
}
sub AddCommasToMoney
{
my ($num) = @_;
return &SeparateStringBy($num, ',', 3);
}
#$str を $nsep桁ごとに$sepで区切る
sub SeparateStringBy
{
my ($str, $sep, $nsep) = @_;
$str =~ s/\G((?:^[-+])?\d{1,$nsep})(?=(?:\d{$nsep})+(?!\d))/$1$sep/g;
return $str;
}
sub GetSimplifiedSize
{
my ($size, $factor, $ReturnInt, $nAddCommas) = @_;
$factor = 10 if(!defined $factor);
my $unit = '';
if($size > 1024*$factor) {
$size /= 1024;
$unit = "K";
}
if($size > 1024*$factor) {
$size /= 1024;
$unit = "M";
}
if($size > 1024*$factor) {
$size /= 1024;
$unit = "G";
}
if($size > 1024*$factor) {
$size /= 1024;
$unit = "T";
}
$size = int($size) if($ReturnInt);
$size = Utils::SeparateStringBy($size, ',', $nAddCommas);
return ($size, $unit);
}
sub convert
{
my ($pStr, $targetcharcode, $sourcecharcode) = @_;
return '' if(!defined $pStr or $pStr eq '');
return $$pStr if(!defined $targetcharcode or $targetcharcode eq '' or $targetcharcode eq 'ascii' or $targetcharcode eq 'binary');
$sourcecharcode = Jcode::getcode($$pStr) if(!defined $sourcecharcode);
return $$pStr if(!defined $sourcecharcode or $sourcecharcode eq '' or $sourcecharcode eq 'ascii' or $sourcecharcode eq 'binary');
Jcode::convert($pStr, $targetcharcode, $sourcecharcode);
return $$pStr;
}
sub ConvertToValidFileName
{
my ($fname) = @_;
my ($drive, $directory, $filename, $ext1, $lastdir, $filebody) = Deps::SplitFilePath($fname);
$filename =~ s/[\s:\\\/\*\?\|]/_/g;
return Deps::MakePath("$drive$directory", $filename, 0);
}
sub FindExistingPath
{
my (@paths) = @_;
for(my $i = 0 ; $i < @paths ; $i++) {
return $paths[$i] if(-e $paths[$i]);
}
return undef;
}
sub FindExistingDir
{
my (@paths) = @_;
for(my $i = 0 ; $i < @paths ; $i++) {
return $paths[$i] if(-d $paths[$i]);
}
return undef;
}
sub FindExistingFile
{
my (@paths) = @_;
for(my $i = 0 ; $i < @paths ; $i++) {
return $paths[$i] if(-f $paths[$i]);
}
return undef;
}
sub DeleteFile
{
my ($infile, $DeleteDirectory) = (@_);
if(-d $infile) {
if(!$DeleteDirectory) {
return 0;
}
return 0 if(!rmdir($infile));
return 1;
}
return 0 if(!unlink($infile));
return 1;
}
sub MoveFile
{
my ($infile, $outfile) = (@_);
if(-d $infile) {
return 0 if(!rename($infile, $outfile));
return 1;
}
return move($infile, $outfile);
my $ret = &CopyFile($infile, $outfile);
return $ret if($ret != 1);
return -3 if(!unlink($infile));
return 1;
}
sub CopyFileRecursive
{
my ($infile, $outfile, $buf) = (@_);
#fcopy($Source, $CopyTarget) or die $!;
if($buf) {
return rcopy($infile, $outfile, $buf);
}
else {
return rcopy($infile, $outfile);
}
#dircopy($Source, $CopyTarget) or die $!;
}
sub CopyFile
{
my ($infile, $outfile, $buf) = (@_);
my ($drive, $directory, $filename, $ext, $lastdir, $filebody) = Deps::SplitFilePath($outfile);
$directory = "$drive$directory" if(defined $drive and $drive ne '');
if(!-e $directory) {
Deps::CreateDirecotry($directory);
}
if($buf) {
return copy($infile, $outfile);
}
else {
return copy($infile, $outfile);
}
open(IN, "<$infile") or return -1;
binmode(IN);
open(OUT, ">$outfile") or return -2;
binmode(OUT);
my @content = ;
print OUT @content;
close(OUT);
close(IN);
my $time = GetWriteDate($infile);
if($time) {
utime($time, $time, $outfile)
}
return 1;
}
sub DeleteDirectory
{
my ($infile) = (@_);
return 0 if(!rmdir($infile));
return 1;
}
sub CreateDirectory
{
my ($dir, $dirsep, $IsPrint) = @_;
$IsPrint = 1 if(!defined $IsPrint);
my $directorysep = $DirectorySeparator;
$directorysep = $dirsep if($dirsep ne '');;
$dir =~ s/\\/\//g;
#$Debug=1;
if($Debug) {
print "CreateDirectory: $dir
\n";
}
# my $IsHeadSep = 0;
# $IsHeadSep = 1 if($dir =~ /^\//);
my $IsRelative = 1;
$IsRelative = 0 if($dir =~ /^[A-Za-z]:\// or $dir =~ /^\//);
#print "IsRelative: $IsRelative\n";
my @eachpath = split(/\//, $dir);
my $i = 0;
my $path = "";
if($eachpath[$i] =~ /^[A-Za-z]:/) {
$path = $eachpath[$i];
$i++;
}
$path .= $directorysep unless($IsRelative);
for( ; $i < @eachpath ; $i++) {
$path .= $eachpath[$i] . $directorysep;
if($Debug) {
print "path: $path
\n";
}
next if(-d $path);
if(-f $path) {
print "Can not create [$path]: $path is a file.\n" if($IsPrint);
return 0;
}
if($Debug) {
print " Create $path [$directorysep]
\n";
}
mkdir($path);
}
return 1;
}
sub Glob
{
my ($dir, $fmask, $Sort) = @_;
my $pwd = getcwd();
return () if(!chdir($dir));
my @files = glob($fmask);
@files = sort @files if($Sort);
for(my $i = 0 ; $i < @files ; $i++) {
$files[$i] = Utils::MakePath($dir, $files[$i], '/', 0);
#print "f[$files[$i]]
\n";
}
chdir($pwd);
return @files;
}
sub MyFindFile
{
my ($dir, $RegExp) = @_;
my @f;
opendir my $dh, $dir or return undef;
while (my $file = readdir $dh) {
next if($file eq '.' or $file eq '..');
push(@f, $file) if($RegExp eq '' or $file =~ /$RegExp/i);
}
closedir $dh;
return @f;
}
my @FileArrayForSearchFilesRecursive;
sub AddFileForSearchFilesRecursive
{
push(@FileArrayForSearchFilesRecursive, $File::Find::name);
}
sub SearchFilesRecursive
{
my ($dir, $pFiles) = @_;
@FileArrayForSearchFilesRecursive = ();
find(\&AddFileForSearchFilesRecursive, $dir);
return @$pFiles = @FileArrayForSearchFilesRecursive;
}
sub SearchFilesRecursive2
{
my ($dir, $fmask, $nLevel, $pFiles, $Sort, $func, %arg) = @_;
$fmask = '*' if(!defined $fmask);
$nLevel = 1 if(!defined $nLevel);
$Sort = 0 if(!defined $Sort);
my $path0 = Deps::MakePath($dir, $fmask, 0);
my $DirPath0 = Deps::MakePath($dir, '*', 0);
#print "Path[$path0]\n";
my @dir = glob($DirPath0);
# my @dir = Utils::Glob($dir, '*');
for my $path (@dir) {
#print("path: $path\n");
if($path =~ /[\\\/]\.$/ or $path =~ /[\\\/]\.\.$/) {
#print("path [$path] is . or ..: skip\n");
next;
}
if(!-d $path) {
#print("path [$path] is not dir: skip\n");
next;
}
#print "Utils::SearchFilesRecursive2: Found Dir [$path]\n";
print "Utils::SearchFilesRecursive2: Found Dir [$path]\n" if($arg{Debug});
if(!defined $func or &$func($path) == 1) {
push(@$pFiles, $path);
}
if($nLevel != 0) {
&SearchFilesRecursive2($path, $fmask, $nLevel-1, $pFiles, $Sort, $func, %arg);
}
}
my @files = glob($path0);
# my @files = Utils::Glob($dir, $fmask);
for my $path (@files) {
next if(-d $path and !$arg{SearchDir});
print "Utils::SearchFilesRecursive2: Found File [$path]\n" if($arg{Debug});
# my $path = Utils::MakePath($dir, $f, '/', 0);
#print "File [$path]\n";
if(!defined $func or &$func($path) == 1) {
push(@$pFiles, $path);
}
}
@$pFiles = sort { $a cmp $b; } @$pFiles if($Sort);
return @$pFiles;
}
sub SearchFilesRecursive3
{
my ($dir, $fmask, $nLevel, $pFiles, $Sort, $func, %arg) = @_;
$fmask = '*' if(!defined $fmask);
$nLevel = 1 if(!defined $nLevel);
$Sort = 0 if(!defined $Sort);
my $path0 = Deps::MakePath($dir, $fmask, 0);
my $DirPath0 = Deps::MakePath($dir, '*', 0);
print "Search path [$path0]\n";
my @dir = Utils::MyFindFile($dir, '');
for my $path (@dir) {
next if($path eq '.' or $path eq '..');
my $path1 = Utils::MakePath($dir, $path, '/', 0);
print "Utils::SearchFilesRecursive3: Found Dir [$path1]\n" if($arg{Debug});
next if(!-d $path1);
if($nLevel != 0) {
&SearchFilesRecursive3($path1, $fmask, $nLevel-1, $pFiles, $Sort, $func, %arg);
}
}
my @files = Utils::MyFindFile($dir, $fmask);
for my $path (@files) {
my $path1 = Utils::MakePath($dir, $path, '/', 0);
next if(-d $path1);
print "Utils::SearchFilesRecursive3: Found File [$path1]\n" if($arg{Debug});
#print "File [$path1]\n";
if(!defined $func or &$func($path1) == 1) {
push(@$pFiles, $path1);
}
}
@$pFiles = sort { $a cmp $b; } @$pFiles if($Sort);
return @$pFiles;
}
sub FindFuncForSearchFilesRecursive4
{
my $path = $File::Find::dir . '/' . $_;
print "Check path [$path]\n";
return 1;
};
sub SearchFilesRecursive4
{
my ($dir, $func) = @_;
find($func, ($dir));
}
sub ChangeMode
{
my ($path, $mode) = @_;
return chmod(oct($mode), $path);
}
sub PrintList
{
my (@a) = @_;
for(my $i = 0 ; $i < @a ; $i++) {
print "$i: [$a[$i]]\n";
}
}
sub PrintHash
{
my (%hash) = @_;
foreach my $key (keys %hash) {
print "$key: [$hash{$key}]\n";
}
}
#==========================================
#
# For HTML
#
#==========================================
sub HTMLRedirectTo
{
my ($url, $wait, $target, $charset) = @_;
$wait = 0 if(!defined $wait);
$target = "_self" if(!defined $target);
$charset = 'iso-8859-1' if(!defined $charset);
Utils::InitHTML();
print <
Jump to $url
Click the following link if this page is not redirected automatically