Welcome Guest, Not a member yet? Register   Sign In
File security
#1

[eluser]frist44[/eluser]
I have a folder where people will be uploading files. I would like to these files NOT to be accessible with the normal direct URL (I can control this via apache), however, I would like the application to be able to get them.

I would prefer that a user not know the exact path of the download. Is there a good way to mask this while still protecting the files?

Thanks.
#2

[eluser]Jelmer[/eluser]
Save it outside your webroot and make it accessible through a controller (you can do whatever checking you like) and serve it up in the end by readfile().
Just don't forget to set the correct content-type in the header, for example the header for a JPG:
Code:
header('Content-Type: image/jpg');
readfile('../outside_webroot_dir/image.jpg');

If your index.php is in your webroot, for example /http_docs/, this will give the file at / outside_webroot/image.jpg

Your paths are protected (because it's outside the webroot and thus cannot accessed directly) and you can require someone to be logged in before doing the readfile().
#3

[eluser]frist44[/eluser]
Great idea. I actually started toying around with the same idea not long after I posted. I'm having trouble though because I made a test function that works file:

Code:
$path = $this->config->item('base_path') . 'data/sample.xls';
        
        header('Content-type: application/excel');
        header('Content-Disposition: attachment; filename="data.xls"');

        
        echo file_get_contents($path);

This worked fine and delivered the content to the browser in the same format. I try it with my real controller and everything it opens, it says it's a different format than the file was saved.

Code:
if ($purchase = $this->purchases_model->is_user_authorized_for_download(userid(), $purchaseid)) {

            $fullpath = $this->config->item('base_path') . $purchase['datapath'];
            
            //file_get_contents($fullpath);
            
            header("Content-Type: application/msexcel; ");
            header("Content-Disposition: attachment; filename=\"" . $purchase['title'] . ".xls\"; ");

            readfile($fullpath);

            
        } else {
            
            redirect_with_error(base_url(), 'flash_error_download');
        }

any idea why the latter doesn't work?
#4

[eluser]frist44[/eluser]
It appears that the latter requires ob_clean(). any idea why?

header('Content-Type: application/excel');
header('Content-Disposition: attachment; filename="' . $purchase['title'] . '.xls"');
ob_clean();

echo file_get_contents($fullpath);
#5

[eluser]Jelmer[/eluser]
The only thing I can think of is that maybe there's something outputted before the readfile() statement? That would prevent headers from being sent and might cause the error you described.
Also you're outputting a different header in the ob_clean() and non-CI examples from the first Controller example.

Do you have error_reporting set to E_ALL? If not, that might show you when something goes wrong.

I also must admit I'm a bit surprised that your first example would work: file_get_contents reads a file into a string, and I wouldn't expect that to work with an Excel file (which I think are not ASCII).
#6

[eluser]frist44[/eluser]
Gotcha. My error reporting is indeed set to E_ALL. Haven't seen anything to believe it was sending something else out, but I guess it works, so it is what it is. I changed it to be consistent with the readfile() function.

Thanks for the help.
#7

[eluser]frist44[/eluser]
I guess I was looking into it a little too hard. I used the force_download() function that's in the download helper and it did everything for me. Oddly enough, I don't need to do the flush and it works fine. it also uses the file_get_contents function successfully.

Code:
force_download($template['name'] . '.xls',  file_get_contents($fullpath));




Theme © iAndrew 2016 - Forum software by © MyBB