サーバー上にあるデータを他の人に渡したい時に、WEB公開ディレクトリに置いてあるファイルを直接指定したURLを公開すると、サイト内のフォルダ構成が見えてあまりいいURLとは言えない。
もし、そのファイルが置いてあるフォルダのディレクトリ表示した際に、ファイル一覧が表示されるような事になれば、情報漏洩にも繋がる可能性があります。
また、web公開エリアにおいておらず、ユーザーのホームディレクトリに置かれているファイルも、いちいちwebディレクトリに設置しなおすのも面倒くさい。
シンボリックで対応する場合も、ファイル単体で対応できないので、とてもめんどくさくなる。
そこで、簡単にダウンロードさせることができるURLを出力して、ダウンロードの実行ができるツールを作ってみました。
概要
- ダウンロードする階層をエンコードして見た目で分かりにくくする。
- エンコードされたURLからファイルをダウンロードさせる。
- サーバー内のどの領域でもダウンロード対象にする。
- ファイルの種類は問わない
プログラム
index.php
ツールの入り口になるソース。このファイルで全ての処理をさばく。
<?php
require_once "lib.php";
require_once "libUrl.php";
$lib = new LIB();
//file-download
if($_REQUEST['mode']=='dl' && $_REQUEST['path']){
$lib->dl($lib->code2str($_REQUEST['path']));
}
//Encode
else if($_REQUEST['mode']=='encode'){
echo $lib->str2code($_REQUEST['path']);
}
//Decode
else if($_REQUEST['mode']=='decode'){
echo $lib->code2str($_REQUEST['code']);
}
//path->query(only one)
else if($_REQUEST['mode']=='convert'){
$convert = $lib->path2query($_REQUEST['path']);
$libUrl = new libUrl();
echo $libUrl->getUrl()."?mode=dl&path=".$convert;
}
//path->query(multi)
else if($_REQUEST['mode']=='converts'){
$libUrl = new libUrl();
$_REQUEST['path'] = str_replace("\r\n","\n",$_REQUEST['path']);
$_REQUEST['path'] = str_replace("\n\r","\n",$_REQUEST['path']);
$converts = explode("\n",$_REQUEST['path']);
for($i=0;$i<count($converts);$i++){
$converts[$i] = trim($converts[$i]);
$converts[$i] = str_replace("\n","",$converts[$i]);
$converts[$i] = str_replace("\r","",$converts[$i]);
if(!$converts[$i]){continue;}
$convert = $lib->path2query($converts[$i]);
$html.= $libUrl->getUrl()."?mode=dl&path=".$convert."<br>";
}
echo $html;
}
// download
else{
//$lib->dl($lib->code2str($_REQUEST['p']));
echo file_get_contents("convert.html");
}
exit();
lib.php
ダウンロードやURLエンコードなどの処理のライブラリ。
<?php
class LIB{
//DownLoad
function dl($path){
//ファイルが存在しない場合
if(!file_exists($path)){
if($_REQUEST['debug']){
echo $path;
}
else{
echo "not-dir:".$path;
}
return;
}
//ファイル名を取得
$file=basename($path);
//DL用ヘッダ
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.$file);
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . filesize($path));
readfile($path);
}
// [Encode] String -> Code
function str2code($str){
unset($data);
for($i=0;$i<strlen($str);$i++){
$data[] = sprintf("%03d",ord(substr($str,$i,1)));
}
return join("",$data);
}
// [Decode] Code -> String
function code2str($code){
//3の倍数チェック
if(strlen($code)%3){echo "no-match-code";return;}
unset($strs);
for($i=0;$i<strlen($code)/3;$i++){
$strs[] = chr(substr($code,$i*3,3));
}
return join("",$strs);
}
// Full-path
function path2query($path){
$code = $this->str2code($path);
return $code;
}
}
libUrl.php
PHPはjavascriptと違って、自分のURLを取得するのが関数一発では難しいので(旧バージョンでは)URL取得するライブラリを付けます。
<?php
class libUrl{
//port + domain [http://hoge.com:8800/]
//現在のポートの取得(80 , 443 , その他)
function getSite(){
//通常のhttp処理
if($_SERVER['SERVER_PORT']==80){
$site = 'http://'.$_SERVER['SERVER_NAME'];
}
//httpsページ処理
else if($_SERVER['SERVER_PORT']==443){
$site = 'https://'.$_SERVER['SERVER_NAME'];
}
//その他ペート処理
else{
$site = 'http://'.$_SERVER['SERVER_NAME'].':'.$_SERVER['SERVER_PORT'];
}
return $site;
}
//現在ページのサービスroot階層のパスを返す
function getDir(){
$uri = $this->getSite();
$req = explode('?',$_SERVER['REQUEST_URI']);
return $uri.dirname($req[0]." ")."/";
}
//現在のクエリ無しパスを返す
function getUrl(){
$uri = $this->getSite();
$req = explode('?',$_SERVER['REQUEST_URI']);
$uri.= $req[0];
return $uri;
}
//フルパスを返す
function getUri(){
$uri = $this->getSite();
if($_SERVER['REQUEST_URI']){
$uri.= $_SERVER['REQUEST_URI'];
}
else{
$uri = $this->getUrl.(($_SERVER['QUERY_STRING'])?"?".$_SERVER['QUERY_STRING']:"");
}
return $uri;
}
//基本ドメインを返す
function getDomain(){
return $_SERVER['SERVER_NAME'];
}
//リダイレクト処理
function setUrl($url){
if(!$url){return;}
header("Location: ".$url);
}
}
convert.html
表示用HTMLファイル。URLをコンバートするソースを記述。※デザインは一切入れていないので、気になる人はCSSを足してください。
<!DOCTYPE html>
<html>
<head>
<title>DownLoadLink</title>
</head>
<body>
<form method="post" action="index.php">
<input type="hidden" name="mode" value="converts">
<div>ダウンロードするファイルをサーバー内のFullPathで入力してください。</div>
<!--input type="text" name="path" value=""-->
<div><textarea name="path"></textarea></div>
<div><input type="submit" value="Convert"></div>
</form>
</body>
</html>
使い方
1.ページにアクセス
2.サーバー内のフルパスを記入
※複数ある場合は、改行で書き込んでください。
※入力欄が狭い場合は、カーソルで拡大できます。
3.convertボタンを押す
以下の文字列が表示されます。
http://192.168.33.10/labo/downloadLink/index.php?mode=dl&path=047104111109101047116101115116047097097097
http://192.168.33.10/labo/downloadLink/index.php?mode=dl&path=047104111109101047116101115116047098098098
4.ダウンロードテスト
上記で表示されたURLをひとつずつブラウザのアドレスに入力すると、階層が間違っていないければ、ダウンロードが開始されます。
注意
容量の大きいファイルを扱う時は、PHPでreadしているので、一度メモリに格納されてしまうので、非力なサーバーの場合は、ファイル上限値を指定する必要があります。
※現段階では、無制限なので、サーバーダウンする可能性があります。
今後
ダウンロードする際にロギングして、ダウンロードされたログ管理をしたり、DL数など計測を行なってサービス化してもいいかもしれません。
また、ユーザー登録させて、ユーザー権限に応じたダウンロードを振り分けたり、サーバーのディレクトリの内部リストをエンコードURLで表示できたりしてもいいかもしれません。
0 件のコメント:
コメントを投稿