Track downloads with PHP?

Miscellaneous Forums/General Discussion/Track downloads with PHP?

The forum is locked. These are the original blitzbasic.com forums, kept so they can still be read. No new topics, replies or edits can be made here. To join in, head over to the Blitz3D+ forums.

Ok, I can't post the entire thing, but here's a download script that I wrote for a project a few months ago.

<?php
require_once("resources/includes/init.php");

if (isset($_GET['id'])){
	if ($_GET['id'] != ""){
		$id = HZ_Taint($_GET['id']);
		$file = HZ_SelectFromTable("HZ_FileList", "WHERE file_id = '".$id."'");
		
		if (!PEAR::isError($file)){
			if (count($file) > 0){
				if (count($file) > 1){//if we have more than one file with exactly the same name (should never happen)
					header('Content-Type: text/plain');
					echo "Error, file naming conflict, please contact admin with this error message and the file name you requested (".$name.")";
					exit;
				} else {
					$file = $file[0];//reassign the first object in the returned array to $file since there is only one file
					//if it really is a regular file
					if (is_file($file->path)){
						//if the requested file's path is not outside the base directory we set in config
						if (substr(realpath($file->path), 0, strlen(BASE_FILE_UPLOAD_DIR)) == BASE_FILE_UPLOAD_DIR){
							$file_data = file_get_contents($file->path);
							$finfo = finfo_open(FILEINFO_MIME);
							$finfo_mime = finfo_file($finfo, $file->path);
							//the following headers ensure that the browser is forced to download the file, it should work on all major bowsers
							header('Pragma: public');
							header('Last-Modified: '.gmdate('D, d M Y H:i:s') . ' GMT');
							header('Cache-Control: no-store, no-cache, must-revalidate');
							header('Cache-Control: pre-check=0, post-check=0, max-age=0');
							header('Content-Transfer-Encoding: none');
							//This should work for IE & Opera
							header('Content-Type: '.$file->type.'; name="'.basename($file->name).'"');
							//This should work for the rest
							header('Content-Type: '.$file->type.'; name="'.basename($file->name).'"');
							header('Content-Disposition: attachment; filename="'.basename($file->name).'"');
							echo $file_data;
							exit;
						} //if substr
					}//if is_file
				}//if count == 1
			}//if count > 0
		}//if !PEAR::isError
	}//if name != ""
}//if isset(name)

header("Content-Type: text/plain");
echo "The file you requested cannnot be found";
exit;
?>


It uses PEAR::DB, db initialization is in the init.php, HZ_SelectFromTable is a wrapper for table access (handles errors and some other things and returns an array, by default it uses DB_FETCHMODE_OBJECT), HZ_Taint is essentially a wrapper for mysql_real_escape_string (plus a few other checks).

It relies on the file info (NOT the file data) previously being inserted into the database with paths.

It wouldn't take much to add a bit of code to track downloads to it.