Re: [PHP] Re: Strategy for Secure File Storage

2007-09-25 Thread Andrew Ballard
Kevin Murphy wrote:
  The problem is IE7. All browsers work with this code as is but IE  says
  Internet Explorer cannot download test.pdf from XXX

The problem with IE was when you told it not to cache the document. If
you just want the browser to download the file rather than let the
Adobe plug-in handle it, as it looks like you intend with the
Content-disposition set to attachment, you have to send just the right
headers to make IE happy. (I think Brian's example should do it.)
Otherwise, IE knows it can handle the document internally with a
plug-in and will still try to open the file anyway. For some reason
when IE tries to handle files like PDF, it downloads the file, saves
it to cache, and then tells the Adobe plug-in to open the file from
the cache. Since you've told IE not to cache the file, IE honors that
request -- it builds the cache filename (and may even save the file
before promptly deleting it) and then sends that file name to the
Adobe plug-in which then tries to open a file that does not exist in
your computer's local cache.

On 9/24/07, brian [EMAIL PROTECTED] wrote:
 echo 'Your software provider sucks eggs. Get a better browser.';

LOL. I love that approach, too. Unfortunately, it's not very practical. :-\

-- 
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php



[PHP] Re: Strategy for Secure File Storage

2007-09-25 Thread Colin Guthrie
Kevin Murphy wrote:
 $ext = explode(.,$file);
 
 $extension = $mimetypes[$ext[1]];

Other people have provided answers so I'll just make a quick comment on
this bit.

It's not ideal but if you only upload a subset of file types then I
guess it's OK.

Also if the file has more than a single dot in it (e.g. my.image.jpg)
which is perfectly valid, then $ext[1] will contain (image) which
isn't right.

If possible use e.g.
http://www.php.net/manual/en/function.mime-content-type.php or Example
606 here http://www.php.net/manual/en/function.finfo-file.php but these
may not be available on your PHP install.

You should probably check more thoroughly:

e.g.

$mimetype = 'application/octet-stream'; // default
$ext = array_pop($dummy = explode('.', $file));
if (!empty($mimetypes[$ext]))
  $mimetype = $mimetypes[$ext];

or something similar (not tested above!)


Hope this helps ya.

Col

-- 
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php



[PHP] Re: Strategy for Secure File Storage

2007-09-24 Thread Colin Guthrie
Kevin Murphy wrote:
 1) Write secure files to MySQL as a blob (only secure files would be
 written there)

Personally I don't like this strategy but it is always a hot topic on
this list. I don't mind storing a few small images in the db but when
you start to store 200-300Megs it just complicates your database backup
strategy. If you use snapshot-based filesystem level backups (e.g. using
LVM) then this is mitigated but still has many downsides IMO.

 3) Use Unix passwords to protect a folder in the web level and then the
 CMS knows the password and can pass the password for access (so that the
 user doesn't know this password, but the CMS does).

Nah... seems to complex.

 4) Some various forms of link obfuscation, where the CMS goes through
 all the secure files once an hour or so and rewrites the file name with
 a random string.

Still not 100% secure and overly complex IMO.

 2) Write secure files to the level below the web root and come up with a
 way of copying the files over to a temporary directory for access, then
 delete the files as soon as they are accessed.

 5) Or  I'm open to suggestions.

I think you are kind of on the right track with 2 but there is no need
to do this copying.

Simply put all requests for your file through a PHP script. This can be
done with PATH_INFO or mod-rewrite in Apache (just google this for examples.

You PHP script will then check the access credentials of the user (e.g.
a logged in Session) and then output relevent cache headers (again
google) before issuing a Content-Type header with the correct mime type
for the file in question along with the Content-Length header with the
physical size of the file (not strictly speaking necessary but nicer for
the client) before simply calling
include('/path/to/file/not/in/webroot.ext') to push the content to the
user.

Hope this helps.

Col

-- 
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP] Re: Strategy for Secure File Storage

2007-09-24 Thread Kevin Murphy
Ok, I'm almost there. I took what everyone said (and a few Google  
searches later) and built this, which works great on Firefox and  
Safari (both mac and PC). The $path leads to a directory outside the  
web root, and there is also an array with all the mime types in it  
($mimetype).



$file_path = $path./.$file;

$ext = explode(.,$file);

$filesize = filesize($file_path);

$extension = $mimetypes[$ext[1]];

header(Content-type: $extension);
header(Content-length: $filesize);
header(Content-Disposition: attachment; filename=\$file\);
header(Pragma: no-cache);
$file = file_get_contents($file_path);
echo ($file);

The problem is IE7. All browsers work with this code as is but IE  
says Internet Explorer cannot download test.pdf from XXX


Any suggestions?

--
Kevin Murphy
Webmaster: Information and Marketing Services
Western Nevada College
www.wnc.edu
775-445-3326

P.S. Please note that my e-mail and website address have changed from  
wncc.edu to wnc.edu. 

Re: [PHP] Re: Strategy for Secure File Storage

2007-09-24 Thread brian

Kevin Murphy wrote:
Ok, I'm almost there. I took what everyone said (and a few Google  
searches later) and built this, which works great on Firefox and  Safari 
(both mac and PC). The $path leads to a directory outside the  web root, 
and there is also an array with all the mime types in it  ($mimetype).



$file_path = $path./.$file;

$ext = explode(.,$file);

$filesize = filesize($file_path);

$extension = $mimetypes[$ext[1]];

header(Content-type: $extension);
header(Content-length: $filesize);
header(Content-Disposition: attachment; filename=\$file\);
header(Pragma: no-cache);
$file = file_get_contents($file_path);
echo ($file);

The problem is IE7. All browsers work with this code as is but IE  says 
Internet Explorer cannot download test.pdf from XXX


Any suggestions?



echo 'Your software provider sucks eggs. Get a better browser.';

heh ...

I just did precisely this (the script, not the sucks eggs comment) for 
a project i'm working on. There's a file store above document root and a 
script that does user validation, then reads the top dir of the file 
store and display links for each directory or file in there (of course, 
they're not direct links), letting the user drill down as far as it goes.



What exactly is in the var $extension?
header(Content-type: $extension);


Don't do this:
$file = file_get_contents($file_path);
echo ($file);

Do this instead:
readfile($file_path);
exit;


Here's the business end of my script:

-- snip --
header ('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header ('Content-Type: application/octet-stream');
header('Content-Transfer-Encoding: Binary');
header('Content-length: ' . filesize($filepath));
header('Content-disposition: attachment; filename=' . 
basename($filepath) .'');

readfile($filepath);
exit;
-- snip --

Note that i'm not trying to give the option for the browser to hand off 
the file to a helper application or plugin. This script is for 
downloading only, hence no MIME type and the octet-stream'  'attachment'.


I just checked another project where i did pass the MIMIE to allow for 
the file to open in Adobe Reader, MSExcel, etc. You also might want to 
add these two with your no-cache header:


header ('Expires: Mon, 1 Apr 1974 05:00:00 GMT');
header ('Last-Modified: ' . gmdate('D,d M YH:i:s') . ' GMT');

I seem to remember that it was IE that wanted these in order to play nice.

brian

--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php