Regex negative look-ahead is not working for mod_rewrite between different Apache versions

I have a mod_rewrite line that works under Apache 2.2, but not under Apache 1.3:

RewriteRule     ^(?!index.php)(?!skin/)(?!js/)(.+)      /index.php?file=$1              [NC,L]

If I lose the negative look-ahead components between the brackets, I lose the 500 status code. GoDaddy won't upgrade the httpd for this client's package (sigh), so has anyone got a solution that could work in 1.3 (and isn't too messy :P)? Or even better can anyone explain what might be going on here? I remain curious only because I can't find any information on the Perl regex engine used in 1.3 not supporting negative look-ahead...


Solution 1:

Apache 1.3 doesn't use Perl compatible regular expressoins (PCRE), it uses POSIX regexes. POSIX regexes don't support negative lookahead. PCRE support is a new feature starting in Apache 2.

As to how to get this to work, you probably need to use some RewriteCond to have the rule NOT trigger if it matches one of those three... e.g. perhaps:

RewriteCond   %{REQUEST_URI}   !index.php.*
RewriteCond   %{REQUEST_URI}   !skin/.*
RewriteCond   %{REQUEST_URI}   !js/.*
RewriteRule   ^(?!index.php)(?!skin/)(?!js/)(.+)  /index.php?file=$1    [NC,L]

Of course, I haven't tested this... I haven't got any Apache 1.3's around anymore.

Solution 2:

Adam Bellaire is right. Apache changed the regular expression engine with version 1.2 and with version 2.0.

For Apache 1.1.x they used “System V8” and since Apache 1.2 and later it was POSIX ERE. The last change was with Apache 2.0 when they switched to PCRE. You can take a look at the Regular Expression Flavor Comparison to see the differences.

Now here’s a solution how you can solve this without look-ahead assertions that are only available in PCRE:

RewriteCond $1 !^(index\.php|skin/|js/)
RewriteRule ^(.+) /index.php?file=$1 [NC,L]

Here the additional RewriteCond is to check that the matched string of the first subpattern does start with the listed options.