Dave Jarvis' Repositories

git clone https://repo.autonoma.ca/repo/keenwrite.git

Honours HTTP HEAD requests

AuthorDaveJarvis <email>
Date2023-11-11 12:25:39 GMT-0800
Commit2cf02c3710214f393b1b42ba0d8361fbca4b7390
Parentfc107ca
Delta54 lines added, 67 lines removed, 13-line decrease
www/downloads/counter.php
/**
- * Isolate the file name being downloaded.
+ * Normalize the file name being downloaded.
*
- * @param array $fileinfo The result from calling pathinfo.
+ * @param string $path The path to the file.
*
* @return string The normalized file name.
*/
- function normalize_filename( $fileinfo ) {
+ function normalize_filename( $path ) {
+ $fileinfo = pathinfo( $path );
$basename = $fileinfo[ 'basename' ];
/**
- * Determine the content type based on the file name extension, rather
- * than the file contents. This could be inaccurate, but we'll trust that
- * the website administrator is posting files whose content reflects the
- * file name extension.
- * <p>
- * If the file name extension is not known, the content type will force
- * the download (to prevent the browser from trying to play the content
- * directly).
+ * Downloads a file, allowing for resuming partial downloads.
*
- * @param array $fileinfo The result from calling pathinfo.
+ * @param string $path Fully qualified path of a file to download.
*
- * @return string The IANA-defined Media Type for the file name extension.
+ * @return bool True if the file was transferred.
*/
- function get_content_type( $fileinfo ) {
- $extension = strtolower( $fileinfo[ 'extension' ] );
+ function transmit( $path, $seek_start, $size ) {
+ if( ob_get_level() == 0 ) {
+ ob_start();
+ }
- switch( $extension ) {
- case 'app': $ctype='application/octet-stream'; break;
- case 'bin': $ctype='application/octet-stream'; break;
- case 'exe': $ctype='application/octet-stream'; break;
- case 'jar': $ctype='application/octet-stream'; break;
- case 'zip': $ctype='application/zip'; break;
- case 'avi': $ctype='video/msvideo'; break;
- case 'mp3': $ctype='audio/mpeg'; break;
- case 'mpg': $ctype='video/mpeg'; break;
- case 'mpv': $ctype='video/mpv'; break;
- case 'webm': $ctype='video/webm'; break;
- default: $ctype='application/force-download'; break;
+ // If the file doesn't exist, don't count it as a download.
+ $bytes_sent = -1;
+
+ // Open the file to be downloaded.
+ $fp = @fopen( $path, 'rb' );
+
+ if( $fp !== false ) {
+ @fseek( $fp, $seek_start );
+
+ $aborted = false;
+ $bytes_sent = $seek_start;
+ $chunk_size = 1024 * 16;
+
+ while( !feof( $fp ) && !$aborted ) {
+ print( @fread( $fp, $chunk_size ) );
+ $bytes_sent += $chunk_size;
+
+ if( ob_get_level() > 0 ) {
+ ob_flush();
+ }
+
+ flush();
+
+ $aborted = connection_aborted() || connection_status() != 0;
+ }
+
+ if( ob_get_level() > 0 ) {
+ ob_end_flush();
+ }
+
+ fclose( $fp );
}
- return $ctype;
+ // Download succeeded if the total bytes matches or exceeds the file size.
+ return $bytes_sent >= $size;
}
/**
* Downloads a file, allowing for resuming partial downloads.
*
* @param string $path Fully qualified path of a file to download.
*
- * @return bool True if the download succeeded.
+ * @return bool True if the file was transferred.
*/
function download( $path ) {
// Don't cache the file stats result.
clearstatcache();
$size = @filesize( $path );
$size = $size === false || empty( $size ) ? 0 : $size;
- $fileinfo = pathinfo( $path );
- $filename = normalize_filename( $fileinfo );
- $content_type = get_content_type( $fileinfo );
+ $filename = normalize_filename( $path );
+ $content_type = mime_content_type( $filename );
$range = "0-$size";
: max( abs( $seek_start + 0 ), 0 );
+ header_remove( 'x-powered-by' );
header( 'Pragma: public' );
header( 'Expires: -1' );
header( 'Cache-Control: public, must-revalidate, post-check=0, pre-check=0' );
+ header( 'Cache-Control: private', false );
header( "Content-Disposition: attachment; filename=\"$filename\"" );
+ header( 'Content-Transfer-Encoding: binary' );
$content_length = $size;
header( "Content-Length: $content_length" );
header( "Content-Type: $content_type" );
-
- // If the file doesn't exist, don't count it as a download.
- $bytes_sent = -1;
-
- // Open the file to be downloaded.
- $fp = @fopen( $path, 'rb' );
-
- if( $fp !== false ) {
- @fseek( $fp, $seek_start );
-
- $aborted = false;
- $bytes_sent = $seek_start;
- $chunk_size = 1024 * 16;
-
- while( !feof( $fp ) && !$aborted ) {
- print( @fread( $fp, $chunk_size ) );
- $bytes_sent += $chunk_size;
-
- if( ob_get_level() > 0 ) {
- ob_flush();
- }
-
- flush();
-
- $aborted = connection_aborted() || connection_status() != 0;
- }
-
- if( ob_get_level() > 0 ) {
- ob_end_flush();
- }
-
- fclose( $fp );
- }
- // Download succeeded if the total bytes matches or exceeds the file size.
- return $bytes_sent >= $size;
+ // Respond to HTTP HEAD requests.
+ return $_SERVER['REQUEST_METHOD'] === 'HEAD'
+ ? false
+ : transmit( $path, $seek_start, $size );
}