How to eliminate special characters from url? - php

I have the following url where var_a should always be a number. Also I don´t know how many var_a will be:
http://localhost/url.php?var_a[]=298&var_a[]=299
How to prevent getting an error if the user writes special characters in the url?
I have done this:
$data = preg_replace('/[^0-9\']/', '',$_GET['var_a']);
$data = str_replace("'", '', $data);
print_r ($data);// Array ( [0] => 298 [1] => 299 )
//This is ok, all number were printed
But I still get an error with the special characters like # % &
e.g.
http://localhost/url.php?var_a[]=298&var_a[]=#299
print_r ($data);// Array ( [0] => 298 [1] => )
//299 was not printed!
How can I fix this?

As far as I can tell, you can't fix it if the users are entering the values directly in the URL. The reason being is that these characters have special meanings in URLS: # represents data fragment, % represents unicode values, and & represents a new variable . The two options you can do are to use if it is coming from a form is to use $_POST values, or use urlencode before submitting the values. Pound sign (#) not working in PHP has more information on using urlencode .

Related

How to properly sanitise an array of user supplied data for JSON output?

My code
I have a function get_points_table() that returns an array like so:
Array
(
[0] => Array
(
[player] => steve
[points] => 10
)
[1] => Array
(
[player] => jess
[points] => 7
)
)
I would like to pass this array as JSON to a JavaScript script to output as HTML.
My current script looks like this:
<?php
require_once 'db.php';
$points_table = get_points_table($dbh);
echo json_encode($points_table);
?>
My problem
My understanding is that if I don't sanitise the data before echo'ing it back, there is a security risk posed by a player setting their username to something like steve<script>alert()</script> or using some other combinations of special characters.
My research suggests I need to use some combination of htmlentities() and/or htmlspecialchars() to safely output the data. However htmlentities() does not return utf8 encoded data, so I also need to use utf8_encode() in order for json_encode() to understand it. htmlentities() also does not allow you to pass an array as a value.
What I've tried
I've tried various combinations of array_walk(), array_walk_recursive() and array_map() to apply htmlentities() to each value of my array but to no success. I've also tried accessing the values in nested foreach loops to no success either. e.g.:
foreach($points_table as $key=>value) {
htmlspecialchars($value);
htmlentities($value);
utf8_encode($value);
}
echo json_encode($points_table);
What I need
I would like to know how to sanitise my array so I can safely pass it as JSON to be output as HTML, even if the user sets their username to something like steve<script>alert()</script><php echo "hello world";?> ;-- - &%00
Ideally I would like to do this so that the end result has the username in human readable format without converting symbols to html entities (i.e. steve<script> not steve"<script>")
This feels like a very common thing developers would do and should have a simple and easy answer, but I have done much searching and cannot work it out for myself.

Combining 2 Arrays So That They Display Correctly in my URL

I have an array $cat1 including
cat1[0]=>16 and cat1[1]=>16.
I also have this array:
$url_vars = array('text'=>$event->properties['text'],'SearchResultPagerPage'=>$thenextpage);
I need to put these combined into this URL function:
$this->URL('SearchResult','',$url_vars);
So that the resulting URL needs to look like this:
/SearchResult.html?text=cat&SearchResultPagerPage=1&cat1[]=1&cat1[]=16
Currently, if I combine them, I get this as the resulting combined array:
Array
(
[text] => cat
[SearchResultPagerPage] => 1
[0] => 1
[1] => 16
)
and this as the resulting URL:
SearchResult.html?&text=cat&SearchResultPagerPage=1&1=16
How do I form this so that it says cat1[]=1&cat1[]=16 instead of 1=16?
Thanks very much for any help anyone might offer!!
If you MUST use the URL function $this->URL('SearchResult','',$url_vars); then one idea is to use indices in the cat1 array. That is:
$url_vars["cat1[0]"] = 1;
$url_vars["cat1[1]"] = 16;
This will result in your query string having
...&cat1[0]=1&cat1[1]=16
with the []'s probably escaped, but perhaps your server script can properly accommodate these indices. It is worth a try. Otherwise you'll have to generate the URL outside of the URL function, because you can't have a php array with identical keys "cat1[]" but two separate values.
EDIT: One other thing to try in case your URL function is intelligent enough:
$url_vars["cat1"] = [1,16];

preg_match from URL string

I have a string passed through a campaign source that looks like this:
/?source=SEARCH%20&utm_source=google&utm_medium=cpc&utm_term=<keyword/>&utm_content={creative}&utm_campaign=<campaign/>&cpao=111&cpca=<campaign/>&cpag=<group/>&kw=<mpl/>
when its present I need to cut this up and pass it through to our form handler so we can track our campaigns. I can check for it, hold its contents in a cookie and pass it throughout our site but i am having and issue using preg_match to cut this up and put it into variables so I can pass their values to the handler. I want the end product to look like:
$utm_source=google;
$utm_medium=cpc;
$utm_term=<keyword/>
there is no set number of characters, it could be Google, Bing etc, so i am trying to use preg_match to get the first part (utm_source) and stop past what I want (&) and so forth but I don't understand preg_match well enough to do this.
PHP should be parsing your query sting for you, into $_GET. Otherwise, PHP knows how to parse query strings. Don't use regular expressions or for this, use parse_str.
Input:
<?php
$str = "/?source=SEARCH%20&utm_source=google&utm_medium=cpc&utm_term=<keyword/>&utm_content={creative}&utm_campaign=<campaign/>&cpao=111&cpca=<campaign/>&cpag=<group/>&kw=<mpl/>";
$ar = array();
parse_str($str, $ar);
print_r($ar);
Output:
Array
(
[/?source] => SEARCH
[utm_source] => google
[utm_medium] => cpc
[utm_term] => <keyword/>
[utm_content] => {creative}
[utm_campaign] => <campaign/>
[cpao] => 111
[cpca] => <campaign/>
[cpag] => <group/>
[kw] => <mpl/>
)

PHP http_build_query special symbols

I want to create an url out of an array with the help of http_build_query (PHP). This is the Array:
$a = array("skip" => 1, "limit" => 1, "startkey" => '["naturalProduct","Apple"]')
After calling
$s = http_build_query($a);
I get the following string $s:
skip=1&limit=1&startkey=%5B%22naturalProduct%22%2C%22Apple%22%5D
My problem is, that I would need an url like this:
skip=1&limit=1&startkey=["naturalProduct","Apple"]
which means, that I don't want to convert the following symbols: ",[]
I have written a conversion function which I call after the http_build_query:
str_replace(array("%5B", "%22", "%5D", "%2C"), array('[', '"', ']', ','), $uri);
My question now: Is there a better way to reach the expected results?
My question now: Is there a better way to reach the expected results?
Yes, there is something better. http_build_query­Docs by default uses an URL encoding as outlined in RFC 1738. You just want to de-urlencode the string. For that there is a function that does this in your case: urldecode­Docs:
$s = http_build_query($a);
echo urldecode($s);
I hope you are aware that your URL then is no longer a valid URL after you've done that. You already decoded it.
You don't need to decode the special characters - they are automatically decoded when PHP's $_GET superglobal is generated. When I do print_r($_GET) with your generated string, I get this:
Array ( [skip] => 1 [limit] => 1 [startkey] => [\"naturalProduct\",\"Apple\"] )
Which has decoded every character, but hasn't unescaped the double quotes. To unescape them, use stripslashes():
echo stripslashes($_GET['startkey']);
This gives
["naturalProduct","Apple"]
Which you can then parse or use however you wish. A better solution, as ThiefMaster mentions in the comments, is to disabled magic_quotes_gpc in your php.ini; it's deprecated and scheduled for removal completely in PHP6.

UTF-8 not showing in multi-dimensional arrays with a NUMERIC key

I have a script that puts some cyrillic text into session variables like this: $_SESSION['cyrillic'][$y] where $y is an iterator, so in the end the array will look like this:
[cyrillic] => Array
(
[0] => ������
[1] => ��������
[2] => ������
[3] => ������
However, after struggling with UTF-8 headers in both PHP, HTML and files save charsets (with and without BOM), I've found out there is nothing wrong with the charset settings (apparently), as setting any other session variable with the cyrillic text in WILL WORK.
This means:$_SESSION['cyr']['txt'] = $cyrillic_string_here; will work just fine, as shown here:
[cyr] => Array
(
[txt] => десять
)
So, what I fail to understand then, is WHY can't I insert cyrillic into an array using a numeric key, but an alphabetical one? And how can I work around this when I -need- to use an iterating loop?
EDIT: It's not that. I can insert the same text into another variable and echo it, or a session variable without numeric key values and it will work fine.
EDIT: I also found this:
*The hard-to-find documentation sentence I'm about is: "The keys in the $_SESSION associative array are subject to the same limitations as regular variable names in PHP."*
But I thought I could make an array with a numeric value like this: $array[$i]? Or does it mean since the key is ASSOC that $array['text'][$i] wouldn't work?
Found the solution. I had a trim(strtolower($text)); wrapped around my cyrillic.
strtolower:
[These functions] only work when translation is between common characters in ISO 8859-1 and UTF-8, that means they will work well with western languages but not cyrillic or asian.
Thanks for your help.

Categories