Reputation: 1645
I'm trying to rewrite the static URLs on my shared webserver running apache2, in order to track the download counts of the files in the public_html/files/
subdirectory.
I want to rewrite the urls like
http://example.com/files/foo.zip
into the url
http://example.com/files/download.php?file=foo.zip
The download.php
script works fine if I type manually its URL in the browser.
The RewriteRule
that I'm using is the following:
RewriteRule ^files/(.*)$ /files/download.php?file=$1 [L]
I tried two different ways:
Insert the rule in the "root" public_html/.htaccess
file. This results in a 500 error when I request example.com/files/foo.zip
# public_html/.htaccess
# Use PHP5.4 as default
AddHandler application/x-httpd-php54 .php
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
# Default wordpress rules
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
# My custom rule
RewriteRule ^files/(.*)$ /files/download.php?file=$1 [L]
</IfModule>
# END WordPress
Options -Indexes
Insert the rule in a new public_html/files/.htaccess
file. Now when I request example.com/files/foo.zip
the download works, the rewrite doesn't, i.e. download.php
is not called.
# public_html/files/.htaccess
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^files/(.*)$ /files/download.php?file=$1 [L]
</IfModule>
I'm having a hard time debugging this, because I'm on a shared server and I don't have a quick access to the apache error logs. What I'm doing wrong?
I should probably clarify that the url rewriting triggered by wordpress (with its permalinks) works fine.
This is files/download.php
used for tracking downloads on my DB:
<?php
define('WP_USE_THEMES', false);
require('../wp-blog-header.php');
$filename = $_GET['file'];
$basepath = $_SERVER['DOCUMENT_ROOT']."/files/";
$realbase = realpath($basepath);
$actual_link = "http://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
file_put_contents("request.log", $actual_link."\n\n", FILE_APPEND);
$inputpath = $basepath . $filename;
$realpath = realpath($inputpath);
if ($realpath === false || strpos($realpath, $realbase) !== 0) {
echo "Directory traversal detected! <br/>";
exit;
}
$fileinfo = pathinfo($realpath);
$filetypes = array("gz", "zip", "tgz");
$table = "downloads"; // table name
$pk = "filename"; // table primary key
$counter = "download_count"; // counter field
if (!in_array($fileinfo['extension'], $filetypes)) {
echo "$inputpath - {$fileinfo['extension']} is an invalid download type.";
exit;
}
if (file_exists($realpath)) {
$count = $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM {$table} WHERE {$pk} = '{$filename}';"));
$query = "";
if ($count == 1) {
$query = "UPDATE {$table} SET {$counter} = {$counter} + 1 WHERE {$pk} = '{$filename}';";
}
else if ($count == 0) {
$query = "INSERT INTO {$table} ({$pk}, {$counter}) VALUES ('{$filename}', 1);";
}
$wpdb->query($wpdb->prepare($query));
$size = filesize($realpath);
header("Content-Type: application/octet-stream");
header("Content-Disposition: filename={$fileinfo['basename']}");
header("Content-Length: {$size}");
header("Cache-Control: private");
header("Location: {$filename}");
readfile(basename($realpath));
}
else {
echo "File $filename does not exist.";
}
exit;
?>
Upvotes: 0
Views: 546
Reputation: 785146
Inside public_html/files/.htaccess
you should have:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /files/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)$ download.php?file=$1 [L,QSA]
</IfModule>
EDIT:
Try this in WP .htaccess:
# public_html/.htaccess
# Use PHP5.4 as default
AddHandler application/x-httpd-php54 .php
Options -Indexes -MultiViews
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
# Default wordpress rules
RewriteBase /
RewriteRule ^index\.php$ - [L]
# My custom rule
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^files/((?!download\.php).+)$ /files/download.php?file=$1 [L,QSA]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
Upvotes: 1
Reputation: 6694
Try to put /
here:
RewriteRule ^/files/(.*)$ /files/download.php?file=$1 [L]
^--here
Upvotes: 1