<?php

###############################################################
# File Download 1.3
###############################################################
# Visit http://www.zubrag.com/scripts/ for updates
###############################################################
# Sample call:
#    download.php?f=phptutorial.zip
#
# Sample call (browser will try to save with new file name):
#    download.php?f=phptutorial.zip&fc=php123tutorial.zip
###############################################################

// Allow direct file download (hotlinking)?
// Empty - allow hotlinking
// If set to nonempty value (Example: example.com) will only allow downloads when referrer contains this text
define('ALLOWED_REFERRER', '');

// Root folder where log files are kept, and in whose subfolders files for downloading are kept
// MUST end with slash (i.e. "/")
define('DOWNLOAD_DIR','/afs/csail.mit.edu/proj/jwi/www/download/');

// log downloads?  true/false
define('LOG_DOWNLOADS',true);

// log file name
define('LOG_FILE_NAME','jwi.log');

// Allowed extensions list in format 'extension' => 'mime type'
// If mime type is set to empty string then script will try to detect mime type 
// itself, which would only work if you have Mimetype or Fileinfo extensions
// installed on server.
$allowed_ext = array (
  'zip' => 'application/zip',
  'pdf' => 'application/pdf',
  'jar' => 'application/java-archive',
);

####################################################################
###  DO NOT CHANGE BELOW
####################################################################

// If hotlinking not allowed then make hackers think there are some server problems
if (ALLOWED_REFERRER !== ''
&& (!isset($_SERVER['HTTP_REFERER']) || strpos(strtoupper($_SERVER['HTTP_REFERER']),strtoupper(ALLOWED_REFERRER)) === false)
) {
  die("Internal server error. Please contact system administrator.");
}

// Make sure program execution doesn't time out
// Set maximum script execution time in seconds (0 means no limit)
set_time_limit(0);

if (!isset($_GET['f']) || empty($_GET['f'])) {
  die("Please specify file name for download.");
}

// Get real file name.
// Remove any path info to avoid hacking by adding relative path, etc.
$fname = basename($_GET['f']);

// find the target file in one of the download directory's subfolders
function find_file ($target_name, &$target_dir, &$target_file) {
  
  // open the download directory
  $dir = opendir(DOWNLOAD_DIR);

  // loop over all subdirectories
  while ($child = readdir($dir)) {

    // skip non-directories, this dir, and parent dir markers
    if (!is_dir(DOWNLOAD_DIR.'/'.$child) || $child == '.' || $child == '..') continue;
    
    if (file_exists(DOWNLOAD_DIR.$child.'/'.$target_name)) {
         $target_file = DOWNLOAD_DIR.$child.'/'.$target_name;
         $target_dir = $child;
         return;
    } 
  }

} // find_file

// holds the full path to the file to be downloaded
$target_file = '';

// holds the name of the directory in which the file to be download resides
$target_dir = '';

// find the appropriate file
find_file($fname, $target_dir, $target_file);

if (!is_file($target_file)) {
  die("File does not exist. Make sure you specified the correct file name."); 
}

// file size in bytes
$fsize = filesize($target_file); 

// file extension
$fext = strtolower(substr(strrchr($fname,"."),1));

// check if allowed extension
if (!array_key_exists($fext, $allowed_ext)) {
  die("Not allowed file type."); 
}

// get mime type
if ($allowed_ext[$fext] == '') {
  $mtype = '';
  // mime type is not set, get from server settings
  if (function_exists('mime_content_type')) {
    $mtype = mime_content_type($target_file);
  }
  else if (function_exists('finfo_file')) {
    $finfo = finfo_open(FILEINFO_MIME); // return mime type
    $mtype = finfo_file($finfo, $target_file);
    finfo_close($finfo);  
  }
  if ($mtype == '') {
    $mtype = "application/force-download";
  }
}
else {
  // get mime type defined by admin
  $mtype = $allowed_ext[$fext];
}

// Browser will try to save file with this filename, regardless original filename.
// You can override it if needed.

if (!isset($_GET['fc']) || empty($_GET['fc'])) {
  $asfname = $fname;
} else {
  // remove some bad chars
  $asfname = str_replace(array('"',"'",'\\','/'), '', $_GET['fc']);
  if ($asfname === '') $asfname = 'NoName';
}

// Make sure that we are only fixing file name problems for IE
if ( isset($_SERVER['HTTP_USER_AGENT']) && strstr($_SERVER['HTTP_USER_AGENT'], "MSIE") ){
  $asfname = preg_replace('/\./', '%2e', $asfname, substr_count($asfname,'.')-1);
}

// set headers
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-Type: $mtype");
header("Content-Disposition: attachment; filename=\"$asfname\"");
header("Content-Transfer-Encoding: binary");
header("Content-Length: " . $fsize);

// download @readfile($target_file);
$file = @fopen($target_file,"rb");
if ($file) {
  while(!feof($file)) {
    print(fread($file, 1024*8));
    flush();
    if (connection_status()!=0) {
      @fclose($file);
      die();
    }
  }
  @fclose($file);
}

// log downloads
if (!LOG_DOWNLOADS) die();

$log_file = DOWNLOAD_DIR.LOG_FILE_NAME;
$f = @fopen($log_file, 'a+');
if ($f) {
  echo("writing...<br/>");
 $ip = $_SERVER['REMOTE_ADDR'];
 $hostname = strtolower(gethostbyaddr($ip));
 if($hostname == $ip) $hostname = ""; 
 @fputs($f, date("m.d.Y g:ia")."  ".$ip."  ".$fname."  ".$hostname."\n");
 @fclose($f);
} else {
  echo("problem writing<br/>");
}

?>
