#!/usr/local/bin/perl # ************** scm4.cgi V2.0(2005/08/31)************* # シンプル着メロサイトメーカー4 # Copyright (c) とまて # # 配布元URL:『シンプル着メロサイトメーカー4のページ』 # http://www3.kcn.ne.jp/~tomate/o_gate/scm4.html # 『とまての実験室』http://www3.kcn.ne.jp/~tomate/ 内 # 2004/09/23:自CGIを呼ぶときにフルパス指定推奨することにしました。$me="…"の部分です。 # 2005/08/31:Vodafoneのユーザーエージェントの変更になったため機種選択部分を改造しました。 ############################################################# # ファイル名関連 $me="http://(絶対パス指定)/scm4.cgi"; # このCGIのファイル名をフルパス指定にして下さい。 $top_page="html/k_top.html"; # ページを指定していない場合のデフォルトのファイル名(通常サイトのトップページをこのCGIからの相対パスで) $I_path="Imelo"; # i-mode着メロ(*.mld)を格納するフォルダへのパス(このCGIからの相対パス) $J_path="Jmelo"; # Vodafone/EzWeb用 着メロ(*.mmf)を格納するフォルダへのパス(このCGIからの相対パス) # 管理人パスワード $passset='kanri'; # ページタイトルのデフォルト $title="NonTitle"; # アクセスログ関連 $access_log=1; # アクセスログを採るか採らないか 1:採る 0:採らない $access_max=100; # アクセスログ保存数 $access_log_file='access.txt'; # アクセスログファイルの指定(このCGIからの相対パスで) # ダウンロードカウンタ関連 $dlcnt_file_head="DL_"; # ダウンロードカウンタファイル名の頭(scm4_count.cgiと整合性を取る必要が有ります) $lockfile="lockfile.txt"; # ロックファイルの名前 $dllogmax=12; # ダウンロードカウンタファイルの保存数(何か月分か?) $pc_dnload=1; # PCへのダウンロードを許可する(1:許可,0:不許可) # 曲のコメント(作曲者名、作者名など)の色 $comcolor="#00aaff"; # エラーメッセージの文言 # ロックファイルが有る。2人以上のリクエストが同時に入った場合。 $message1='只今混み合っております。恐れ入りますがもう一度お願いします。'; # ログファイルが開けない場合(管理人はログファイルの属性などをチェックする必要有り。 $message2='申訳ありません。只今、ダウンロードできません。'; # PCからのダウンロードを許可しない場合のメッセージ(PCに対して) $for_pc=<<'HIA';
着メロはリスト表示のみになっております。 PCからのアクセスと認識されました。 携帯電話実機でのアクセスをお待ちしております!
携帯電話実機でアクセスしているにもかかわらずこのメッセージが出ている場合は、 ご連絡頂けたら幸いです。


HIA # PC表示の時にページ下部に載せる情報(サイトアドレス送信用LINK、管理人パスワード入力欄が有りますが、調整・削除・お好みの情報を追加して下さい) $pcfooter=<<"HIA"; 【携帯にこのサイトのURLを送信する】
管理人PASS
HIA ############################################################# @indata=(); $err=""; # アクセスされたページネームの取得 %form = &read_input('sjis'); $page = $form{'page'}; $name = $form{ 'name' }; $count = $form{ 'count' }; $offset = $form{ 'offset' }; $dump = $form{ 'dump' }; $pass = $form{'pass'}; # 日付のセット ($sec , $min , $hour, $mday, $mon, $year ,$wday) = localtime(); $today=sprintf("%04d/%02d/%02d %02d:%02d:%02d",$year + 1900, $mon + 1, $mday,$hour,$min,$sec); $dlcnt_file=$dlcnt_file_head.sprintf("%04d_%02d",$year + 1900, $mon + 1).".txt"; # エージェントの取得 if($agent eq ""){$agent=$ENV{'HTTP_USER_AGENT'}}; # ホストの取得 $host=$ENV{'REMOTE_HOST'}; if($host eq ''){$host=$ENV{'REMOTE_ADDR'};} # エージェントによって表示の切り替えを行う if( index($agent,"DoCoMo")>=0 ){$pnum=0;} elsif(index($agent,"J-PHON")>=0 || index($agent,"Configuration")>=0){$pnum=1;} elsif(index($agent,"UP.Browser")>0 ){$pnum=2;} elsif(index($agent,"UP.Browser")==0){$pnum=3;} else{ $pnum=4;} if($dump ne '' || $name ne ''){ # EzWebの場合のダウンロードサブルーチン(from z2.cgi)へ跳ぶ。 if ( $dump ne '' ) {$xdcgi = 1;$name = $dump;} if ( $name ) {&download} }else{ #==================================================================================== # ページデータの情報を収集して、表示やEzWeb以外のキャリアへのダウンロードの準備をする。 if($page eq ''){$page=$top_page;} if(index($page." ","@")>0){$atnum=1}else{$atnum=0} ($page,$kyokuban,$PC_IJ)=split('@',$page); # ページデータの入力 @dmy=<${page}*>; if($dmy[0] eq $page){ &fileinput($page,'indata'); $honbun=join("\n",@indata); }else{$err=$massage."$pageが見つかりません";} # ページタイトル・BODYタグ要素の分離 if(&chopparu($honbun,'','',0)>=0){ $title=$chop2; $honbun=$chop1.$chop3;} if(&chopparu($honbun,'',0)>=0){ $title=$chop2; $honbun=$chop1.$chop3;} $body=''; if(&chopparu($honbun,'',0)>=0){ $body=$chop2 ; $honbun=$chop1.''.$chop3; if(&chopparu($honbun,'','',0)>=0){$honbun=$chop2;} } if(&chopparu($honbun,'',0)>=0){ $body=" $chop2"; $honbun=$chop1.$chop3} if(&chopparu($honbun,'',0)>=0){ $comcolor=$chop2; $honbun=$chop1.$chop3} # イメージタグの書き換え $pos3=&chopparu($honbun,'src="','"',0); while($pos3>=0){ $honbun=$chop1.'src="'.&path_reduce("$base/$chop2").'"'.$chop3; $pos3=&chopparu($honbun,'src="','"',$pos3+1); } # VODAFONとHDMLはpngそれ以外はgif if($pnum==1||$pnum==3){$honbun=~ s/\.gif\"/\.png\"/g;}else{$honbun=~ s/\.png\"/\.gif\"/g;} #==================================================================================== if($atnum==0){ # 普通のインフォメーションページの表示を行うサブルーチンへ跳ぶ。 &info_sub; }else{ # mldとmmfを選別する if($PC_IJ eq 'I'||$pnum==0){$ctype='Content-Type: application/x-mld' ;$kakucho='.mld';$dir=$I_path} else{ $ctype='Content-Type: application/x-smaf';$kakucho='.mmf';$dir=$J_path} # ダウンロード操作(表示)のためのデータの取り出し $pos=-1; for($i=0;$i<$kyokuban;$i++){$pos=index($honbun,'',$pos+1);} &chopparu($honbun,'','',$pos+1); ($label,$filename,$data_type0,$comment)=split(",",$chop2); if( $pnum==2 || $pnum==3){ # EzWebの場合のダウンロードページの表示を行うサブルーチンへ跳ぶ。 &ez_dl_page; }else{ # PC,i-mode,J-PHONの場合のダウンロード操作を行うサブルーチンへ跳ぶ。 &normal_dnld; } } } exit(); #===================↓ここからサブルーチン============================= sub normal_dnld{ # ダウンロード画面やエラー表示の場合の戻りリンクを作成する。 $modoru="
[戻る]
"; if(index($filename,'/',0)>=0){ @dmy=split('/',$filename); $fname=$dmy[@dmy-1]; }else{$fname=$filename} if($pnum==4){$nameset="Content-disposition: filename=\"$fname$kakucho\n\""}else{$nameset=''} &binmode_in("$dir/$filename$kakucho\n"); # ダウンロードログを採る if($dllogmax>0){&DLcnt($filename.$kakucho);} &binmode_out("$ctype\n${nameset}Content-Length: ".length($buf)."\n\n$buf"); } sub ez_dl_page{ # ダウンロード画面やエラー表示の場合の戻りリンクを作成する。 $modoru="
[戻る]
"; # mmfのデータタイプを4,16,40の各和音数で振り分ける if( $data_type0== 4){$data_type0='dev4anm';} elsif($data_type0==16){$data_type0='devmfan';} elsif($data_type0==40){$data_type0='devm39z';} $comment=~ s/
//g; $comment=~ s/\s//g; # ファイルサイズを実測する $fs = -s "$J_path/$filename.mmf"; if($pnum==2){ # WAP2.0の場合のダウンロード画面 # 着メロダウンロード操作 $honbun=<をダウンロードしますか?

\n
\n \n
\n$modoru HIA2 }else{ # HDMLの場合のダウンロード画面 # 着メロダウンロード操作 $cheksum=$fs+2; $honbun=<
[OK]
$modoru HIA1 } &display($honbun); } sub info_sub{ # アクセスログを取る if($access_log == 1 && $page eq $top_page){ $access=&access_check; $pos3=-1; $pos3=index($honbun,'$access',0); if($pos3>=0){$honbun=substr($honbun,0,$pos3).$access.substr($honbun,$pos3+7,length($honbun)-$pos3-7);} } # 表示頁のパスの分離 $pos1=rindex($page,"/"); if($pos1>0){$base=substr($page,0,$pos1+1);}else{$base="";} # 相対アドレス指定のファイルへのLINKをCGI経由でのアクセスに変更する。 $pos3=&chopparu($honbun,'',0); while($pos3>=0){ if(index($chop2,'http:')<0){ # 表示頁のパスの整理 $soutaipath=&path_reduce($base.$chop2); # Link Checkモード======================================= if($pass eq $passset){ if(-e "$soutaipath"){$linkchk='LINK OK';} else{$linkchk="LINK NG$soutaipath";} $pass_add="&pass=$pass"; } #======================================================== # cgi経由のアクセスに置き換え $honbun="$chop1$linkchk$chop3"; } $pos3=&chopparu($honbun,'',$pos3+1); } # タグの処理を行う if(index($honbun,'')>=0){ # mldとmmfを選別する if($pnum==0){$kakucho='.mld'}else{$kakucho='.mmf'} # 携帯実機以外からの着メロのダウンロードを禁止している場合の文言を表示します。 if($pc_dnload!=1 && $pnum==4){$honbun=$for_pc.$honbun;$listonly=1}else{$listonly=0} $i=-1; while(&chopparu($honbun,'','',0)>=0){ $i++; ($label,$filename,$dmy1,$comment)=split(",",$chop2); # Link Checkモード======================================= if($pass eq $passset){ if(-e "$I_path/$filename.mld"){$linkchk='MLD OK';} else{$linkchk="MLD NG$filename.mld";} if(-e "$J_path/$filename.mmf"){$linkchk=$linkchk.'MMF OK';} else{$linkchk=$linkchk."MMF NG$filename.mmf";} } #======================================================== if($listonly==1){ # 携帯実機以外からの着メロのダウンロードを禁止している場合の着メロリスト画面 $atag="$label
  ($comment)$linkchk"; }elsif($pnum==4){ # PCの場合の着メロ選択画面 $atag=<$label
($comment)
[i-mode用] [Vodafone/EzWeb用]$linkchk HIA }else{ # i-mode、Vodafon、EzWebの場合の選択画面 $atag="\n$label\n
  ($comment)\n\n"; } $honbun=$chop1.$atag.$chop3; } } &display($honbun); } sub display{ local $honbun=$_[0]; if($pnum==0 || $pnum==1){ #----------------------------- # i-modeとVordafonのための表示 #----------------------------- local $out="$title\n$honbun"; print "Content-Type: text/html\nContent-Length: ".length($out)."\n\n".$out; }elsif($pnum==2){ #----------------------------- # EzWeb(WAP2.0)用の表示 #----------------------------- $out=<<"HIA"; content-type:text/html\n\n $title $honbun HIA $out=~ s/
/
/g; print $out; }elsif($pnum==3){ #----------------------------- # EzWeb(HDML)用の表示 #----------------------------- $out=<<"HIA"; content-type:text/x-hdml;charset=shift_jis\n\n $honbun HIA # ==========================HDML特有のタグの変更を行う======================== # タグを削除、
タグを
へ、[通常モードに戻る]";} $out=<<"HIA"; content-type:text/html\n\n $title $honbun
$pcfooter$kanri_add
scm4.cgi
HIA print $out; } exit; } sub chopparu{ # &chopparu(0:元の文字列,:1開く括弧,2:閉じる括弧,3:探し始める位置) local($pos1,$pos2); $pos1=index($_[0],$_[1],$_[3]); if($pos1>=0){ $pos2=index($_[0],$_[2],$pos1+length($_[1])); if($pos2 >= 0){ $chop1=substr($_[0],0,$pos1); $chop2=substr($_[0],$pos1+length($_[1]),$pos2-$pos1-length($_[1])); $chop3=substr($_[0],$pos2+length($_[2]),length($_[0])-$pos2-length($_[2])); }else{ $chop1=$_[0]; $chop2=''; $chop3=''; $pos1=-1; } } return $pos1; } sub access_check{ # アクセスログファイル入力 @access=(); &fileinput($access_log_file,'access'); $dmy=$access[@access-1]; @dmy=split("\,",$dmy); $dmy=$dmy[3].','.$dmy[4]; local $count=substr($dmy[0],0,5); # ↓前の行とのみ比較している if($dmy ne "\"$agent\",\"$host\""){ # カウントUP(5桁まで) $count++; # アクセスログ更新 local $newaccess=sprintf("%05d",$count).",$today,($access_page),\"$agent\",\"$host\""; push(@access,$newaccess); if(@access>$access_max){$dmy=shift(@access);} if ( !open (FILEOUT, ">$access_log_file") ){ $message="
ファイル書き込みに失敗しました
"; }else{ print FILEOUT join("\n",@access); close(FILEOUT); } } return $count; } sub DLcnt{ # ダウンロードカウンタ local @dmy=split('/',$_[0]); local $nameset=$dmy[@dmy-1]; # ロックファイルのチェック if(-e $lockfile){ $ok_frag=0;$err=$message1; }else{ # ロックファイル作成 $ok_frag=1;open(LOCK,">$lockfile");close(LOCK); } if($ok_frag == 1){ # ダウンロードログファイル入力 $logs=""; if(-e $dlcnt_file){ if ( !open (FILE_IO, $dlcnt_file )){ $err=$message2; }else{ $logs = join("\n",); close(FILE_IO); } } # 過去ログ検索 # ↓過去ログに同じ(ファイル名、エージェント、ホスト)の組み合わせが有るかどうかのチェックをしているが、 # 今回ははずしました。 #if(index( $logs,"\t$nameset\t$agent\t$host\n" )<0 || $logs eq ""){ # アクセスログ更新 if ( !open (FILEOUT, ">>$dlcnt_file") ){ $err=$message2; }else{ print FILEOUT "$today\t$nameset\t$agent\t$host\n"; close(FILEOUT); } #} # ロックファイル削除 if(-e $lockfile){unlink($lockfile);} # ログファイルが指定数以上になった場合、古いものから消す。 $wildcard="$dlcnt_file_head*.txt"; @logfiles=<${wildcard}>; if(@logfiles>$dllogmax){unlink($logfiles[0])} } if($err ne ''){&display("$err\n$modoru");} } #================================================================= # ファイル入力サブルーチン__ &fileinput(入力ファイル名,変数名) #   ※サブルーチンを呼ぶ前に、@変数名=();など、配列をあらかじめ作っておく必要があります。 sub fileinput{ local $filename=$_[0]; local $hensuumei=$_[1]; if ( !open (FILE_IO, $filename) ){ local $err="ファイルオープンエラー"; }else{ @$hensuumei = ; close(FILE_IO); } $cntend=@$hensuumei-1; for ($i=0;$i<=$cntend;$i++){ $$hensuumei[$i]=~s/\r//g; $$hensuumei[$i]=~s/\n//g; } return($err); } sub binmode_in{ open ( R , $_[0] )||&display('ファイルが有りません'.$modoru); binmode ( R ); local ( $fsize ) = -s R; read ( R, $buf, $fsize ); close ( R ); } sub binmode_out{ binmode STDOUT; print $_[0]; } sub path_reduce{ local @dmy=split("/",$_[0]); local $kaisou=@dmy-2; local $minus=0; local $soutaipath=$dmy[$kaisou+1]; for($i=$kaisou;$i>=0;$i--){if($dmy[$i] eq ".."){$minus--;}else{if($minus>=0){$dmy=$soutaipath;$soutaipath=$dmy[$i]."/".$dmy;}else{$minus++;}}} for($i=$minus;$i<0;$i++){$soutaipath="../$soutaipath"} return $soutaipath; } #******************************************************************************** # “Kamitani Home Page”http://home.interlink.or.jp/~kamitani/index.cgi # のcgi-bin抜粋を利用させていただいております # # read_input : フォームからのデータを分解し $form{'xxxx'} で返す。 # 引数 1: 'euc' or 'jis' or 'sjis' #******************************************************************************** sub read_input { local $charset = $_[0]; $charset = 'euc' if ( $charset eq '' ); local ($buffer, @pairs, $pair, $name, $value, %FORM); # Read in text $ENV{'REQUEST_METHOD'} =~ tr/a-z/A-Z/; if($ENV{'REQUEST_METHOD'} eq "POST") { read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'}); }else{ $buffer = $ENV{'QUERY_STRING'};} @pairs = split(/&/, $buffer); foreach $pair (@pairs) { ($name, $value) = split(/=/, $pair); $value =~ tr/+/ /; $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; #&jcode'convert(*value, $charset); $FORM{$name} = $value; } %FORM; } #******************************************************************************** # # sub downloadとsub crcは(http://www.kt.rim.or.jp/~marca/)様配布の # ez2.cgi ver1.2814『ezGet用超単純スクリプト』から抜粋、改造させていただいたものです。 # 他用途への利用を希望される方は、汎用性のある原作に戻られることをお勧めいたします。 #                               とまて #******************************************************************************** sub download { binmode STDIN; binmode STDOUT; if($pnum==3){$c5000=-1;}else{$c5000=0;} if ( ( $offset >= 0 ) && ( $count > 0 ) || ( $dump ne '' ) ) { open ( R , "$J_path/$name" ) || &display("ファイルが有りません"); binmode ( R ); local ( $fsize ) = -s R; local ( $buf ); read ( R, $buf, $fsize ); close ( R ); local ( $crc ) = 0; if ( $c5000 != 0 ) {$crc = &crc ( *buf );} if ( $dump ne '' ) { $offset = 0; $count = $fsize; } if ( $crc != 0 ) { local ( $c1 ) = ( $crc & 0xff00 ) >> 8; local ( $c2 ) = $crc & 0x00ff; $buf .= pack ( 'CC', $c1, $c2 ); } local ( $out ) = substr ( $buf, $offset, $count ); if ( $dump ne '' ) { if($dllogmax>0){&DLcnt($name);};# ダウンロードログを採る print "Content-Type: application/x-smaf\n"; print "Content-length: $count\n\n"; print $out; } else { if($dllogmax>0){&DLcnt($name);};# ダウンロードログを採る print "Content-type: application/x-up-download\n"; print "Content-length: $count\n\n"; print $out; } } elsif ( ( $offset == 0 ) && ( $count == 0 ) ) { print "Content-type: application/x-up-download\n"; print "Content-length: 0\n\n"; } elsif ( ( $offset == -1 ) && ( $count == -1 ) ) { print "Content-type: text/x-hdml;charset=Shift_JIS\n\n"; print qq|\n|; print qq|\n|; print qq|\n|; print qq|\n|; print qq|\n|; } elsif ( ( $offset == -1 ) && ( $count == -2 ) ) { &display ( 'ダウンロード失敗', 'データが壊れているか,表示/再生できない形式です.' ); } else { &display ( '原因不明のエラー' ); } } sub crc { local ( *a ) = shift; local ( @crctable ) = ( 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0 ); local ( $crc ) = 0xffff; local ( $i ); foreach $i ( unpack ( 'C*', $a ) ) { local ( $ch ) = ( $crc & 0xff00 ) >> 8; local ( $cs ) = ( $crc << 8 ) & 0xffff ; $crc = $crctable[ $ch ^ $i ] ^ $cs; } return ( $crc & 0xffff ); } # ez.cgi ver1.2814 __END__