9

If I want to apply a rule to only some files in apache2.conf, I can use <FilesMatch>.

For example:

<FilesMatch ".(gif|jpg|jpeg|png|mpg|avi)$">
    deny from env=hotlink
</FilesMatch>

But is there a opposite to FilesMatch, i.e. a FilesNotMatch?

What I want to achieve is:

<FilesMatch ".(gif|jpg|jpeg|png|mpg|avi)$">
    <FilesNotMatch "ban">
        deny from env=hotlink
    </FilesNotMatch>
</FilesMatch>

(deny hotlinking of all images on a server BUT banners)

Or do you have a suggestion how I could modify my regexp to not match anything that contains "ban" ?

2 Answers 2

8

Sadly there doesn't seem to be a way to negate a file match in Apache.

However, the regular expression library that Apache uses is PCRE (Perl Compatible Regular Expressions). This means you have the full power of Perl's regexes, including their negative lookbehind and lookahead assertions. These are fairly complicated and powerful features. I can't be certain that this will work, especially without knowing the full layout of your images, but you might be able to use something like:

<FilesMatch "(?<!ban).*\.(gif|jpg|jpeg|png|mpg|avi)$">
1
1

Almost correct - you need to use \b(?!.*ban.*)(.+)\.(gif|jpg|jpeg|png|mpg|avi)$ regexp for such exception.

5
  • I tried "\b(?!/test.php)" to match any file other than test.php and it didn't work. Jan 2, 2020 at 14:06
  • Well, you just need to follow my example. As you've ignored 'ending$' (and escaping dot via '\.') you have probably did some tests earlier - up to the point, where rexexp fails, but somehow your comment doesn't specify the place, where it happens. I won't reproduce your test-case, but I might guess it has something to do with '/' you've introduced... Jan 26, 2020 at 10:18
  • Thanks! I almost always have trouble with regexps. Now I'm trying ^(?!(test\.php))$ and this still doesn't work. It doesn't match "xx" when it should. I'm using the online regexp tester regex101.com to test. And when I try your example, it matches "a.gif" when it should not match. Probably, I'm not understanding the original question, and misunderstanding the ?! operator. Jan 27, 2020 at 11:32
  • Consider ^(?!(test\.php))$ - if you remove the negation, that doesn't match your "xx", what's left? ^()$ - i.e. empty string. Try ^(?!(test\.php)).+$. As for my example - it's supposed to match "a.gif", but do not match "ban.gif" and that is what happens. The accepted answer matches "ban.gif" and so is wrong... Jan 30, 2020 at 14:32
  • 1
    If you ask me, the Perl Regular Expression library, and all the products that use it, need a true negation operator. Trying to force a "look-ahead" feature to work well can obviously be done, but only with great difficulty. PCRE needs to be extended. Jan 31, 2020 at 17:05

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .