开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜