mod_rewrite not matching regexp - php

I have a regexp that seems to work fine when tested at regexp101.com
but that does not give me the same result within mod_rewrite.
So, the URL I am trying to rewrite is:
/modeles-voiture/Nissan/Qashqai+2
The expected result is:
/modeles.php?brand=Nissan&model=Qashqai+2
The rewrite rule:
RewriteCond %{REQUEST_URI} ^/?modeles-voiture [NC]
RewriteRule \/([A-Z][\-A-Za-z]+)\/([\+\-A-Za-z0-9]+$) /modeles.php?brand=$1&model=$2 [L]
What I am getting out of the rewrite rule is:
/modeles-voiture/Nissan/Qashqai 2
Note the missing + sign, which throws off my script at modeles.php
Thanks for your help.

I think you want the [B] flag.
Look at the answer to this question: How to encode special characters using mod_rewrite & Apache?
So then mod_rewrite changes your request '/tag/c++' to 'script.php?tag=c++'. But in a query string component in the application/x-www-form-encoded format, the escaping rules are very slightly different to those that apply in path parts. In particular, '+' is a shorthand for space (which could just as well be encoded as '%20', but this is an old behaviour we'll never be able to change now).
So PHP's form-reading code receives the 'c++' and dumps it in your _GET as C-space-space.

Related

Need to pass backslashes in query string with pretty urls

I'm trying to pass a backslash as part of a query string argument.
The project uses a pretty simple url_rewriting method:
//.Htaccess
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* index.php?arguments=$0 [NC,L]
Then receive $_GET['arguments'] with values separated by /
Ex.: blog/post/2/ will fill $_GET['arguments'] with: 'post/2/'
The problem is, when I try to pass something like test%5Cabc (url encoded for test\abc), the request returns a 404 error instead of passing it as an argument
I have no idea how to fix it. Thanks in advance.
The reason you get a 404 error is because by default, Apache has AllowEncodedSlashes turned off, and its behavior is to 404 any request containing a backslash. This is because having it turned on is a potential security hazard. In Apache 2.2.18 and later, there is a NoDecode setting which makes this a bit safer, and works well for your case.
Anyway I tried turning it on locally, and indeed this script:
<?php var_dump($_REQUEST); ?>
is able to handle urls like
http://localhost/this\is\a\test
and outputs
array(1) { ["arguments"]=> string(14) "this\is\a\test" }
However, it (or my browser) seems to have problems with encoded backslashes, converting them to regular backslashes - maybe that's not a problem. If you enable the B flag on your rewriterule, it will convert unencoded backslashes to encoded backslashes.
I hope I got you right, try using this :
'/file.php?id=$value'//this utilise that backslash and then pass the id to the `$_Get[]` Function somewhere in the file.php.

CodeIgniter Mod Rewrite Rules and the Controller

Learning PHP, I am playing around with mod_rewrite and CodeIgniter. I have configured my .htaccess file correctly with
RewriteEngine On
RewriteRule ^(resources)/(.*) $1/$2 [L]
RewriteRule ^(user_guide)/(.*) $1/$2 [L]
RewriteRule (.*) index.php?$1 [L]
I understand a bit of regex, and can appreciate what happens here. The rewrite rules are applied and the server than handles the final URL which in the above case- attaches index.php (the front controller) to the "pretty" URL. So far so good.
I now want a URL pattern :
/<person-name>/at/<place>
to get translated to :
/index.php/person/list?personName=$1&place=$2
And i handle the request at my list function in the person controller. I do not understand why the following doesn't work:
RewriteRule ^([a-z]+)/(at)/([a-z]+)$ index.php/person/list?personName=$1&place=$2 [L]
What am i doing wrong/where is my understanding flawed? I see that the placeholders are extracted correctly ($1 and $3), however, it throws a CodeIgniter 404.
Many thanks!
It's possible that the simplest fix will fix your issue. By wrapping "at" in parentheses, you're creating another matching group, which means that $2 will always be "at." That could be breaking everything. You want index.php?person/list?personName=$1&place=$3 But you may have noticed that issue and fixed it without fixing the problem, in which case, read on.
Check out How to make CodeIgniter accept "query string" URLs?. It seems to indicate that you can't mix and match the segment-based approach and the query string approach. Without seeing your controller code, I can't say for certain, but I'd start investigating there. You might also try:
RewriteRule ^([a-z]+)/(at)/([a-z]+)$ index.php?person/list/$1/$3 [L]
which would do the same thing the general-purpose CI redirect rule below does; send the URL off to index.php as a query string for processing. You've said you got it working with routes, so rather than passing a query string to your controller, you can expect person and place as two arguments. CI's handling of query strings leaves a lot to be desired, and I've never tried to MOD_REWRITE something including a query string into a query string.

mod_rewrite .htaccess redirect part of a query string

I'm struggling with a redirect problem. I need to redirect the following URL with mod_rewrite thorough .htaccess
http://www.mysite.com/somescript.php?&lang=php&var=1&var=2
to the following
http://www.mysite.com/somescript.php?lang=php&var=1&var=2
So, basically I just need to remove the
&
before
lang=php
However, the order is important. Sometimes
&lang=php
appears after other variables in the querystring. in this scenario I need the
&
to remain part of
&lang=php
Is this possible?
To summarise, if &lang=php appears at the beginning of the query string, remove the &. If &lang=php appears anywhere else in the query string, the & must remain.
Hope this is clear!
I would change the script myself but unfortunately I am not the developer, and he doesn't seem too helpful at the moment; this is a quick fix.
I would replace ?& with ?:
RewriteCond %{QUERY_STRING} ^\&(.*)$
RewriteRule ^somescript\.php$ /somescript.php?%1 [L,R=301]
why don't you match "?&" and replace it by "?" ?
Something like:
RewriteRule ^(.*)?&(.*) $1?$2 [L]
(not tested)
Because I think the combination "?&" is never valid...(?)

Trouble with encoding special chars for URL through text input

I'm building a PHP application using CodeIgniter. It is similar to Let Me Google That For You where you write a sentence into a text input box, click submit, and you are taken to a URL that displays the result. I wanted the URL to be human-editable, and relatively simple. I've gotten around the CodeIgniter URL routing, so right now my URLs can look something like this:
http://website.com/?q=this+is+a+normal+url
The problem right now is when the sentence contains a special character like a question mark, or a backslash. Both of these mess with my current .htaccess rewrite rules, and it happens even when the character is encoded.
http://website.com/?q=this+is+a+normal+url? OR
http://website.com/?q=this+is+a+normal+url%3F
What does work is double-encoding. For example, if I take the question mark, and encode it to %253F (where the ? is encoded to %3F and the % sign is encoded to %25). This url works properly.
http://website.com/?q=this+is+a+normal+url%253F
Does anyone have an idea of what I can do here? Is there a clever way I could double encode the input? Can I write a .htaccess rewrite rule to get around this? I'm at a loss here. Here are the rewrite rules I'm currently using for everyone.
RewriteEngine on
RewriteCond %{QUERY_STRING} ^q=(.*)$
RewriteRule ^(.*)$ /index.php/app/create/%{QUERY_STRING}? [L]
Note: The way CodeIgniter works is they have a index/application/function/parameter URL setup. I'm feeding the function the full query string right now.
If your’re using Apache 2.2 and later, you can use the B flag to force the backreference to be escaped:
RewriteCond %{QUERY_STRING} ^q=.*
RewriteRule ^ /index.php/app/create/%0? [L,B]
I usually do human readable urls like this
$humanReadableUrl= implode("_",preg_split('/\W+/', trim($input), -1, PREG_SPLIT_NO_EMPTY));
It will remove any non-word characters and will add underscores beetween words

Is it possible to use .htaccess to send six digit number URLs to a script but handle all other invalid URLs as 404s?

Is it possible to use .htaccess to process all six digit URLs by sending them to a script, but handle every other invalid URL as an error 404?
For example:
http://mywebsite.com/132483
would be sent to:
http://mywebsite.com/scriptname.php?no=132483
but
http://mywebsite.com/132483a or
http://mywebsite.com/asdf
would be handled as a 404 error.
I presently have this working via a custom PHP 404 script but it's kind of kludgy. Seems to me that .htaccess might be a more elegant solution, but I haven't been able to figure out if it's even possible.
In your htaccess file, put the following
RewriteEngine On
RewriteRule ^([0-9]{6})$ /scriptname.php?no=$1 [L]
The first line turns the mod_rewrite engine on. The () brackets put the contents into $1 - successive () would populate $2, $3... and so on. The [0-9]{6} says look for a string precisely 6 characters long containing only characters 0-9.
The [L] at the end makes this the last rule - if it applies, rule processing will stop.
Oh, the ^ and $ mark the start and end of the incoming uri.
Hope that helps!
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteRule ^([0-9]{6})$ scriptname.php?no=$1 [L]
</IfModule>
To preserve the clean URL
http://mywebsite.com/132483
while serving scriptname.php use only [L].
Using [R=301] will redirect you to your scriptname.php?no=xxx
You may find this useful http://www.addedbytes.com/download/mod_rewrite-cheat-sheet-v2/pdf/
Yes it's possible with mod_rewrite. There are tons of good mod_rewrite tutorials online a quick Google search should turn up your answer in no time.
Basically what you're going to want to do is ensure that the regular expression you use is just looking for digits and no other characters and to ensure the length is 6. Then you'll redirect to scriptname.?no= with the number you captured.
Hope this helps!

Categories