View file download.php

File size: 7.5Kb
<?php
/*
Утилита отдачи файлов
Автор: Denvas
Функционал:
1. Скачивание файлов только определенного расширения
2. Защита от скачивания файлов из "неправильных" папок
3. Поддержка докачки не учитывая поддерживает это apache или нет
4. В случае неразрешенных расширений, неправильных путей или ошибок чтения выставляет 404 ошибку (страница не найдена)
5. Запрос так download.php или если стоит модреврайт то просто файл.
6. В jad файлах меняет пути
*/
//==================================================//
/*
Настройки
*/
    include_once("config.php");
    include_once("session.php");
    include_once("function.php");
    include_once("shop.php");

    //==================================================//
    /*
    Выставление заголовокв
    */
    function FileHeader($filename){
        global $download_type;
        $path_parts=pathinfo($filename);
        $ext=strtolower($path_parts["extension"]);
        $contenttype="application/octet-stream";
        if(isset($download_type[$ext]))$contenttype=$download_type[$ext];
        //отдача заголовоков
        header("Content-type: ".$contenttype);
        header("Content-Disposition: attachment;  filename=".$path_parts["basename"]);
    }
    //==================================================//
    /*
    Скачивание jad файла
    */
    function FileDownloadJAD($localfile,$filename){
        $content=file($localfile);
        $nline=count($content);
        for($j=0;$j<$nline;$j++){
            $line=strtolower($content[$j]);
            if(strpos($line,"midlet-jar-url")===0){
                $content[$j]="MIDlet-Jar-URL: http://".@$_SERVER['HTTP_HOST'].strtr($_SERVER["REQUEST_URI"],array(".jad"=>".jar"))."\r\n";
            };
        };
        $content=join("",$content);
        FileHeader($filename);
        FileDownloadFile("",$content);
        return 1;
    }
    //==================================================//
    /*
    Скачивание файла с поддержкой докачки
    */
    function FileDownloadFile($localfile="",$content=""){

        if($localfile)$attach_size=filesize($localfile); else $attach_size=strlen($content);
        @set_time_limit(0);//выполнять без ограничений
        
        $headers = getallheaders();
        $start=-1;$size=0;
        if(isset($headers['Range'])){//определение откуда стартовать
            $str=$headers['Range'];
            if(strstr($str,"bytes=")){
                $str=substr($str,6);
                $elem=explode('-',$str);
                $start=$elem[0];
                if(!empty($elem[1]))$size=$elem[1];
            };//if(strstr($str,"bytes="))
        };//if(isset($headers['Range']))
        
        if(($start>=0)&&($start<$attach_size)&&($start+$size<$attach_size)){
            if($size<=0)$size=$attach_size-$start;
            header("Accept-Ranges: bytes");
            header("Content-Range: bytes ".$start."-".($attach_size-1)."/".$attach_size); 
        }
        else{
            header("Accept-Ranges: bytes");
            $size=$attach_size;
        };

        header("Content-Length: ".$size);
        header("Cache-Control: none" );
        header("Connection: close");

        if($localfile){//из файла
            $attach_size=filesize($localfile);
            $fd=@fopen($localfile, "rb");
            if($start>0)fseek($fd, $start);
            fpassthru($fd);
            fclose($fd);
        }
        else{//данные
            if($start>0)print substr($content,$start); else print $content;
        };
        return 0;
    }//function DownloadFile
    //==================================================//
    /*
    Отдать файл на скачивание
    */
    function FileDownload($localfile,$filename){
        if(!file_exists($localfile))return -1;
        $path_parts=pathinfo($filename);
        $ext=strtolower($path_parts["extension"]);

        //особый случай. JAD файл. В нем нужно изменить данные.
        if(strcmp($ext,"jad")==0)return FileDownloadJAD($localfile,$filename);

        //обычный файл, его править не нужно
        FileHeader($filename);
        return FileDownloadFile($localfile);
    }
//==================================================//
/*
Отдать файл $name с позиции $start размером $size
*/
/*
function get_file($name,$start=-1,$size=0){
    global $download_log,$path_download,$download_type;
    $downpath=$path_download.$name;
    //проверка на существование фала
    if(!file_exists($downpath))return -1;
    //взятие расширения файла
    $path_parts=pathinfo($downpath);
    $ext=strtolower($path_parts["extension"]);
    if(!isset($download_type[$ext]))return -2;
    //чтение и отдача файла с заголовками
    if(!($fd=fopen($downpath,"rb")))return -3;
    $attach_size=filesize($downpath);
    if(($start>=0)&&($start<$attach_size)&&($start+$size<$attach_size)){
        if($size<=0)$size=$attach_size-$start;
        header("Accept-Ranges: bytes");
        header("Content-Range: bytes ".$start."-".($attach_size-1)."/".$attach_size); 
    }
    else{
        Header("Accept-Ranges: bytes");
        $size=$attach_size;
    };
    fseek($fd, $start);
    header("Cache-Control: none" );
    header("Content-type: ".$download_type[$ext]);
    header("Content-Disposition: attachment;  filename=".$path_parts["basename"]);
    header("Content-Length: ".$size);
    header("Connection: close");
    fpassthru($fd);
    fclose($fd);
    return 1;
};//function get_file($name)
*/
//==================================================//
    $filename=basename($_SERVER["PHP_SELF"]);    
    $download_log=$path_log."/download.log";

    if(strcmp($filename,"download.php")==0){
        if(empty($_SERVER['PATH_INFO']))NotFound();
        $name=$_SERVER['PATH_INFO'];
    }
    else{
        $name="/".$filename;
    };
    //выполнять без ограничений
    @set_time_limit(0);
    //взятие имени файла
    //защита от выхода на уровень вверх (чтоб с сайта ни чего не утащили)
    $name=preg_replace("/\.\.+/",".",$name);
    /*
    //Взять из заголовка Range-Unit: $start | $size
    $headers = getallheaders();
    $start=-1;$size=0;
    if(isset($headers['Range'])){//определение откуда стартовать
        $str=$headers['Range'];
        if(strstr($str,"bytes=")){
            $str=substr($str,6);
            $elem=explode('-',$str);
            $start=$elem[0];
            if(!empty($elem[1]))$size=$elem[1];
        };
    };
    */
    $shop=GetProduct(isset($_GET["cat"])?(int)$_GET["cat"]:"");$flag=-1;
    for($j=0;$j<count($shop);$j++){
        for($i=0;$i<count($shop[$j]["file"]);$i++){
            if(strcmp("/".$shop[$j]["file"][$i],$name)==0){$flag=$j;break;};
        };
        if($flag>=0)break;
    };

    if($flag<0)NotFound();
    
    if($shop[$flag]["price"]>0){
        if(isset($_REQUEST["ses"])){
            $session=strtr($_REQUEST["ses"],array("."=>"","/"=>"","\\"=>"","'"=>"","\""=>""));
            $ses=GetSession($session,-$shop[$flag]["price"],$shop[$flag]);
            if(!is_array($ses))NotFound();
        }
        else NotFound();
    };//if($shop[$flag]["price"]>0)

    //отдать файл
    $res=FileDownload($path_download."/".$name,$name);
    if($res<0)NotFound();

    //записать лог, если задано название
    if($download_log){
        $str=$name."|".$res;
        if(isset($headers['Range']))$str.="|Range:".$headers['Range'];
        $fd=fopen($download_log,"ab");
        if($fd){
            flock($fd,LOCK_EX);
            fwrite($fd,$str."\n");
            fclose($fd);
        };
    };//if($download_log)

?>