Apache rewrite rule for existing files doesn't work - mod-rewrite

I need to protect all pdf files on server through a password. Typical path to a pdf is /images/a/a2/some.pdf
My rewriting code in httpd.conf is :
RewriteEngine On
Options FollowSymLinks
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^images/([^/]*)/([^/]*)/([^/]*)^.pdf$ /download.php?file=$3& [L]
RewriteRule images/a/a2/VB-VB-41-445%29_Small.pdf$ /download.php?file=ok [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)$ /index.php/$1 [L,QSA]
The 5th line is added to check whether there is some problem in regular expression.
Unfortunately, the redirect doesn't work. If pdf exists it starts to load immediately.
But if path doesn't exist, it works! I need the opposite result. What is wrong with code or maybe there are some config settings with mod_rewrite?
P.S. I noticed one clue to a possible answer: if i replace "images" with "asdf" in rewrite rule and try non-existing path, it redirects to download.php. But if i try non-existing path with "images", it returns 404 error. Asdf doesn't exist on the server, but images - is a true folder.
RewriteRule /images/asd.pdf /download.php?file=ok [L,QSA] - doesn't work, folder exists, file asd.pdf doesn't exist
RewriteRule /asdf/asd.pdf /download.php?file=ok [L,QSA] - works, redirects correctly to download.pdf, path doesn't exists (neither folder nor file)
RewriteRule images/a/a2/VB.pdf$ /download.php?file=ok [L] - doesn't work, redirect doesn't happen, instead an existing pdf file starts to download.
P.P.S. After some time I found that inside /images/ folder there is .htaccess file with this text:
# Protect against bug 28235
<IfModule rewrite_module>
RewriteEngine On
RewriteCond %{QUERY_STRING} \.[^\\/:*?\x22<>|%]+(#|\?|$) [nocase]
RewriteRule . - [forbidden]
</IfModule>
<IfModule expires_module>
ExpiresActive On
ExpiresDefault "access plus 1 month"
</IfModule>
Probably, it is the cause of rewriting issue.
P.P.P.S.
The problem has been solved with writing the rewrite rule in a file .htaccess inside folder /images/:
# Protect against bug 28235
<IfModule rewrite_module>
RewriteEngine On
RewriteCond %{QUERY_STRING} \.[^\\/:*?\x22<>|%]+(#|\?|$) [nocase]
RewriteRule . - [forbidden]
RewriteRule ^[^\/]+/[^\/]+/(.*)\.pdf$ ../download.php?file=$1& [L]
</IfModule>
<IfModule expires_module>
ExpiresActive On
ExpiresDefault "access plus 1 month"
</IfModule>

The PDF starts to download if exists in path because of RewriteCond %{REQUEST_FILENAME} -f directive. This tells apache that the file exists and to not proceed with the following rules. If you remove this line, the mod_rewrite will always follow rules no matter if file exists or not.

Related

Redirect image url to another page using .htaccess

I want to redirect this url
http://192.168.1.101/project/test/wordpress/wp-content/uploads/2013/06/Sunset.jpg
to this with main url as following.
http://192.168.1.101/project/test/wordpress/redirect.php?file=http://192.168.1.101/project/test/wordpress/wp-content/uploads/2013/06/Sunset.jpg
If url contain extension like .jpg, .png, .jpeg, .bmp, .png then move all it to redirect.php with file name like.
http://192.168.1.101/project/test/wordpress/redirect.php?file=imagefile
My current .htaccess code
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /project/test/wordpress/
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /project/test/wordpress/index.php [L]
</IfModule>
# END WordPress
Please Help Me..
Insert this line just after RewriteBase line:
RewriteRule ^wp-content/.+?\.(jpe?g|png|gif|bmp)$ redirect.php?file=http://%{HTTP_HOST}%{REQUEST_URI} [NE,R=302,L,NC]
Once you verify it is working fine, replace R=302 to R=301. Avoid using R=301 (Permanent Redirect) while testing your mod_rewrite rules.

Rewrite part of url .htacces

I need to redirect an url from
http://mydomain.com/download/filename.zip
to
https://dl.dropbox.com/u/0000/filename.zip
How can I do this using mod_rewrite?
Make a .htaccess file in root of your first domain, with this rule:
RewriteEngine On
RewriteRule download/(.+) https://dl.dropbox.com/u/0000/$1 [L,R=301]
# Check to see if mod_rewrite is installed / avaliable
<IfModule mod_rewrite.c>
RewriteEngine on
# Check to see if file or directory exists
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# Rewrite to Dropbox URL. Make sure you change the data after "/u/" (9502594) to your own user ID
RewriteRule ^e/(.*)$ http://dl.dropbox.com/u/9502594/$1 [L,QSA] # Embedded File
RewriteRule ^(.*)$ http://dl.dropbox.com/u/9502594/$1?dl=1 [L,QSA] # Force Download (Default)
</IfModule>

Mod rewrite into subdirectory

I have been having some trouble getting the following to work:
<IfModule mod_rewrite.c>
DirectoryIndex index.php
Options +FollowSymLinks
RewriteEngine On
# If the file is not found in web
RewriteCond web/$1 -f [NC] #<-- This line seems to be the problem.
RewriteRule ^(.*)$ web/$1 [L]
# Then rewrite it to index.php
RewriteRule ^(.*)$ index.php [L,QSA]
</IfModule>
The idea is to check if the file exists in the web directory, and if it doesn't, route the request to index.php.
The problematic line above seems to pick up the correct URL, but it does not recognize that the file exists.
For example:
http://localhost/img.gif --> /www/web/img.gif
http://localhost/subdir/file.doc --> /www/web/subdir/file.doc
http://localhost/user/add --> /www/index.php
http://localhost/invalidurl --> /www/index.php
However, I cannot get static resources to be served correctly, they are all routed to index.php.
I also want to keep all URLs relative; so I can make this code reusable without editing it.
The following .htaccess gives an Internal Server Error, if I visit img.gif:
<IfModule mod_rewrite.c>
DirectoryIndex index.php
Options +FollowSymLinks
RewriteEngine On
# If the file is not found in web
#RewriteCond web/$1 -f [NC] #<-- This line seems to be the problem.
RewriteRule ^(.*)$ web/$1 [L]
# Then rewrite it to index.php
#RewriteRule ^(.*)$ index.php [L,QSA]
</IfModule>
This .htaccess redirects to http://localhost/C:/absolute/path/to/web/img.gif, when visiting img.gif:
<IfModule mod_rewrite.c>
DirectoryIndex index.php
Options +FollowSymLinks
RewriteEngine On
# If the file is not found in web
#RewriteCond web/$1 -f [NC] #<-- This line seems to be the problem.
RewriteRule ^(.*)$ web/$1 [R]
# Then rewrite it to index.php
#RewriteRule ^(.*)$ index.php [L,QSA]
</IfModule>
My conclusion from this would be that it's getting the path correct, but some weirdness is causing it to do something completely weird (I don't even know why it has an internal server error - Should be 404 not found).
Ok I got it:
When you do a rewrite, then keep in mind that the rewritten URL is called internally.
So you basically have to reprocess the .htaccess with mostly different values.
So in your example : http://localhost/img.gif is directed to http://localhost/web/img.gif and then to http://localhost/index.php by the last rule.
I would try this (replace the last rule by: )
RewriteCond %{SCRIPT_NAME} !^/web/
RewriteRule ^(.*)$ index.php [L]
(NB: [QSA] is not needed since you don't touch the query string, so it is passed as is.)
Edit : What about
# If the file is not found in web
RewriteCond web/$1 !-f [NC]
# And we don't ask for /web/something at the beginning (Avoid infinite loops since you'll try to call web/image.gif and we don't want to test /web/web/image.gif and fail to index.php
RewriteCond %{SCRIPT_NAME} !^/web/
#Rewrite it to index.php
RewriteRule ^(.*)$ index.php [R,L]
# If the file is found in web
RewriteCond web/$1 -f [NC]
# And we don't ask for /web/something at the beginning (Avoid infinite loops since you'll try to call web/image.gif and we don't want to test /web/web/image.gif and fail to index.php
RewriteCond %{SCRIPT_NAME} !^/web/
#Then point to web/image.gif
RewriteRule ^(.*)$ web/$1 [L]

how do i get to restrict access to my folders

am using codeigniter to build a website with a lot of image galleries , i store the images in folders ,but i want to restrict access to the folders via url .i.e i don't want people to have access to my image folder using a url like this::
http://website/all_images/
all images is the folder that contains the image folder .. i tried using a htaccess file
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_URI} ^CI_system.*
RewriteRule ^(.*)$ /website/index.php?/$1 [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond $1 !^(index\.php|all_images)
RewriteRule ^(.*)$ /website/index.php?/$1 [L]
</IfModule>
<IfModule !mod_rewrite.c>
ErrorDocument 404 /index.php
</IfModule>
the rewrite condition for the index.php works well but i still get access to all my folders via the url
If you want to disable folders to be viewed, just add empty index.html file, but if you try to protect images from being viewed then your website wont be able to find them too
Why don't you create an index file under that folder. In this way no will will be able to view images under that folder.
You can make this file call a function that says "access denied" or whatever you need.
Options -Indexes in your htaccess file will stop directory viewing no extra files needed. and if you want to stop direct image viewing i.e. myweb.com/all_images/coolpic.jpg then all you have to do is (since your base is / you can use the whole one below):
Options -Indexes
ErrorDocument 404 /index.php
DirectoryIndex index.php
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [L,QSA]
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http://(www\.)?myweb.com/.*$ [NC]
RewriteRule \.(gif|jpg)$ - [F]
</IfModule>
All you would have to change is the line with your web address in it and add all of your file types to the last rewrite rule (seperating each with a pipe |) and then this will cover all of the angles you have discussed 100%.

What does this Mod Rewrite do?

Can anybody tell me what this does?
RewriteRule .* .main.php [QSA,L]
From what I understand it will rewrite ANYTHING to main.php correct? But not so sure what the QSA,L does.
This is the whole .htaccess file, when I hit the main directory I get a 400 Bad Request error. Edit: Bad request went away when I added an ending slash in the browser to the root directory of this script.
RewriteEngine On
# Transfering to the main tranfer file
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-l
RewriteCond %{REQUEST_FILENAME} !\.css$
RewriteCond %{REQUEST_FILENAME} !\.js$
RewriteRule .* .main.php [QSA,L]
# nobody is allowed to access the access the INI file
<FilesMatch "\.inc.php$">
Order allow,deny
Deny from all
</FilesMatch>
QSA = Query String Append: append the existing query string to the re-written rule
L = Last Rule: last rule of the set, don't process any following RewriteRule
Check out the documentation for more.
Do you have a file that is named .main.php? The dot prefix worries me. Your rules read that unless the request is an exists, symbolic link, or it has a CSS or JS extension it goes to .main.php

Resources