2

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
1

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).
| improve this answer | |
  • 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 7: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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.