Troubles with file protector server - readfile();
I wrote the following script to avoid exposing the protected files to users logged in my web application.
This works well with small files... but on some platforms, such as iPad, Android, Internet Explorer and sometimes Safari I get sometimes (about 50% times) file served partially... like as a connection stop in the middle of the trasfer.
I'm running Apache2.2/PHP 5.3 on Ubuntu Server 10.04.
Can anyone suggest how to improve it? Thanks.
<?php
// my bootstrap with env vars
// some includes ..
if(! @constant('APP_BASE_PATH') ) { header('HTTP/1.1 502 Bad Gateway'); die(''); }
// allowed types
$allowed_types = array( 'application/pdf', 'image/png', 'image/jpeg' );
// my custom function to check login
if( isUserLogged($_SESSION) )
{
// if file exist
if(! is_file( $file ) )
{ header('HTTP/1.1 400 Bad Request'); die('unable to find target file'); }
// if is permitted
$type = exec('file -bi ' . escapeshellarg($file) );
if(! in_array( $type, $allowed_types ) )
{ header('HTTP/1.1 400 Bad Request'); die(''); }
// lenght calc
$content_lenght = intval( sprintf( "%u", filesize( $file ) ) );
// last modify
$last_modified = gmdate('D, d M Y H:i:s', filemtime( $file ) ) . ' GMT';
// generating l'etags
$stat = stat($file);
$etag = sprintf( '"%x-%x-%s"' , $stat['ino'] , $stat['size'] , base_convert( str_pad( $stat['mtime'], 16, '0' ) , 10 , 16 ) );
// disable gzip compression
@apache_setenv ( 'no-gzip', 1 );
@ini_set ( 'zlib.output_compression', 0 );
ini_set( 'display_error', 0);
header ( 'HTTP/1.1 200 OK' );
header ( 'Content-Type: ' . $type );
开发者_高级运维 header ( 'Content-Length: ' . $content_lenght );
header ( 'Etag: ' . $etag );
header ( 'Last-Modified: ' . $last_modified );
// if that's a PDF, try to force
if( strpos($type, 'application/pdf') !== FALSE ) {
header ( 'Content-Description: File Transfer' );
header ( 'Content-disposition: attachment; filename=' . basename ( $file ) );
header ( 'Content-Transfer-Encoding: binary');
}
// serve file
readfile ( $file );
} else {
header('HTTP/1.1 401 Unauthorized');
}
Theres a problem with this line:
$type = exec('file -bi ' . escapeshellarg($file) );
On an Ubuntu 9.10 server, the return value of the shell command is:
image/jpeg; charset=binary
So your check should fail always. You need to change the command to:
$type = exec('file --mime-type -b ' . escapeshellarg($file) );
Which should give you:
image/jpeg
Also, its best to test your API calls via curl instead of a browser.
精彩评论