3

I have this tree:

libs/
html/
app/
uploads/
    files/
    images/
        male.png
        female.png
    .htaccess
    download.php
.htaccess
index.php

/.htaccess has this content:

<IfModule mod_rewrite.c>
    <IfModule mod_negotiation.c>
        Options -Indexes
    </IfModule>

    RewriteEngine On

    RewriteRule ^ index.php [END,L]
</IfModule>

I want /uploads/.htaccess to:

  • redirect to download.php

    • if existent file, but not this .htaccess or download.php
  • redirect 404

    • if don't match existent file
    • or match .htaccess or download.php
    • or match existent folder

Examples:

www.example.com/uploads - redirect 404
www.example.com/uploads/files - redirect 404
www.example.com/uploads/images- redirect 404
www.example.com/uploads/.htaccess - redirect 404
www.example.com/uploads/download.php - redirect 404
www.example.com/uploads/nonexistentfile - redirect 404

www.example.com/uploads/images/male.php - redirect download.php
www.example.com/uploads/images/female.php - redirect download.php
MrWhite
  • 11,643
  • 4
  • 25
  • 40
Arșavin
  • 33
  • 1
  • 4

1 Answers1

2

redirect to download.php

I assume you mean "rewrite", rather than an external "redirect".

I would assume your system (ie. server config) is already configured (using mod_authz_...) to return a 403 Forbidden when trying to access .htaccess directly. I would leave that as it is, unless you have a specific requirement to return a 404 instead.

redirect to 404

And just to clarify, you don't literally "redirect" to a 404, you simply "serve" a 404. If you redirected to a 404 then you would first be sending a 3xx response back to the client, which is undesirable.

In the /uploads/.htaccess file try the following:

RewriteEngine On

# Rewrite request to download.php
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule !download\.php$ download.php [L]

# Serve a 404 otherwise...
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^ - [R=404]

The first rule rewrites all requests that are not already for download.php and exist as physical files to download.php. (A request for .htaccess should return a 403, assuming the server is configured correctly.)

The second rule serves a 404 for all other "direct" requests. The initial condition that checks the REDIRECT_STATUS environment variable ensures we only check direct requests and not rewritten requests (by the earlier rewrite). So this includes:

  • direct requests to download.php (but not rewritten requests to download.php).
  • direct requests for directories.
  • The request does not map to a file (because the first rule would have failed).
MrWhite
  • 11,643
  • 4
  • 25
  • 40
  • It helped me. Can I ask you one more little thing? How to make download.php act as it would be near index.php (one "row" above) while is in upload/ ? – Arșavin Jul 17 '19 at 07:41
  • Sorry, I'm not sure what you mean? What does this have to do with `index.php`? Do you have other directives in this `.htaccess` file? The mod_rewrite directives in `/uploads/.htaccess` completely override the mod_rewrite directives in the parent `.htaccess` file. – MrWhite Jul 17 '19 at 10:25
  • I meant: How to make, from .htaccess, download.php act ast it is in root, instead in uploads/, while it's in uploads/ ? – Arșavin Jul 17 '19 at 14:39
  • "download.php act ast it is in root" - What do you mean by "act"? This doesn't really make sense, as the location of `download.php` is already hidden from the user. As far as the user is concerned it might already be located in the root. In fact, the user doesn't even know there is a `download.php` script. You don't need to make it "act" like it is anywhere, except for where it actually is. (?) You can physically move the `download.php` file anywhere you like, but it makes no difference to the user (or your script). These directives are an _internal rewrite_, not an _external redirect_. – MrWhite Jul 17 '19 at 15:48
  • I understand. Thank you very much. :) – Arșavin Jul 17 '19 at 17:47