Please help with this mod_rewrite issue - apache

This current system in place needs to allow periods (.) optionally inside of the rewrite condition.
For example: /john.doe should work, since we allow periods in our user names.
However when I add . or \\. or [.] to the following rewrite rule, it either gets stuck in an endless loop, having to restart apache2. Amazingly, the behaviour has changed and I am not sure why. Now it just appends the new string to the existing URL.
For example: /john.doe will become /john.doe/?pg=user&username=john.doe
RewriteRule ^/([a-z0-9_]+)$ /?pg=user&username=$1 [NC,PT]
I am going crazy trying to fix this, please help!

This should work (I'm saying "should" as I do not know how your whole system is set up and what other redirects etc are in place -- I see you are using PT flag (maybe you are using aliases)):
RewriteCond %{REQUEST_URI} !^/index\.php
RewriteRule ^([a-z0-9_\.]+)$ /index.php?pg=user&username=$1 [NC,QSA,L]
OR
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([a-z0-9_\.]+)$ /index.php?pg=user&username=$1 [NC,QSA,L]
I have specified the script file directly -- it's much more easier to write a rule if you know how it works behind.

Related

Block direct access to .php files, less the index.php file and ajax.php file

been looking for your help, i found a method, but it is not as i wish. if someone can help me.
What I want is that nobody can enter a direct URL with .php
example when I enter my domain.com/buy/product.php, I want it to be forbidden,
I was looking for information here, I found this code that worked for me but in .htaccess
RewriteEngine On
RewriteCond %{THE_REQUEST} "^.+? [^?]+\.php(?:[?/# ]|$)" [NC]
RewriteRule !^index\.php$ - [F,L,NC]
it worked fine for me, but the problem that I in a directory /include/ajax.php , I use an ajax. and it gives me error to execute the ajax by browsing.
Now what I'm thinking how to make it work with that htaccess code that you can enter the index.php and /include/ajax.php, I tried all means but it does not work for me.
In another case if you know any code to add to my php or how to do for my version which is version 7.3, but without ruining my code.
Rather than giving you the answer straight out, I'm going to give you some hints so that you aren't copying code you don't understand.
Each RewriteRule has three parts:
the pattern to match against the URL sent by the browser
the URL to rewrite to
an optional set of flags for extra options
Before each rule, you can optionally have one or more RewriteCond lines which apply extra conditions to the rule; each has three parts:
a variable to match against
the pattern to match
an optional set of flags for extra options
The most important flag in this case is [F], short for [forbidden], which says "if the rule matches, instead of rewriting or redirecting, just server a 403 response.
You should very rarely need to test against %{THE_REQUEST}, which is a raw version of the request line from the browser; much more often, you want %{REQUEST_URI} and/or %{QUERY_STRING}.
The patterns in both RewriteRule and RewriteCond can be negated (i.e. "must not match this pattern") by starting them with !
So, if you wanted to return a 403 for all URLs ending ".bad", except for URLs ending "not.bad" or "only-a-little.bad", you could write this (note that $ is the way to say "must end here" in the regex patterns):
RewriteCond %{REQUEST_URI} !not.bad$
RewriteCond %{REQUEST_URI} !only-a-little.bad$
RewriteRule .bad$ - [F]
Hopefully it should be straight-forward enough to see how to adapt that to your requirements.
The full list of options and variables available is in the Apache manual.
After 2 days of looking for some code, I was able to read and understand.
study how htaccess works.
Thanks to the users who guided me, I found the solution.
Although my title is not quite correct.
My intention was always to block all .php that always the user wanted to enter directly by .PHP, I had found the code above, but it did not work with a specific file in the /include/ajax.php folder, exactly it was an ajax, I could not find solution.
exactly it was an Ajax, I could not find the solution to make it work.
Until I managed to solve this way.
RewriteEngine on
RewriteCond %{THE_REQUEST} ajax\.php [NC]
RewriteRule ^ - [NC,L]
RewriteCond %{THE_REQUEST} .+\.php [NC]
RewriteRule ^ - [F,L]
This causes all .php to be blocked, except the index.php and the /include/ajax.php file.
This is how it worked for me.
If I am right or wrong, can you give me some guidance.
I leave this in case someone might find it useful in the future.
I was always recommended to route my php, that I would forget about these problems.
I will keep it in mind as I move forward in the future, to route my php.

RewriteRule to remove all slashes

Hi I have tried everything and can't find a solution.
When a user access this URL
http://www.mydomain.com/B/13/B0/BD62CB5382479EFE5EE122BE6FB.jpg?pid=5623
I want it to rewrite it to (not using redirect)
http://www.mydomain.com/B13B0BD62CB5382479EFE5EE122BE6FB.jpg?pid=5623
how do I remove the '/' ?
Your help is very appreciated .
Try with this rule (your htaccess must be located in your document root folder)
RewriteCond %{QUERY_STRING} ^pid=([0-9]+)$
RewriteRule ^/?([^/]+)/([^/]+)/([^/]+)/([^/]+)\.jpg$ /$1$2$3$4.jpg?pid=%1 [L]
EDIT: this code will only work with urls like in your example (with 3 slashes and pid in query string)
EDIT2: to simplify query string if you have multiple params (maybe in different order) we don't need RewriteCond anymore but QSA flag instead
RewriteRule ^/?([^/]+)/([^/]+)/([^/]+)/([^/]+)\.jpg$ /$1$2$3$4.jpg [L,QSA]
If that rule should remove any number of slashes, not just a fixed number, you have to create a loop. TO do so, you can use the \[N\] flag, which will cause the rewriting process to start all over with the current URL. Be careful when doing this, this could lead to infinite loops when done wrong ;)
RewriteRule ^/?(.*)/(.*) $1$2 [N]
Should work however. You can test it with this online tool.
[Edit]: Complete rewrite - I forgot about the [N] Flag ;)

.htaccess RewriteCond – adding multiple exceptions

My question is very simple, but I want to get it absolutely right the first try, because I'm working on a live website and bad things could happen if I blew this :)
So, as a part of a RewriteRule that forwards all my regular visitors to /myfolder/, there is an important line preventing the rule from being applied if you're already in that folder:
RewriteCond %{REQUEST_URI} !^/myfolder/
That works fine. What I want is to add my dev folder to that exception, so myself and my clients can access my development projects while all other URI's still get forwarded to /myfolder/
I'm guessing I need to modify the RewriteCond along the lines of:
RewriteCond %{REQUEST_URI} !^/myfolder/
(here I basically need 'OR' in the right syntax) !^/dev/
What's the correct syntax for this?
You can actually use this condition:
RewriteCond %{REQUEST_URI} !^/(myfolder|dev)/ [NC]

.htaccess pretty url problem (mod_rewrite)

I have a directory that lists products by categories. if a _GET variable exists, it is used in a query. I would like to use "pretty url's", like: example/a/1/b/2/c/3/d/4 becomes example/index.html?a=1&b=2&c=3&d=4
most .htaccess examples I see only use variables to replace the _GET values, but I can use rules like this:
Options +FollowSymlinks
RewriteEngine on
RewriteRule ([^/]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+)$ index.html?$1=$2&$3=$4&$5=$6 [L]
RewriteRule ([^/]+)/([^/]+)/([^/]+)/([^/]+)$ index.html?$1=$2&$3=$4 [L]
RewriteRule ([^/]+)/([^/]+)$ index.html?$1=$2 [L]
And it works... However, the when I add longer and longer RewriteRules (like out to &17=$18), it stops working. The last variables in the chain turn into some sort of array based on earlier values (in above it would build index.html?a0=a1&a3=a4)...
Is there a better way to do this?
It seems inefficient?
Is there a limit to the number of variables in .htaccess
How long a rule can be?
Thanks!
mod_rewrite only supports up to $9 and %9.
I recommend you either modify your script to use $_SERVER['PATH_INFO'], or you use RewriteMap to invoke a script to transform the path into a querystring.
mod_rewrite only allows for you to have ten back-references, one of which is the whole matchable part (which ends up leaving you with only nine definable capture groups), so you're definitely limited by that.
However, to me it would make much more sense to examine the server's REQUEST_URI/SCRIPT_NAME/PATH_INFO variable in your script file, and parse that to get the key-value pairs from the URL. Then, you'd simply have this in your .htaccess:
RewriteRule On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule . index.html [L]
And then your script would take care of the rest. I do have to wonder though, if you have that many GET variables, is it actually more readable if they're all made into a "pretty" URL? After all, if you have twenty-some forward slashes in the URL, you may be equally well off just passing a normal query string at that point. It depends on your application though and how users interface with these URLs, so you may have good reason for wanting to do it this way.

Why would mod_rewrite rewrite twice?

I only recently found out about URL rewriting, so I've still got a lot to learn.
While following the Easy Mod Rewrite tutorial, the results of one of their examples is really confusing me.
RewriteBase /
RewriteRule (.*) index.php?page=$1 [QSA,L]
Rewrites /home as /index.php?page=index.php&page=home.
I thought the duplicates might have had been caused by something in my host's configs, but a clean install of XAMPP does the same.
So, does anyone know why this seems to parse twice?
And, to me this seems like, if it's going to do this, it would be an infinite loop -- why does it stop at 2 cycles?
From Example 1 on this page, which is part of the tutorial linked in your question:
Assume you are using a CMS system that rewrites requests for everything to a single index.php script.
RewriteRule ^(.*)$ index.php?PAGE=$1 [L,QSA]
Yet every time you run that, regardless of which file you request, the PAGE variable always contains "index.php".
Why? You will end up doing two rewrites. Firstly, you request test.php. This gets rewritten to index.php?PAGE=test.php. A second request is now made for index.php?PAGE=test.php. This still matches your rewrite pattern, and in turn gets rewritten to index.php?PAGE=index.php.
One solution would be to add a RewriteCond that checks if the file is already "index.php". A better solution that also allows you to keep images and CSS files in the same directory is to use a RewriteCond that checks if the file exists, using -f.
1the link is to the Internet Archive, since the tutorial website appears to be offline
From the Apache Module mod_rewrite documentation:
'last|L' (last rule)
[…] if the RewriteRule generates an internal redirect […] this will reinject the request and will cause processing to be repeated starting from the first RewriteRule.
To prevent this you could either use an additional RewriteCond directive:
RewriteCond %{REQUEST_URI} !^/index\.php$
RewriteRule (.*) index.php?page=$1 [QSA,L]
Or you alter the pattern to not match index.php and use the REQUEST_URI variable, either in the redirect or later in PHP ($_SERVER['REQUEST_URI']).
RewriteRule !^index\.php$ index.php?page=%{REQUEST_URI} [QSA,L]