Htaccess entry for blocking user agent not working - .htaccess

The user agent blocking code in my .htaccess file stopped working, though I didn't make any recent changes to it. To troubleshoot this I changed the user agent in FF and created a sub-directory with its own .htaccess file and one php file. In that file I added code to display the $_SERVER['USER_AGENT'] string. It shows the UA I am using and is:
Mozilla/5.0 (compatible; Konqueror/4.2; Linux) KHTML/4.2.96 (like Gecko)
In my .htaccess file I have the following but when I visit that location I am not blocked.
RewriteEngine On
RewriteCond %{HTTP_USER_AGENT} "^Konqueror$" [NC]
RewriteRule ^ - [F]
I added the following, with my real IP, after the above to verify the rewrite was working and it blocked me:
RewriteCond %{REMOTE_ADDR} ^12\.23\.45\.666
RewriteRule ^ - [F]
Does anyone know what the problem is?

This won't work due to the "^" at the start and the "$" at the end of your matching pattern in the RewriteCond. These two special characters anchor a regular expression to the beginning and the end of the subject, so the search string. So your condition will only match of the header contains the exact string "Konqueror" with nothing before or after that. That is not what you want.
The word "Konqueror" appears in the middle of that string you send as a user agent. So you want to match any string that contains the word "Konqueror" most likely. Just leave both special characters away and you are happy.
You can also remove the quote characters, they are not required.
So simply use that condition:
RewriteCond %{HTTP_USER_AGENT} Konqueror [NC]

Related

Use htaccess to change query parameter to iOS app-specific deep-link [duplicate]

I am trying to do the following:
User visits URL with query parameter: http://www.example.com/?invite=1234
I then want them to be deep linked into the app on their iOS device, so they go to: app_name://1234
Any suggestions on how to accomplish this in my .htaccess file?
I tried this but it doesn't work:
RewriteEngine On # Turn on the rewriting engine
RewriteRule ^invite/(.*)/$ app_name://$1 [NC,L]
If RewriteRule won't work, can anyone send me an example code for RewriteCond or JavaScript to achieve what I need?
Not sure how this will work with the iOS device, but anyway...
RewriteRule ^invite/(.*)/$ app_name://$1 [NC,L]
This doesn't match the given URL. This would match a requested URL of the form example.com/invite/1234/. However, you are also matching anything - your example URL contains digits only.
The RewriteRule pattern matches against the URL-path only, you need to use a RewriteCond directive in order to match the query string. So, to match example.com/?invite=1234 (which has an empty URL-path), you would need to do something like the following instead:
RewriteCond %{QUERY_STRING} ^invite=([^&]+)
RewriteRule ^$ app_name://%1 [R,L]
The %1 backreference refers back to the last matched CondPattern.
I've also restricted the invite parameter value to at least 1 character - or do you really want to allow empty parameter values through? If the value can be only digits then you should limit the pattern to only digits. eg. ^invite=(\d+).
I've include the R flag - since this would have to be an external redirect - if it's going to work at all.
However, this may not work at all unless Apache is aware of the app_name protocol. If its not then it will simply be seen as a relative URL and result in a malformed redirect.

RewriteRule and Hash

I have a webpage which has ugly urls like this
DOMAINNAME/gallery.php#filter=.filtername
I want them to look like this
DOMAINNAME/artwork/filtername/
I've tried this in my .htaccess file
RewriteRule ^artwork/([^.]+)/ gallery.php#filter=.$1 [NE]
But this doesn't do the trick. It just goes to DOMAINNAME/artwork/
If you are adding # in URL then you must do a full redirect since # part is only interpreted in browser:
RewriteRule ^artwork/([^./]+)/?$ /gallery.php#filter=.$1 [L,NE,NC,R=302]
I just tried this in my environment and it seems, Apache swallows everything after and including #, when it does an internal rewrite.This happens no matter, whether you use flag NE or not.
So the only solution seems to be using a regular query string, e.g.
RewriteRule ^artwork/([^.]+)/ gallery.php?filter=.$1 [L]
or separate the filter with a slash
RewriteRule ^artwork/([^.]+)/ gallery.php/filter=.$1 [L]

.Htaccess redirect with multiple query strings

I tried doing searching and trying to understand how to do a redirect with (multiple) query strings but I didn't have luck. I'm hoping someone here can help me understand this issue :)
I'm working on this ecommerce shop and people are searching the ecommerce search input for content located in a different CMS. For example, the word "returns". This isn't a product in the ecommerce system so of course it returns an error for the results (no products found).
My idea was simply to manually redirect those quieres to the proper landing pages in the CMS.
Here's an example of the URL for "return" on the ecommerce system:
http://www.domain.com/catalog/search.php?mode=search&page=1&substring=return
And here's where I would like to send people:
http://www.domain.com/catalog/Returns.html
Any thoughts on how to do this? Thanks in advance!
Solution
The way to do this is as Phil suggested; but with a few (small) modifications:
RewriteEngine On
RewriteCond %{QUERY_STRING} substring=returns? [NC]
RewriteRule . /catalog/Returns.html? [L]
RewriteCond %{QUERY_STRING} substring=shipping [NC]
RewriteRule . /catalog/Shipping.html? [L]
N.B. In the event you only want to remove one parameter see the Additional Information and Explanations below.
N.B. For more strict matching see Where & becomes a problem below.
Explanation
Background
The best way for me to explain the difference (between the above and Phil's original) and why you were having a problem is to explain what is going on...
RewriteCond %{QUERY_STRING} substring=returns? [NC] checks the query string for instances of the regex that follows it in this case substring=returns?*.
The [NC] flag simply means to match upper and lower case letters.
*Clarification: The regex(substring=returns?) means substr=return is matched literally with or without an s.
Problem
If the condition is met (i.e. the regex pattern is matched in the query string) then the rewrite rule is triggered. This is where the problem lies...
Given the URL: http://example.com/?substring=returns
The original rule:
RewriteRule . /catalog/Returns.html [L]
Rewrites the URL leaving the query string in place, like so:
http://example.com/?substring=returns
http://example.com/catalog/Returns.html?substring=returns
http://example.com/catalog/Returns.html?substring=returns
http://example.com/catalog/Returns.html?substring=returns
http://example.com/catalog/Returns.html?substring=returns
...and so on until limit is reached...
Side note: The [L] flag stops the .htaccess file from going through any more rules but it doesn't stop it looping again.
Solution
The solution then is to overwrite the query string (since we no longer need it) you can do this simply by adding a ? to the end of the RewriteRule:
RewriteRule . /catalog/Returns.html? [L]
N.B. In the event you only want to remove one parameter see the Additional Information and Explanations below.
N.B. For more strict matching see Where & becomes a problem below.
Resources
The following resources may come in helpful in the future:
.htaccess flags
http://httpd.apache.org/docs/current/rewrite/flags.html
Regular expressions
http://www.regular-expressions.info/ - Check out the tutorials section
Additional Information and Explanations
Where & becomes a problem
RewriteCond %{QUERY_STRING} &substring=returns? [NC]
In the above the regex means to match the characters &substring=return with an optional s appended to it.
So it would match the following as expected:
http://example.com/?var1=somvalue&substring=return
http://example.com/?var1=somvalue&substring=returns
http://example.com/?var1=somvalue&substring=return&var2=othervalue
http://example.com/?var1=somvalue&substring=returns&var2=othervalue
Which is fine and given the original query string wouldn't be a problem, however, if I were to navigate to the page and write in the parameters in a different order, the & wouldn't necessarily be there and therefore it wouldn't match (when it should):
http://example.com/?substring=return&var1=somevalue
http://example.com/?substring=returns&var1=somevalue
Simply getting rid of it (as I did) would solve this problem, but it doesn't come risk free.
RewriteCond %{QUERY_STRING} substring=returns? [NC]
If you were to introduce a new parameter secondsubstring for example it would match when it shouldn't:
Good Match > http://example.com/?substring=return&var1=somevalue
Good Match > http://example.com/?var1=somevalue&substring=return
Bad Match > http://example.com/?secondsubstring=return&var1=somevalue
To solve this potential issue you could do the following:
RewriteCond %{QUERY_STRING} ^(.*&)?substring=returns?
The above will match:
http://example.com/?substring=return&var1=somevalue
http://example.com/?var1=somevalue&substring=return
But won't match:
http://example.com/?secondsubstring=return&var1=somevalue
One more potential problem is that the expression would match:
http://example.com/?substring=returning&var1=somevalue
http://example.com/?substring=return%20television&var1=somevalue
My understanding, again, is that this wouldn't be a problem in the given situation. However if it were to be a problem you could do:
RewriteCond %{QUERY_STRING} ^(.*&)?substring=returns?(&|$)
The above checks that the character following return/returns is either an & signalling the end of the variable and the start of a new one or the end of the query string.
Rewriting one parameter
In some circumstances as Phil pointed out it may be preferable to only remove one parameter at a time and leave the rest of the query string untouched.
You can do this, quite simply, by implementing capture groups in the RewriteCond and outputting them in the RewriteRule:
RewriteCond %{QUERY_STRING} ^(.*&)?substring=returns?(&.*)?$ [NC]
RewriteRule . /catalog/Shipping.html?%1%2 [L]
Rewrite explanation
You use %N to insert capture groups from the rewrite condition and $N to insert capture groups from the rewrite rule.
So in this case we redirect to:
/catalog/shipping.html?(RewriteCond Group1)(RewriteCond Group2)
/catalog/Shipping.html?%1%2
The [L] flag - as previously - stops the processing of any rules further down the .htaccess file
Regex explanation
^(.*&)?substring=returns?(&.*)?$
^ Start of string
(.*&)? First capture group
Capture any character . 0 or more times *
Followed by an &
The ? makes the entire group optional
substring=returns? Matches substring=return literally with an optional s
(&.*)? Second capture group
Capture an &
Capture any character . 0 or more times *
The ? again makes the group optional
$ End of string
[L] flag vs [END]
For completeness sake...
The [L] flag stops the .htaccess from going over any more rules further down the .htaccess file.
The [END] flag stops the rewrite process completely.
To illustrate with an example:
while(TRUE){
if(condition1){ continue; }
if(condition2){ continue; }
if(condition3){ continue; }
if(condition4){ continue; }
}
while(TRUE){
if(condition1){ break; }
if(condition2){ break; }
if(condition3){ break; }
if(condition4){ break; }
}
In the above code blocks the [L] flag acts like a continue statement in that it skips the rest of the code block and starts again. Whilst the [END] flag acts as a break statement and stops the loop entirely.
If we were to replace the [L] flag with [END] in Phil's original answer then it would work. With the caveats mentioned in the Where & becomes a problem section above.
RewriteEngine On
RewriteCond %{QUERY_STRING} &substring=returns? [NC]
RewriteRule . /catalog/Returns.html [L]
RewriteCond %{QUERY_STRING} &substring=shipping [NC]
RewriteRule . /catalog/Shipping.html [L]
etc.
Would something like that do the job for you? Note that 'returns?' means 'return' or 'returns'. Are you limited to one search term at a time, or might customers type in a phrase? I think & is safe to use there, but it's possible it's not.
Don't forget to do this stuff ahead of any commands to rewrite Returns.html to Returns.php, do SEO, etc.

How to write this .htaccess rewrite rule

I am setting up a MVC style routing system using mod rewrite within an .htaccess file (and some php parsing too.)
I need to be able to direct different URLs to different php files that will be used as controllers. (index.php, admin.php, etc...)
I have found and edited a rewrite rule that does this well by looking at the first word after the first slash:
RewriteCond %{REQUEST_URI} ^/stats(.*)
RewriteRule ^(.*)$ /hello.php/$1 [L]
However, my problem is I want it to rewrite based on the 2nd word, not the first. I want the first word to be a username. So I want this:
http://www.samplesite.com/username/admin to redirect to admin.php
instead of:
http://www.samplesite.com/admin
I think I just need to edit the rewrite rule slightly with a 'anything can be here' type variable, but I'm unsure how to do that.
I guess you can prefix [^/]+/ to match and ignore that username/
RewriteCond %{REQUEST_URI} ^/[^/]+/stats(.*)
RewriteRule ^[^/]+/(.*)$ /hello.php/$1 [L]
then http://www.samplesite.com/username/statsadmin will be redirecte to http://www.samplesite.com/hello.php/statsadmin (or so, I do not know the .htaccess file)
To answer your question, "an anything can be here type variable" would be something like a full-stop . - it means "any character". Also the asterisk * means "zero or more of the preceding character or parenthesized grouped characters".
But I don't think you need that...If your matching url will always end in "admin" then you can use the dollar sign $ to match the end of the string.
Rewrit­eRule admin$ admin.php [R,NC,L]
Rewrites www.anything.at/all/that/ends/in/admin to www.anything.at/admin.php

Mod_Rewrite to /subdirectory and /subdirectory/query

I'm having a difficult time getting into using mod_rewrite. I've been at this for about an hour googling stuff but nothing quite seems to work. What I want to do is change
example.com/species.php into example.com/species
and also
example.com/species.php?name=frog into example.com/species/frog.
Using
Options +FollowSymlinks
RewriteEngine on
RewriteRule ^species/(.*)$ /species.php?name=$1
I can get example.com/species.php?name=frog to display as example.com/species/frog, and with
RewriteRule ^species/ /species.php
I can get example.com/species.php to display as example.com/species/, but I can't get both of them to work at the same time.
Also, example.com/species with no trailing slash always comes up as a 404.
I've considered just making a /species/ directory to catch any problems but I'd rather just have a few rules for one species.php file. Any help would gladly be appreciated!
Edit (because I can't answer my own question for 8 more hours):
I seem to have fixed both of my problems. I changed my .htaccess to:
Options +FollowSymlinks
RewriteEngine on
RewriteRule ^species/(.*)$ /species.php?name=$1
RewriteRule ^species/?$ /species.php
The second RewriteRule successfully redirects example.com/species to example.com/species.php while leaving the other RewriteRule working at the same time.
However, if I typed in example.com/species/ with a trailing slash, it was being read as example.com/species.php?name= and would throw an error because no name was submitted, so I just added
if(isset($_GET['name']) && empty($_GET['name'])) {header('location: http://example.com/species');}
so that if I used example.com/species/ it would redirect to /species and work as desired.
If you change the * (match zero or more) to a + (match one or more) in your first RewriteRule then you should stop seeing species.php?name= if a trailing slash is used.
This is because the + will require that something appears after the slash, otherwise the rule will not match. Then your second RewriteRule will match because it ends with an optional slash, but will not add the name= query string to the target URL.
You may also want to add the [L] flag (last) after the first rule, because you don't need the second rule to execute if the first rule matches. (Note that this will not stop the RewriteCond and RewriteRule tests being run on the resulting redirect URL, which will have to go through the .htaccess file just like any other request.)
See the Reference Documentation for mod_rewrite in Apache 2.4 (or see the docs for the version of Apache you're actually using).

Resources