#!/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を送信する】
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$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
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__