I'm playing with .htaccess and I was wondering if with just an .htaccess inside the root directory is possible to block all the request from a browser directed on existing files or directories.
Let's try this example:
RewriteEngine On
RewriteBase /~my_user/my_base/
RewriteRule ^list/$ list.php [L]
RewriteRule ^element_of_list/([a-zA-Z0-9\-]+)/$ element.php?elem_id=$1 [L]
Now, if I write http://127.0.0.1/~my_user/my_base/list/, this is wroking fine but if I write http://127.0.0.1/~my_user/my_base/list.php it's still working. I don't want that. I want the user to obtain a 404 error in the last case.
We have /etc/apache2/mods-enabled/userdir.conf
<IfModule mod_userdir.c>
UserDir public_html
UserDir disabled root
<Directory /home/*/public_html>
AllowOverride All
Options Indexes FollowSymLinks
<Limit GET POST OPTIONS>
Order allow,deny
Allow from all
</Limit>
<LimitExcept GET POST OPTIONS>
Order deny,allow
Deny from all
</LimitExcept>
</Directory>
</IfModule>
My first try was to use RewriteCond:
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^(.*)$ 404.php [L]
But it's not working. Every request ends up redirected to 404.php
UPDATE
So I've managed to create the filter for directories:
RewriteCond %{REQUEST_FILENAME} -d
RewriteCond %{REQUEST_URI} !^/~my_user/my_base/$ [NC]
RewriteRule ^(.*)$ 404.php [L]
What it does is to check if the requested path (REQUEST_FILENAME) exists and it's a directory AND if it's not my RewriteBase which is basically index.php, then redirect to 404.php
I'm still trying to find something that does the same thing for files. I know I can selectively do that using extensions filename but I want an universal filter for files.
If I've understood your requirements correctly, you're looking to do something like this:
# This is a real directory...
RewriteCond %{REQUEST_FILENAME} -f [OR]
# Or it's a real file...
RewriteCond %{REQUEST_FILENAME} -d
# And it's not 404.php...
RewriteCond $0 !=404.php
# And it's not the root
RewriteCond $0 !=""
# And it's not any of the above due to an internal redirect...
RewriteCond %{ENV:REDIRECT_STATUS} ^$
# So cause a 404 response (you could redirect to 404.php if you want)
RewriteRule ^.*$ - [R=404,L]
# Set the 404 error document
ErrorDocument 404 /~my_user/my_base/404.php
Keep in mind that this blocks everything that exists, so any images, stylesheets, or scripts will be sent to the 404 page too. If you just want to block access to the PHP files, Gumbo's solution is more appropriate. I think in that case you'll need another RewriteCond though to prevent looping:
# Make sure the reason this request has a .php is because it was requested
# by the user (and not due to a redirect)
RewriteCond %{THE_REQUEST} ^[A-Z]+\s/[^\s]+\.php
# Make sure we aren't on 404.php already
RewriteRule %{REQUEST_URI} !404\.php$
# We aren't, so redirect to 404.php
RewriteRule ^ 404.php [L]
Try this rule:
RewriteCond %{THE_REQUEST} ^[A-Z]+\ /[^?\ ]*\.php[/?\ ]
RewriteRule .*\.php$ 404.php [L]
This will rewrite all requests whose paths contain a .php internally to 404.php.
Related
I have this .htaccess file:
Options +FollowSymLinks
Options -Indexes
RewriteEngine On
RewriteEngine On
RewriteRule \.(png|jpg|gif|jpeg|bmp|ico|flv|mpeg|mp4|mp3|swf|exe|WAgame|wsc|eot|svg|ttf|woff|woff2|rar|wav)$ - []
RewriteRule ^ entryPoint3.php
RewriteRule ^ entryPoint2.php
RewriteRule ^ entryPoint.php
RewriteRule ^robots\.txt$ http://www.example.com [R,NE,L]
RewriteCond %{HTTP_HOST} ^example.com [NC]
RewriteRule ^(.*)$ http://www.%{HTTP_HOST} [L,R=301]
<Files .htaccess>
Order Allow,Deny
Deny from All
</Files>
If the entryPoint3.php exists, load it, otherwise load entryPoint2.php otherwise entryPoint.php. How to achieve this?
Have it this way:
Options +FollowSymLinks -Indexes
RewriteEngine On
RewriteRule \.(png|jpg|gif|jpeg|bmp|ico|flv|mpeg|mp4|mp3|swf|exe|WAgame|wsc|eot|svg|ttf|woff|woff2|rar|wav)$ - [L]
RewriteRule ^robots\.txt$ / [R,NC,L]
RewriteCond %{HTTP_HOST} ^example\.com$ [NC]
RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301,NE]
# if entryPoint3 exists then use it
RewriteCond %{DOCUMENT_ROOT}/entryPoint3.php -f
RewriteRule ^ entryPoint3.php [L]
# if entryPoint2 exists then use it
RewriteCond %{DOCUMENT_ROOT}/entryPoint2.php -f
RewriteRule ^ entryPoint2.php [L]
# if entryPoint exists then use it
RewriteCond %{DOCUMENT_ROOT}/entryPoint.php -f
RewriteRule ^ entryPoint.php [L]
<Files .htaccess>
Order Allow,Deny
Deny from All
</Files>
I solved it like that: DirectoryIndex entryPoint3.php entryPoint2.php entryPoint.php what's the difference?
...but remember it will try to open entryPoint files in every directory not just in site root
You can specify root-relative URL-paths as arguments to the DirectoryIndex directive, they do not need to be relative, as you have here. For example:
DirectoryIndex /entryPoint3.php /entryPoint2.php /entryPoint.php
This will search for files in the document root only, regardless of which directory is requested.
But also, this is quite different to #anubhava's solution using mod_rewrite (and similar to what you were attempting in the question). With DirectoryIndex, the necessary file will only be served if you are requesting a directory (which includes the document root, ie. https://example.com/). eg. example.com/ and example.com/directory/ will trigger the relevant entryPoint file, but example.com/something will not.
However, with the mod_rewrite solution as stated, the relevant entryPoint file is served for "any" requested URL (except for the few URL-extension exceptions as stated). eg. example.com/, example.com/something, example.com/file.php and example.com/directory/ will all trigger the relevant entryPoint file.
For the mod_rewrite solution to work the same way as DirectoryIndex you will need an additional condition that explicitly checks that the request maps to a directory (including the trailing slash). For example:
# When requesting a directing... if entryPoint3 exists (in the root) then use it
RewriteCond %{REQUEST_FILENAME} -d
RewriteCond %{DOCUMENT_ROOT}/entryPoint3.php -f
RewriteRule ^(.+/)?$ entryPoint3.php [L]
:
The RewriteRule pattern simply checks that the requested URL ends with a slash (or is the document root) - the same behaviour as DirectoryIndex. (If you request a directory without a trailing slash then mod_dir appends it with a 301 redirect.)
So the solution you choose really depends on your requirements. However, if DirectoryIndex is working for you then I assume you are only requesting filesystem directories, so DirectoryIndex would be the way to go.
My knowledge of htaccess is pretty limited, so please be gentle...
I have a php page that displays an article, based on a variable passed through the url. For each article, I want the url to be changed to the article title, but I can't lose the article id being passed to the page...
So, for ...
www.somesite.com/news/article?id=4
... I can change it to ...
www.somesite.com/news/here-is-the-article-title
Or for
www.somesite.com/news/article?id=7
... I can change it to ...
www.somesite.com/news/some-other-title-that-I-choose
Bascially, I want the content for "article?id=4" to be shown on the page, but the URL to read "here-is-the-article-title". Is this even possible using htaccess? Or is there a similar solution? I know that I'll probably have to rewrite EACH url, and I'm fine with that.
I have some standard htaccess code I use...
Options +FollowSymLinks -MultiViews
# enable the rewrite engine
RewriteEngine On
# Set your root directory
RewriteBase /
# remove the .php extension
RewriteCond %{THE_REQUEST} ^GET\ (.*)\.php\ HTTP
RewriteRule (.*)\.php$ $1 [R=301]
# remove index and reference the directory
RewriteRule (.*)/index$ $1/ [R=301]
# remove trailing slash if not a directory
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} /$
RewriteRule (.*)/ $1 [R=301]
# forward request to html file, **but don't redirect (bot friendly)**
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteCond %{REQUEST_URI} !/$
RewriteRule (.*) $1\.php [L]
# Disable Directory Browsing
Options -Indexes
# Protect htaccess File
<files ~ "^.*\.([Hh][Tt][Aa])">
order allow,deny
deny from all
satisfy all
</files>
Basic REDIRECT doesn't work, since I lose the article id.
I've a small, but hard to understand problem with .htaccess in CMS system.
I've mod expires, that cache stuff on whole website, but I don't want to cache stuff in /admin URL, I can't make another .htacess, couse I've MVC structure and no real directory that could hold all my admin stuff.
I've found directive, but it only works in server configuration and I want it to work on different hostings, so only in htaccess file.
EDIT- Rewrite
# Turn on URL rewriting
RewriteEngine On
# Installation directory
RewriteBase /
RewriteCond %{HTTP_HOST} !^www. [NC]
RewriteCond %{HTTP_HOST} ![0-9]$ [NC]
RewriteRule ^(.*)$ http://www.%{HTTP_HOST}/$1 [L,R=301]
# Protect hidden files from being viewed
<Files .*>
Order Deny,Allow
Deny From All
</Files>
# Protect application and system files from being viewed
RewriteRule ^(?:application|modules|system)\b.* index.php/$0 [L]
# Allow any files or directories that exist to be displayed directly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# Rewrite all other URLs to index.php/URL
RewriteRule .* index.php/$0 [PT]
You can apply your Expires directive using a <if> directive with an expression to match against /admin:
<If "%{REQUEST_URI} =~ /^\/admin\//">
# Your expiry directives
</If>
If you know the exact URL then you can try this pattern.
RewriteRule ^facebook/get/(.*)?$ http://$1 [NC,R]
RewriteRule ^wrapper/share/(.*)?$ http://example.com/wrapper/share/$1 [NC,R]
This will check for URL where <-any-value->facebook/get/<-any-value2-> and then will send to the <-any-value2->
Like
RewriteRule ^stats/(.*)$ admin/dashboard.php?mode=openstats&event_id=$1 [NC,L,QSA]
**If URL has stats/<--any-value--> then it will redirect/open admin/dashboard.php **
If your URLs doesn't have exact value but you do know the URL slot pattern then you can try this.
RewriteRule ^([^/.]+)/([a-zA-Z0-9_-]+)/$ wrapper/index.php?id=$2 [NC,L,QSA]
I've done some code so that the url gets passed to the index page and the index page then decides which page to load in. Initially it would redirect unless a file or directory existed, which was fine for most cases, but things like the php files I wanted to keep private, as they should only be referenced by index.php, and not actually called themselves.
With a bit of help, I managed to switch it so that it would redirect everything, aside from certain extensions, such as images and css files. I've only just noticed it'll still attempt work on files that don't exist, and come up with the default 404 page, but I'd prefer it to be passed to my code like all the other pages.
How would I merge these two rules, so that the redirect will only not happen if both the file exists, and its extension is allowed?
1. RewriteCond %{REQUEST_FILENAME} !-f
2. RewriteCond %{REQUEST_URI} !\.(?:jpe?g|gif|txt|php|bmp|png|ico|tiff|css|js)$
Here were the old rules (specific to the redirecting):
# If the request is not for a valid directory
RewriteCond %{REQUEST_FILENAME} !-d
# If the request is not for a valid file
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php?_page_location=$1 [L,NC,NE]
And here is it as it currently stands:
Options -Indexes
Options +FollowSymLinks
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L,NC]
# Add trailing slash to directories
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule [^/]$ %{REQUEST_URI}/ [L,R=301,NE]
# If the request is not for known file types
RewriteCond %{REQUEST_URI} !\.(?:jpe?g|gif|txt|php|bmp|png|ico|tiff|css|js)$
RewriteRule .* index.php?_page_location=$0 [L,QSA]
<FilesMatch "^(.*)\.php$">
Order Deny,Allow
Deny from all
</FilesMatch>
<FilesMatch "index\.php|info\.php">
Order allow,deny
Allow from all
</FilesMatch>
I have wordpress installed in root directory. I want to use some separate php files as a page on my domain, for which I have made a separate directory which holds all files for serving the php files, of which the directory structure is as:
the root folder has all the wordpress files
the directory which I'd like to serve as a page
/inc/css/
/inc/php/
/inc/img/
the CSS stylesheet files directory location in the PHP file is ../inc/css one step back & then css folder.
I want to hide folders from URL such as the files are served from the root (hide the /inc/php/, /inc/css/ & /inc/img/ folders from URL).
eg: www.domain.com/inc/php/about.php redirect & rewrite this URL to www.domain.com/about
the .htaccess in my root
RewriteEngine On
RewriteBase /
# disable directory browsing
Options -Indexes
# Prevent hotlinking of images htaccesstools.com/hotlink-protection
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http(s)?://(www\.)?domain.com [NC]
RewriteRule \.(jpg|jpeg|png|gif|ico|pdf|flv|jpg|jpeg|mp3|mpg|mp4|mov|wav|wmv|png|gif|swf|css|js)$ - [NC,F,L]
RewriteRule ^login$ http://domain.com/wp-login.php [NC,L]
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
<files wp-config.php>
order allow,deny
deny from all
</files>
<files ~ "^.*\.([Hh][Tt][Aa])">
order allow,deny
deny from all
satisfy all
</files>
I have tried the simple redirect rule but the folders are exposed in the URL.
Redirect 301 /about.php /inc/php/about.php
also I have some more files in the PHP folder on which I'd like to apply the same rule of redirect & rewrite URL & hide folders from URL & remove the PHP extention.
www.domain.com/inc/php/about.php redirect & rewrite this URL to www.domain.com/about
This, of course, means that you can't have the same base filename that's a php file and, say, a css file. Since if the request is www.domain.com/about, is that supposed to map to /inc/php/about.php or /inc/css/about.css? Or is it an image? If you have both files, only one will get mapped to.
But if that's really what you want, try adding these rules right after the hotlinking rule that you have:
# Externally redirect requests for /inc/
RewriteCond %{THE_REQUEST} \ /inc/(php|img|css)/([^\?\ ]+)\.(php|css|jpe?g|png|gif) [NC]
RewriteRule ^ /%2 [L,R=301]
# Check if the request is a php file:
RewriteCond %{DOCUMENT_ROOT}/inc/php%{REQUEST_URI}.php -f
RewriteRule ^(.*)$ /inc/php/$1.php [L]
# Check if the request is a css file:
RewriteCond %{DOCUMENT_ROOT}/inc/css%{REQUEST_URI}.css -f
RewriteRule ^(.*)$ /inc/css/$1.css [L]
# Check if the request is a jpeg file:
RewriteCond %{DOCUMENT_ROOT}/inc/img%{REQUEST_URI}.jpg -f
RewriteRule ^(.*)$ /inc/img/$1.jpg [L]
# Check if the request is a gif file:
RewriteCond %{DOCUMENT_ROOT}/inc/img%{REQUEST_URI}.gif -f
RewriteRule ^(.*)$ /inc/img/$1.gif [L]
# Check if the request is a png file:
RewriteCond %{DOCUMENT_ROOT}/inc/img%{REQUEST_URI}.png -f
RewriteRule ^(.*)$ /inc/img/$1.png [L]