Recent Topics

1 Jul 22, 2007 17:20    

I've made a download script that zips up a ... well it's easier to explain in a example.

So "domain.com/b2evo/skins/download/tictac.zip" will look for "domain.com/b2evo/skins/tictac/" and if it exists zip it up, and download it. There is protection in it to stop people accessing dirs/files higher than the initial parent directory. And it works even without the PHP Zip extension installed.

If you do not have .htaccess abilities then you will need to use "domain.com/b2evo/skins/download/download.php?download=tictac" instead.

So you can see that it stops the need to make official releases all the time, the user can just grab the latest and greatest directly from your website, so it's a "See it in action, and download the same code!".

Anyway, to install make the folder "download" where you want to offer these abilities, so for example the skins and plugins folders. Give the folder 777 permission. And add these two files into it:

download.php

<?php

function become_file_download ( $file_path, $content_type = NULL, $buffer_size = 20000 )
{	// Credits go out to; pechkin at zeos dot net - http://au3.php.net/manual/en/function.header.php#65667
	// Modified into function by balupton
	// A shitload of upgrade to this done by balupton
	
	if ( empty($content_type) )
		$content_type = 'application/force-download';
	
	// Define variables
	$fpath = $file_path;
	$fname = basename($file_path);
	$fsize = filesize($fpath);
	$bufsize = $buffer_size;
	
	if ( isset($_SERVER['HTTP_RANGE']) )
	{	// Partial download
		if( preg_match("/^bytes=(\\d+)-(\\d*)$/", $_SERVER['HTTP_RANGE'], $matches) )
		{	// Parsing Range header
			$from = $matches[1];
			$to = $matches[2];
			
			if( empty($to) )
			{
				$to = $fsize - 1;  // -1  because end byte is included
				//(From HTTP protocol:
				// 'The last-byte-pos value gives the byte-offset of the last byte in the range; that is, the byte positions specified are inclusive')
			}
			
			$content_size = $to - $from + 1;
			
			header("HTTP/1.1 206 Partial Content");
			header('Pragma: public');
			header('Cache-control: must-revalidate, post-check=0, pre-check=0');
			header('Expires: ' . gmdate('D, d M Y H:i:s') . ' GMT');
			header("Content-Range: $from-$to/$fsize");
			header("Content-Length: $content_size");
			header("Content-Type: $content_type");
			if ( $content_type == 'application/force-download' )
				header("Content-Disposition: attachment; filename=$fname");
			header("Content-Transfer-Encoding: binary");
	
		   if(file_exists($fpath) && $fh = fopen($fpath, "rb"))
		   {
			   fseek($fh, $from);
			   $cur_pos = ftell($fh);
			   while($cur_pos !== FALSE && ftell($fh) + $bufsize < $to+1)
			   {
				   $buffer = fread($fh, $bufsize);
				   print $buffer;
				   $cur_pos = ftell($fh);
			   }
	
			   $buffer = fread($fh, $to+1 - $cur_pos);
			   print $buffer;
	
			   fclose($fh);
		   }
		   else
		   {
			   header("HTTP/1.1 404 Not Found");
			   exit;
		   }
	   }
	   else
	   {
		   header("HTTP/1.1 500 Internal Server Error");
		   exit;
	   }
	}
	else // Usual download
	{
		// die ( $fpath.':::'.$fsize);
		header("HTTP/1.1 200 OK");
		header('Pragma: public');
		header('Cache-control: must-revalidate, post-check=0, pre-check=0');
		header('Expires: ' . gmdate('D, d M Y H:i:s') . ' GMT');
		header("Content-Length: $fsize");
		header("Content-Type: $content_type");
		if ( $content_type == 'application/force-download' )
		  header("Content-Disposition: attachment; filename=$fname");
		header("Content-Transfer-Encoding: binary");
		if( file_exists($fpath) ) 
		{
			readfile($fpath);
		}
		else
		{
		   header("HTTP/1.1 404 Not Found");
		}
	}
}

function make_archive( $dir , & $zip, $extdir = '' )
{	// Taken from http://au3.php.net/manual/en/ref.zip.php#65998
	// credits to hostingfanatic dot com
	if ( is_dir($dir) )
	if ( $dh = opendir($dir) )
	{
		while ( ($file = readdir($dh)) !== false )
		{
			if( $file != '.' && $file != '..' )
			{
				if( is_dir( $dir . $file ) )
				{
					$zip->addFile($dir.$file,$extdir.$file);
					make_archive($dir.$file.'/' , $zip, $extdir.$file.'/');
	
				}
				else
				{
					$zip->addFile($dir.$file,$extdir.$file);                                                        
				}
			}
		}
		closedir($dh);
	}
	return true;
}


# ---------------------------------
# Perform the script
# Created by balupton

# Prepare variables
if ( !isset($_GET['download']) )
	exit('no download');
$download = $_GET['download'];

$this_dir_path = dirname(__FILE__);
$this_dir_path = realpath($this_dir_path);

$parent_dir_path = $this_dir_path.'/../';
$parent_dir_path = realpath($parent_dir_path);

$dir_path = $parent_dir_path.'/'.$download;
$dir_path = realpath($dir_path);

if ( $this_dir_path && $parent_dir_path && $dir_path )
{	/* good */	}
else
	exit('something went wrong...');

if ( substr($dir_path, 0, strlen($parent_dir_path)) === $parent_dir_path )
{	/* good */	}
else
	exit('stop hacking '."[$dir_path][$parent_dir_path]");

$file_path = $this_dir_path.'/'.$download.'.zip';

# Prepare Directory
// chmod(dirname(__FILE__), 0777);

# Remove old file
if ( is_file($file_path) )
	unlink($file_path);

# Use Zip Library
if ( class_exists('ZipArchive') )
{
	# Create Zip
	$zip = new ZipArchive();
		
	# Create Zip File
	/*if ( function_exists('zip_open') )
	{
		$zip = zip_open($file_path);
		if ( !$zip )
			  exit("cannot open <$filename>\n");
	}
	else*/if ( $zip->open($file_path, ZIPARCHIVE::CREATE) !== TRUE )
		exit("cannot open <$filename>\n");
	
	# Add folder to Zip
	make_archive($dir_path, $zip);
	
	# Close Zip File
	/*if ( function_exists('zip_close') )
		zip_close($zip);
	else*/
		$zip->close();
}
else
{	// Use perl
	chdir($parent_dir_path);
	`zip -rq $file_path $download`;
	chdir($this_dir_path);
}

# Download
become_file_download($file_path, 'archive/zip');
die;

?>


.htaccess

# Settings
RewriteEngine On
Options +FollowSymlinks -Indexes

# Rule
# RewriteCond %{REQUEST_URI} !-f
RewriteCond %{REQUEST_URI} \.zip$ [NC]
RewriteRule ^([a-z0-9_\%]+)\.zip$ download.php?download=$1 [L]

And your all set :)


Form is loading...