Search code examples
phpwordpress.htaccessdownloadglob

PHP script access a directory that is otherwise 'deny all' (Via .htaccess)


I'm trying to get a php script to list the contents of a backup directory that is protected using a 'deny all' command in a .htaccess file.

The reasoning behind this being a backup plugin for wordpress is only available to Administrators and I'd like to give a lower ranked user the ability to download their backups from online (via a simple dashboard widget).

You can find the code I'm using below, and it trips up when encountering a 403 error because of the htaccess file.

//define the directory (this is where the backup plugin store the .zip files)
$directory = site_url() . "/wp-content/backups/";

//display the generated directory for testing
echo '<b>Scanning: </b>' . $directory . '</br></br>';

//display a link to a test.zip I know exists for testing
echo '<b>Manual Link: </b> <a href="' . $directory . 'test.zip" target="_blank">test.zip</a></br></br>';

//get all files in the directory with a .zip extension.
$files = glob($directory . "*.zip");

//print each file name as a download link
foreach($files as $file){
    echo '<a href="' . $file . '">' . $file . '</a> </br>';
}

Any help you could provide would be most helpful.

Thanks, Andy.

Update on code so that glob works properly

//Define the backup folder location
$backup_location = "wp-content/backups/";

//Set the file directory for glob
$directory = $_SERVER['DOCUMENT_ROOT'] . $backup_location;

//Prints the directory for testing purposes
echo '<b>Scanning: </b>' . $directory . '</br></br>';

//Filter the discovered files
$files = glob($directory . "*.*");

//Echo the filtered files
foreach($files as $file){
    echo '<a href="' . site_url() . '/' . $backup_location . basename($file) . '">' . basename($file) . '</a> </br>';
}

Solution

  • You are currently just providing links to files the user doesn't have access to. This will not work without adding any rights.

    What would work in this set-up is to actually serve the files to the user, using your current page.

    What you basically do is make the php read the file (it has access to that file), send the user a header and then the content. Use code like the example from the php manual:

    http://php.net/manual/en/function.readfile.php

    <?php
    $file = 'monkey.gif';
    
    if (file_exists($file)) {
        header('Content-Description: File Transfer');
        header('Content-Type: application/octet-stream');
        header('Content-Disposition: attachment; filename='.basename($file));
        header('Content-Transfer-Encoding: binary');
        header('Expires: 0');
        header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
        header('Pragma: public');
        header('Content-Length: ' . filesize($file));
        ob_clean();
        flush();
        readfile($file);
        exit;
    }
    ?>