ホーム > PHP > 簡易ダウンロードカウンタ

簡易ダウンロードカウンタ

  • 2007 年 12 月 8 日 19:35
  • PHP

今日 Riszw のりんたんと 3ping.org のうーたんがダウンロードカウンタについて会話しておりました。
要約すると「カウントだけしてくれるダウンロードカウンタがないよねー」との事だったのでついカッとなって作りました。

仕様

  • $ini['downloadDir'] で指定したディレクトリ直下にダウンロードするファイルがなければなりません。
  • $ini['log']['dir'] で指定したディレクトリがなければ作成しますが、権限がないと作れないのであらかじめ作って(パーミッションは707)おいた方がよいです。
  • ログファイルは月毎に YYYYMM.log という形式で保存されますので、納得いかない場合は適当に編集して下さい。
  • ログファイルのフォーマットは
    日付,ダウンロードしたファイル名,リモートアドレス,ユーザーエージェント

    となっております。これも納得いかない場合は適当に編集して下さい。

  • $ini['downloadDir'] で指定したディレクトリ配下には直接アクセスできない方がこの場合よろしいかと思います。その場合には .htaccess などで
    order deny,allow
    deny from all
    allow from localhost

    とされるのが手っ取り早いかと思います。

  • PATH_INFO で指定されたファイルを $ini['downloadDir'] から探してきますが、ダウンロードする際の Content-Type は拡張子から判断しております。ソースに無い Content-Type は任意で追加して下さい。
  • ファイル名として許可されている文字は $ini['pregSource'] となります。納得いかない場合は自己責任の上で編集して下さい。ディレクトリトラバ云々に関しては何も対策しておりませんのでご注意下さい。
  • このスクリプトを通してダウンロードする場合、URI は http://ドメイン/スクリプトのファイル名/ダウンロードするファイル名 となります。例えば spais.jp で d.php を利用して 285.gif をダウンロードする場合の URI は http://spais.jp/d.php/285.gif となります。
  • http://spais.jp/d.php/285.gif ってなんかダサくねえ?という向きはコンテントネゴシエーションなりで対策して下さい。

ソース

ソースはこんな感じです。

<?php
 
/**
 * @name 簡易ダウンロードカウンタ
 * @author nic <webmaster@spais.jp>
 * @version 0.1
 * @since 2007/12/08
 */
 
/**
 * ダウンロードするファイルがあるディレクトリ(相対パス or 絶対パス)
 */
$ini['downloadDir'] = 'download/';
 
/**
 * ログファイルを保存するディレクトリ(相対パス or 絶対パス)
 */
$ini['log']['dir'] = 'log/';
 
/**
 * ログの日付フォーマット:date()
 * http://www.php.net/manual/ja/function.date.php
 */
$ini['log']['dateFormat'] = 'Y/m/d H:i:s';
 
/**
 * ログファイルの拡張子
 */
$ini['log']['name'] = '.log';
 
/**
 * ログファイルの区切り文字
 */
$ini['log']['separator'] = ',';
 
/**
 * 有効な Content-type
 */
$ini['Content-type']['.zip']  = 'application/zip';
$ini['Content-type']['.lzh']  = 'application/x-lzh';
$ini['Content-type']['.txt']  = 'text/plain';
$ini['Content-type']['.php']  = 'text/plain';
$ini['Content-type']['.csv']  = 'text/csv';
$ini['Content-type']['.css']  = 'text/css';
$ini['Content-type']['.js']   = 'text/javascript';
$ini['Content-type']['.html'] = 'text/html';
$ini['Content-type']['.htm']  = 'text/html';
$ini['Content-type']['.gif']  = 'image/gif';
$ini['Content-type']['.jpg']  = 'image/jpeg';
$ini['Content-type']['.jpeg'] = 'image/jpeg';
$ini['Content-type']['.png']  = 'image/png';
$ini['Content-type']['.mpg']  = 'video/mpeg';
$ini['Content-type']['.mpeg'] = 'video/mpeg';
$ini['Content-type']['.wmv']  = 'video/x-ms-wmv';
$ini['Content-type']['.3gp']  = 'video/3gpp';
$ini['Content-type']['.3g2']  = 'video/3gpp2';
 
/**
 * ファイル名チェック用
 * http://www.php.net/manual/ja/reference.pcre.pattern.syntax.php
 */
$ini['pregSource'] = '0-9a-z_\-\~\.';
 
 
/**
 * ここから本文
 */
 
/**
 * ファイル名の抽出
 */
 
$pathinfo_index = isset($_SERVER['ORIG_PATH_INFO']) ? 'ORIG_PATH_INFO' : 'PATH_INFO';
if(!isset($_SERVER[$pathinfo_index])) _back(); // ファイル名は指定されてるかな?
$filename = substr($_SERVER[$pathinfo_index], 1, strlen($_SERVER[$pathinfo_index]));
 
/**
 * ファイル名のチェックとか
 */
 
if(preg_match("/[^{$ini['pregSource']}]/i", $filename)) _back(); // 許可された文字だけかな?
if(!is_file($ini['downloadDir'].$filename)) _back(); // 指定されたファイルはあるかな?
preg_match('/(\.[a-z0-9]+$)/i', $filename, $ext);
if(!isset($ext[0])) _back(); // ファイル名に拡張子はあるかな?
strtolower($ext[0]);
if(!isset($ini['Content-type'][$ext[0]])) _back(); // 許可された拡張子かな?
 
/**
 * ファイル出力
 */
 
header('Content-Type: '.$ini['Content-type'][$ext[0]]);//.'; name='.$filename);
header('Content-Disposition: attachment; filename='.$filename);
header('Content-Length: '.filesize($filename));
 
echo file_get_contents($ini['downloadDir'].$filename);
 
/**
 * ログ生成
 */
$remote_addr = isset($_SERVER["REMOTE_ADDR"])? $_SERVER["REMOTE_ADDR"]: NULL;
$http_user_agent = isset($_SERVER["HTTP_USER_AGENT"])? $_SERVER["HTTP_USER_AGENT"]: NULL;
$l = date($ini['log']['dateFormat']).$ini['log']['separator'].$filename.$ini['log']['separator'].$remote_addr.$ini['log']['separator'].$http_user_agent."\n";
 
/**
 * ログ出力
 */
 
if(!is_dir($ini['log']['dir'])) mkdir($ini['log']['dir']);
$fp = fopen($ini['log']['dir'].date('Ym').$ini['log']['name'], 'a');
fwrite($fp, $l);
fclose($fp);
 
/**
 * 異常時に呼び出される
 * @return void
 */
 
function _back(){
    if(isset($_SERVER['HTTP_REFER'])){
        header('Location: '.$_SERVER['HTTP_REFER']);
    }else{
        header('Location: http://'.$_SERVER['HTTP_HOST']);
    }
    exit;
}
 
?>

ダウンロード

もしこのスクリプトを使ってまずいことになっても責任は取れません。
またこのスクリプトのライセンスは クリエイティブ・コモンズ 表示 – 継承 3.0 Unported を適用しています。
以上の事に同意をした上でダウンロードして下さい。

アクセスログ見ればいいじゃん。ってのは言わない方向でお願いします。

コメント:0

コメントフォーム
入力した情報を記憶する

トラックバック:0

この記事のトラックバック URL
http://spais.jp/php/%e7%b0%a1%e6%98%93%e3%83%80%e3%82%a6%e3%83%b3%e3%83%ad%e3%83%bc%e3%83%89%e3%82%ab%e3%82%a6%e3%83%b3%e3%82%bf/2007-12-08/trackback
トラックバックの送信元リスト
簡易ダウンロードカウンタ - SPaiS より

ホーム > PHP > 簡易ダウンロードカウンタ

カテゴリー

ページの上部に戻る