PHP $_GET var with urlencode and "&" bug - php

In my code, I create a link like this:
$link = 'http://www.mydomain.com/'.urlencode($str).'/1';
I use url-rewriting and the rule in my htaccess file looks like this:
rewriteRule ^(.+)/(.*)$ index.php?var1=$1&var2=$2 [NC,L]
This code is working fine for almost every strings. But sometimes, the string to encode contains "&". The urlencode function encodes it corectly, but when I read the $_GET array in php, it looks like this (with $str = 'substring1&substring2'):
'var1' => 'substring1' (without "&")
'substring2' => '' (without "&")
'var2' => 1
I really need the "&" in my var. Is there a way to encode that character to make it works?
Also, I really don't know why, but sometimes I get a forbidden http error with some strings passed as var1. Apparently, they have nothing special, for exemple, "Décarie Square" makes that error. Other strings with spaces and "é" are working fine.

Apache's mod_rewrite automatically decodes urlencoded strings when it does regex matching. But it only does this once, so you should be if you urlencode your string twice. This will re-escape all of those `%' characters.
try
$link = 'http://www.mydomain.com/'.urlencode(urlencode($str)).'/1';
or stop relying on rewrite rules and use a framework that handles URL routing properly.
Oh, and there should also be htmlentities() somewhere in there.

Apache will automatically translate (decode) the path. You must use a different encoding or even double encoding. Base 64 will work.

your $str isn't setup with key=val pairs
Try $str = 'var1=substr1&var2=substr2';

Two options:
Urlencode the string before urlencoding the query.
Replace all non alphanumerical chars with a dash or underscore
As for the forbidden error are you using http auth basic or digest?
Update may mistake try using htmlentities or htmlspecialchars instead of urlencode

Related

How to find another way of using "&" in post request in Swift

I am doing a post HTTP request in swift 4.2 and in one of my Strings I put in the parameters contain "&" but apparently the requests gets cut off after this symbol. I thought about replacing every "&" symbol with a unique placeholder and convert it back in PHP.
But is there are more elegant or easy way of doing this?
URL encode your data (and decode it when you need to use it), that will make the ampersand into %26 which will stop it cutting off in your GET request.
You could replace the "&" with "%26" and then it's have to work :)
All Precent-encoding characters:
https://en.wikipedia.org/wiki/Percent-encoding#Percent-encoding_reserved_characters
You should probably minimize how much manual percent escaping you do. You might, for example, use URLComponents to build your URL and percent escape it for you:
guard var components = URLComponents(string: "http://example.com") else { return }
components.queryItems = [URLQueryItem(name: "foo", value: "bar&baz")]
let url = components.url
That will result in:
http://example.com?foo=bar%26baz
The ampersand, as well as a few other characters, need to be encoded if they are within a query parameter otherwise they could be recognized as a delimiter of some sort.
You can encode a string for a query param in Swift like this:
let value = string.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)
let urlString = "https://example.com/?query=\(value)"
On the other side, your server will receive the encode param value but will need to decode it.
PHP includes the urlencode() and urldecode() functions, and stift includes the .addingPercentEncoding function.
This means you can replace with the encoded version of the '&' symbol which is '%26', or you can use swift's function
Then when you recieve this value you can use urldecode( $escapedString ), or just replace '%26' with '&', or just pull the values stright from the request with $_GET.

Pass string, containing a slash as get-param

I'm wondering if it's possible to parse a string containing an URL as GET parameter using Mod-Rewrite through CakePHP. Do I have to pass this via $this->request->data (POST)?
Is it common to set Routes for such cases or would you either recommend splitting the URL into separate parameters?
A slash in $_GET? Woudn't that just be a query string containing such a slash?
See http://book.cakephp.org/2.0/en/controllers/request-response.html#accessing-querystring-parameters
By default those query strings are properly escaped, so all is well without any hacks on your end.
You can use rawurlencode() to esacpe special characters.

PHP Remove all non letters

I have several strings that look like this:
Lasklé
Jones & Jon
I am trying to send them via the foursquare API to be matched, however it is failing with these characters. Is there a way to sanitise these so they only include English letters i.e. the results would be:
Lasklé
Jones Jon
As it appears using file_get_contents requests both with the 'é' and the '&' in the URL is causing issues.
I checked how the request was sent and realised that the '&' is uneeded and is causing the issues, is it possible to remove all non Letters/Numbers from the name?
What do the strings look like before you pass them? If your string looks like 'Lasklé' then I think you are using the wrong character set when reading the string, try using UTF-8.
If the string looks correct before you pass it on you should try urlencode the string first.
you can use preg_replace() function to replace the part of string using regex
to keep only letters you can use as follow it will also remove space( add \s from expression to keep space)
preg_replace('/[^a-zA-Z]/','',$string);
to keep space in the string or any character to keep you can add it in []
preg_replace('/[^a-zA-Z\s]/','',$string);
Use this to escape (space and '-'). Good for making a custom URL
$string=preg_replace("/[^A-Za-z0-9\s\/\-]/", '', $string);

Using ampersand in pretty URL breaks URL

I have seen plenty of people having this problem and it seems the only way to stop apache treating the encoded ampersand and a URL ampersand is it use the mod rewrite B flag, RewriteRule ^(.*)$ index.php?path=$1 [L,QSA,B].
However, this isn't available in earlier versions of apache and has to be installed which is also not supported by some hosting companies.
I have found a solution that works well for us. We have a url of /search/results/Takeaway+Foods/Inverchorachan,+Argyll+&+Bute+
This obviously breaks the url at & giving us /search/results/Takeaway+Foods/Inverchorachan,+Argyll which then gives a 404 error as there is no such page.
The url is held in the $_GET['url'] array. If it finds an & the it splits the array for each ampersand.
The following code pieces the URL back together by traversing the $_GET array for each piece.
I would like to know if this has any hidden problems that I may not be aware of.
The code:
$newurl = "";
foreach($_GET as $key=>$pcs) {
if($newurl=="")
$newurl = $pcs;
else
$newurl .= "& ".rtrim($key,"_");
}
//echo $newurl;exit;
if($newurl!='') $url=$newurl;
I am trimming the underscore from the piece as apache added this. Not sure why but any help on this would be great.
You said in a cooment:
We want the URL to show the ampersand so substituting with other characters is not an option.
Short answer: Don't do it.
Seriously, don't use ampersands this way in URLs. Even if looks pretty. Ampersands have a special meaning in a URL and trying to override that meaning because it looks nice is a very bad idea.
Most web-based software (including Apache, PHP and all browsers) makes assumptions about what an ampersand means in a URL, which you will find very hard to work around.
In particular, you will utterly confuse Google and other search engines if you've got arbitrary ampersands in the URL, so it will completely destroy your SEO rank.
If you must have an ampersand in the string, use urlencoding to turn it into a URL-friendly %26. This won't look good in the user's URL string, but it will work as intended.
If that's not acceptable, then substitute something different for ampersands; maybe the word "and", or a character like and underscore, or perhaps just remove it from the string without a replacement.
All of these are common practice. Trying to force the URL to have an actual ampersand character in it is not common practice, and for very good reason.
Take a look at urlencode :
You can also replace the "&" char with something not breaking the URI and won't be interpreted by apache like the "|" char.
We have had this fix in place for two weeks now so I believe that this has solved the issue. I hope this will help someone with a similar issue as I searched for weeks for a solution outside of an apache upgrade to include the B flag. Our users can now type in Bed & Breakfast and we can then serve the appropriate page.
Here is the fix in PHP.
$newurl = "";
foreach($_GET as $key=>$pcs)
{
if($newurl=="")
$newurl = $pcs;
else
$newurl .= "& ".rtrim($key,"_");
}
if($newurl!='') $url=$newurl;

Escape a url within a regular expression in a preg_replace

I am trying to redirect some tags to another page, passing its href as a url parameter. The code I'm using is something like this:
preg_replace(
"/<a(\s[^>]*)href=[\"\']??([^\" >]*?)[\"\']??([^>]*)>(.*)<\/a>/siU",
"<a$1href=\"".WWW."go.php?to=".urlencode("$2")."\"$3>$4</a>", $text
);
It is a modified version of the regexp found here. I use this code in this block:
$text = "<...some other tags...><a target=\"_blank\" href=\"http://www.google.com\" style=\"...\" class=\"...\">Google</a></...some other tags...>";
And it correctly gets captured, but when using urlencode("$2"), it recieves a "$2" string, and not the value stored in the preg variables (as I would). It is not limited to urlencode, but to passing this as a parameter to any other function. So I would not only want to encode this (I can always extend a little more the regexp to accept urls) but generally use variables inside methods.
Do you know any workaround to this? Thanks in advance.
this is totally normal as your are url encoding the string "$2" and then the urlencoded string is used for replacement so you end up with the same thing as writing
"<a$1href=\"".WWW."go.php?to=$2\"$3>$4</a>"
as second parameter. If you want the urlencode to be evaluated you have to use the e (for eval) flag like this:
preg_replace(
"/<a(\s[^>]*)href=[\"\']??([^\" >]*?)[\"\']??([^>]*)>(.*)<\/a>/seiU",
"'<a$1href=\"'.WWW.'go.php?to=\"'.urlencode('$2').'\"$3>$4</a>'", $text
);
another preferable solution may be to use preg_replace_callback to avoid relying on evaluating unknown strings

Categories