views:

352

answers:

4

Hi,

I have inherited a number of grossly coded PHP files, whose output I need to alter programmatically.

To achieve this, I chose to run them through another PHP file, rewriter.php, which looks approximately like this:

<?php
if(!preg_match('/^([a-zA-Z0-9\-_]*)$/', $_GET['page']))
  die('Incorrect page supplied.');
ob_start('changeOutput');

include($_GET['page'].'.php');
ob_end_flush();

function changeOutput ($buffer) {
  ...
}
?>

I use mod_rewrite to force them to run through this file:

RewriteEngine On
RewriteRule ^([^\.]*)\.php$ rewriter.php?page=$1

However an error message is displayed which makes me believe that the include() statement is affected by the RewriteRule above, i.e. it tries to run rewriter.php through rewriter.php and so on.

I suppose there are many ways to tackle this problem but I am specifically looking for a way to escape the include() statement from being affected by mod_rewrite. I looked through the module documentation but I couldn't find anything relevant.

Of course, alternatives to this approach are welcome too.

Thank you for your time and thinking.

Best regards,
Daniel

A: 

Include used the way you do it refer to the filesystem and bypass the mod-rewrite translation engine.

I would watch your regular expression.

/^([a-zA-Z0-9\-_]*)$/

match empty string also.

Try

/^([a-zA-Z0-9\-_]+)$/

and see if $_GET['page'] is empty or not.

Eineki
+1  A: 

You should first check if the file exists before including it:

if ($_GET['page'] != 'rewriter' && is_file($_GET['page'].'.php')) {
    include $_GET['page'].'.php';
} else {
    // file does not exist or is invalid
}
Gumbo
That would work, but would add an additional file stat to every request to the site. Probably not a big deal on a low traffic site, but easily avoidable by handling at the apache level.
Alan Storm
A: 

You can add a RewriteCond conditional to your htaccess that will check to see if the file exists. Similar to the comment by Gumbo, except slightly faster (and more lightweight code-wise).

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -f
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^([^\.]*)\.php$ rewriter.php?page=$1

This checks to see if it's a file or directory relative to the root of your website. If it is, it'll run the rewriter. A quick touch of .htaccess awesomeness :)

Jamie Rumbelow
This won’t work. A file cannot be a regular file (`-f`) and a directory (`-d`) at the same time.
Gumbo
A: 

Sounds like you're looking for RewriteCond, which is essentially a conditional statement for mod_rewrite

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !rewriter.php$
RewriteRule ^([^\.]*)\.php$ rewriter.php?page=$1 [L]

This will prevent your rule from being applied to URLs that end in rewriter.php.

Alan Storm
Thanks, Alan, that's wat I was looking for. That was a lot easier than I expect.
DXL