Location: PHPKode > projects > PhpProjectMaster > www/php/att.php
<?php
/* 
 Attachment preview/download
 (c) 2004-2007 by "Oleg Savchuk" <hide@address.com>

 part of phpProjectMaster project
 http://phpprojmaster.sourceforge.net

 The contents of this file are subject to the GNU GENERAL PUBLIC LICENSE
 http://www.gnu.org/copyleft/gpl.html

*/

 session_cache_limiter('public');  //to prevent 'nocache' header (we really need cache here!)
 session_start();
 require_once "../inc/sitelib.php" ;
 require_once "../inc/form_utils.php" ;
 require_once "../inc/att.lib.php" ;

 global_init();

//********* variables
 $item_id       = $_REQUEST['id']+0;
# $is_preview    = $_REQUEST['ispreview']+0;
# if (!$is_preview) $is_preview='';

 $is_save       = $_REQUEST['download']+0;
 if (!$is_save) $is_save='';

 $CHUNK_SIZE=128*1024; #128Kb blocks


 if ( check_access_att($item_id)<10 ){
    return_forbidden();
 };

//********* action!
 $CGI_ACTIONS=array(
  ''           => 'get_att_file',
 );

 go_action();

 exit;

//***************************
function return_empty(){
 header($_SERVER["SERVER_PROTOCOL"].' 404 Not Found'); 
 print "404 Not Found";
 exit(); 
}

//***************************
function return_forbidden(){
 header($_SERVER["SERVER_PROTOCOL"].' 403 Forbidden'); 
 print "403 Forbidden";
 exit(); 
}


//************* 
function get_att_file(){
 global $item_id, $is_preview, $att_vars, $u_id;

 //check access to the post of the attachment
 $hATT=get_att($item_id);

 $path=get_upload_path($item_id, $att_vars['upload_path'], ($is_preview)?'_s':'', $hATT['ext']);
# echo "$item_id ".$att_vars['upload_path']." $is_preview ".$hATT['ext']." [$path]";
# exit;
 if (!$path){
    return return_empty();
 }

 $mime='application/octet-stream';
 if ($hATT['ext']=='gif') $mime='image/gif';
 if ($hATT['ext']=='jpg') $mime='image/jpeg';
 if ($hATT['ext']=='png') $mime='image/x-png';

 $fname=$hATT['iname'];
 if (!preg_match("/\..{1,4}$/", $fname)) $fname.=".".$hATT['ext'];  //add extension

 return_file($path, $mime, $fname);
}

//************ return file via HTTP
function return_file($path, $mime_type='application/octet-stream', $fname='file.ext'){
 global $is_save, $CHUNK_SIZE;

 $ims=$_SERVER['HTTP_IF_MODIFIED_SINCE'];
 $lastModified=filemtime($path);

 header("Content-type: $mime_type");
 header("Last-Modified: ".gmdate('D, d M Y H:i:s', $lastModified).' GMT');
 header("Accept-Ranges: bytes");

 if (strlen($ims)) { 
    //  §¤¥«ï¥¬ If-Modified-Since (Netscape < v6 ®â¤ ñâ ¨å ­¥¯à ¢¨«ì­®) 
    $modifiedSince = explode(';', $ims); 
 
    // à¥®¡à §ã¥¬ § ¯à®á ª«¨¥­â  If-Modified-Since ¢ â ©¬èâ ¬¯
    $modifiedSince = strtotime($modifiedSince[0]); 
 } else { 
    // “áâ ­ ¢«¨¢ ¥¬ ¢à¥¬ï ¬®¤¨ä¨ª æ¨¨ ¢ ­®«ì
    $modifiedSince = 0; 
 } 
 
 // ‘à ¢­¨¢ ¥¬ ¢à¥¬ï ¯®á«¥¤­¥© ¬®¤¨ä¨ª æ¨¨ ª®­â¥­â  á ªí襬 ª«¨¥­â 
 if ($lastModified <= $modifiedSince) { 
    //  §£à㦠¥¬ ª ­ « ¯¥à¥¤ ç¨ ¤ ­­ëå!
#    logger("CACHE HIT [$path]");
    header($_SERVER["SERVER_PROTOCOL"].' 304 Not Modified'); 
    exit(); 
 } 

# logger("CACHE MISS [$path]");

 //­ã   âãâ 㦠¢ë¤ ¥¬ ä ©« 楫¨ª®¬ (¨«¨ ç áâì) à § 㦠­  â® ¯®è«®
 $fsize=filesize($path);

 //check for Range
 if (isset($_SERVER['HTTP_RANGE'])) {
#    logger("RANGE REQUEST: $_SERVER[HTTP_RANGE]");
    $range=substr($_SERVER['HTTP_RANGE'], strpos($_SERVER['HTTP_RANGE'], '=')+1);
    $from=strtok($range, '-');
    $to=strtok('/');
    if ($from){
       if ($to){   // bytes=0-499   or =500-999 - everything ok, no change

       }else{      // bytes=0- or =500- or =9500-  need to calc $to - till the end of file
          $to=$fsize-1;
       }

    }else{
       if ($to){   // bytes=-500  - final 500 bytes - need to calc $from and recalc $to
          $from=$fsize-$to;
          $to=$fsize-1;
       }else{      // bytes=- illegal, assume return whole file
       }
    }
    //now we have real $from and $to, i.e. $from=500, $to=999 (absolute values, zero based)

    if ($from && $to){
       header($_SERVER["SERVER_PROTOCOL"].' 206 Partial Content');
       header("Content-Range: bytes $from-$to/$fsize");  // 0-499/1234  or 500-999/1234
#       logger("Content-Range: bytes $from-$to/$fsize");
    }
 };

 if ($from && $to){
    $cont_size=$to-$from+1;
 }else{
    $cont_size=$fsize;
 }
 header("Content-Length: $cont_size");
# logger("Content-Length: $cont_size");

 if ($is_save) header("Content-Disposition: attachment; filename=\"$fname\"");

 $fp = fopen($path, "rb");
 if ($from) fseek($fp, $from, SEEK_SET); //seek to range begin point

 if (!$to || $to+1>=$fsize){
    fpassthru($fp);  //whole or all rest file mode
#    logger('PASS THRU!');

 }else{
    $sent=0;
    while( !feof($fp) && !connection_status() && $sent<$cont_size ) {
         echo fread($fp, $CHUNK_SIZE);
         $sent+=$CHUNK_SIZE;
         flush();
#         logger('CHUNK SENT!');
         sleep(1);
    }
 }

 fclose ($fp);

}


?>
Return current item: PhpProjectMaster