PHP json_encode data with double quotes - php

I'm using this simple code to transform database query results into JSON format:
$result = $mysqli->query("
SELECT
date as a
, sum(sales) as b
, product as c
FROM
default_dataset
GROUP BY
date
, product
ORDER BY
date
");
$data = $result->fetch_all(MYSQLI_ASSOC);
echo stripslashes(json_encode($data));
The problem is that if there are double quotes in the data (e.g. in the product column) returned by this query. The json_encode function does not encode the data in a good JSON format.
Could someone help me how to escape the double quotes that are returned by the query? Thank you.

You will need htmlspecialchars instead of stripslashes with proper encoding (UTF-8, if your page uses UTF-8 charset) and ENT_QUOTES which will escape double quotes preventing data to break. See the code below:
echo htmlspecialchars(json_encode($data), ENT_QUOTES, 'UTF-8');

json_encode already takes care of this, you are breaking the result by calling stripslashes:
echo json_encode($data); //properly formed json

Example with a simple array with double quotes string value.
$yourArr = array(
'title' => 'This is an example with "double quote" check it'
);
// add htmlspecialchars as UTF-8 after encoded
$encodeData = htmlspecialchars(json_encode($yourArr), ENT_QUOTES, 'UTF-8');
echo $encodeData;
Result:
{"title":"This is an example with \"double quote\" check it"}
According to PHP Manual:
That said, quotes " will produce invalid JSON, but this is only an
issue if you're using json_encode() and just expect PHP to magically
escape your quotes. You need to do the escaping yourself.

Yes, PHP json_encode wouldn't "escape double" quotes, we need to escape those manually in this super simple way-
array_walk($assoc_array, function(&$v, $k) {
if(is_string($v) && strpos($v, '"') !== false) {
$v = str_replace('"', '\"', $v);
}
});
// After escaping those '"', you can simply use json_enocde then.
$json_data = json_encode($assoc_array);

to encode the quotes using htmlspecialchars:
$json_array = array(
'title' => 'Example string\'s with "special" characters'
);
$json_decode = htmlspecialchars(json_encode($json_array), ENT_QUOTES, 'UTF-8');

You can done that using base64_encode and base64_decode
To store in database first convert it to base64_encode and stored into database and if you want that data then you can decrypt that data using base64_decode
$var['cont'] = base64_encode($_POST['data']);
$dd = json_encode($var['cont']);
echo base64_decode ( json_decode($dd) );

Related

PHP preg_replace with addslashes to string that may or may not contain comma quoted values

Background..
This is user input being collected so I need to expect some strange stuff and try to fix up string before passing these into functions. User input is stored into the database similar to so:
{"value":"O'Neil,'Smith',\"O'Reilly\",100"}
So the script pulls these out of the database, json_decodes them, and then now I'm trying to fix those value strings up. Here's the best example of that I can give.
$json = '{"value":"O\'Neil,\'Smith\',\"O\'Reilly\",100"}';
$array = json_decode($json, true);
The Goal..
How could I go about escaping quotes in strings like so:
O'Neil,Smith,O'Reilly,100
"O'Neil","Smith","O'Reilly",100
'O'Neil','Smith','O'Reilly',100
O'Neil,'Smith',"O'Reilly",100
So that I get the following result out of each:
'O\'Neil','Smith','O\'Reilly',100
Values may or may not contain commas. It could just be a single value like O'Neil or 100.
I'm pretty sure preg_replace could so something like this, or even preg_replace_callback, but I'm just not sure how to go about this.
The below do not work at all but I'm thinking one of these approaches should work.
$value = preg_replace('/(.*?)/', '$1', $array['value']);
$value = preg_replace_callback('/(.*?)/', 'addslashes', $array['value']);
I've also tried exploding the strings using the commas and looping the values but that escapes the quotes I don't want to touch as well.
Thanks all!
I think this function will do what you want. It uses preg_match_all to find either a quoted string (single or double, possibly with escaped quotes inside), or a set of non-comma characters. Each of those values is then trimmed of quotes, and any non-escaped single quotes are replaced with escaped ones. Finally non-numeric values are placed into single quotes:
function quote($value) {
preg_match_all('/"(?:\\\\"|[^"])*"|\'(?:\\\\\'|[^\'])*\'|[^,]+/', $value, $values);
foreach ($values[0] as &$value) {
$value = trim($value, "'\"");
$value = preg_replace("/(?<!\\\\)'/", "\\'", $value);
if (!is_numeric($value)) $value = "'$value'";
}
return implode(',', $values[0]);
}
To use with your sample strings:
echo quote("O'Neil,Smith,O'Reilly,100") . PHP_EOL;
echo quote("\"O'Neil\",\"Smith\",\"O'Reilly\",100") . PHP_EOL;
echo quote("'O\'Neil','Smith','O\'Reilly',100") . PHP_EOL;
echo quote("O'Neil,'Smith',\"O'Reilly\",100") . PHP_EOL;
Output:
'O\'Neil','Smith','O\'Reilly',100
'O\'Neil','Smith','O\'Reilly',100
'O\'Neil','Smith','O\'Reilly',100
'O\'Neil','Smith','O\'Reilly',100
Demo on 3v4l.org

PHP \uXXXX encoded string convert to utf-8

I've got such strings
\u041d\u0418\u041a\u041e\u041b\u0410\u0415\u0412
How can I convert this to utf-8 encoding?
And what is the encoding of given string?
Thank you for participating!
The simple approach would be to wrap your string into double quotes and let json_decode convert the \u0000 escapes. (Which happen to be Javascript string syntax.)
$str = json_decode("\"$str\"");
Seems to be russian letters: НИКОЛАЕВ (It's already UTF-8 when json_decode returns it.)
To parse that string in PHP you can use json_decode because JSON supports that unicode literal format.
To preface, you generally should not be encountering \uXXXX unicode escape sequences outside of JSON documents, in which case you should be decoding those documents using json_decode() rather than trying to cherry-pick strings out of the middle by hand.
If you want to generate JSON documents without unicode escape sequences, then you should use the JSON_UNESCAPED_UNICODE flag in json_encode(). However, the escapes are default as they are most likely to be safely transmitted through various intermediate systems. I would strongly recommend leaving escapes enabled unless you have a solid reason not to.
Lastly, if you're just looking for something to make unicode text "safe" in some fashion, please instead read over the following SO masterpost: UTF-8 all the way through
If, after three paragraphs of "don't do this", you still want to do this, then here are a couple functions for applying/removing \uXXXX escapes in arbitrary text:
<?php
function utf8_escape($input) {
$output = '';
for( $i=0,$l=mb_strlen($input); $i<$l; ++$i ) {
$cur = mb_substr($input, $i, 1);
if( strlen($cur) === 1 ) {
$output .= $cur;
} else {
$output .= sprintf('\\u%04x', mb_ord($cur));
}
}
return $output;
}
function utf8_unescape($input) {
return preg_replace_callback(
'/\\\\u([0-9a-fA-F]{4})/',
function($a) {
return mb_chr(hexdec($a[1]));
},
$input
);
}
$u_input = 'hello world, 私のホバークラフトはうなぎで満たされています';
$e_input = 'hello world, \u79c1\u306e\u30db\u30d0\u30fc\u30af\u30e9\u30d5\u30c8\u306f\u3046\u306a\u304e\u3067\u6e80\u305f\u3055\u308c\u3066\u3044\u307e\u3059';
var_dump(
utf8_escape($u_input),
utf8_unescape($e_input)
);
Output:
string(145) "hello world, \u79c1\u306e\u30db\u30d0\u30fc\u30af\u30e9\u30d5\u30c8\u306f\u3046\u306a\u304e\u3067\u6e80\u305f\u3055\u308c\u3066\u3044\u307e\u3059"
string(79) "hello world, 私のホバークラフトはうなぎで満たされています"

How do I escape only single quotes?

I am writing some JavaScript code that uses a string rendered with PHP. How can I escape single quotes (and only single quotes) in my PHP string?
<script type="text/javascript">
$('#myElement').html('say hello to <?php echo $mystringWithSingleQuotes ?>');
</script>
Quite simply: echo str_replace('\'', '\\\'', $myString);
However, I'd suggest use of JSON and json_encode() function as it will be more reliable (quotes new lines for instance):
<?php $data = array('myString' => '...'); ?>
<script>
var phpData = <?php echo json_encode($data) ?>;
alert(phpData.myString);
</script>
If you want to escape characters with a \, you have addcslashes(). For example, if you want to escape only single quotes like the question, you can do:
echo addcslashes($value, "'");
And if you want to escape ', ", \, and nul (the byte null), you can use addslashes():
echo addslashes($value);
str_replace("'", "\'", $mystringWithSingleQuotes);
In some cases, I just convert it into ENTITIES:
// i.e., $x= ABC\DEFGH'IJKL
$x = str_ireplace("'", "&apos;", $x);
$x = str_ireplace("\\", "&bsol;", $x);
$x = str_ireplace('"', """, $x);
On the HTML page, the visual output is the same:
ABC\DEFGH'IJKL
However, it is sanitized in source.
Use the native function htmlspecialchars. It will escape from all special character. If you want to escape from a quote specifically, use with ENT_COMPAT or ENT_QUOTES. Here is the example:
$str = "Jane & 'Tarzan'";
echo htmlspecialchars($str, ENT_COMPAT); // Will only convert double quotes
echo "<br>";
echo htmlspecialchars($str, ENT_QUOTES); // Converts double and single quotes
echo "<br>";
echo htmlspecialchars($str, ENT_NOQUOTES); // Does not convert any quotes
The output would be like this:
Jane & 'Tarzan'<br>
Jane & 'Tarzan'<br>
Jane & 'Tarzan'
Read more in PHP htmlspecialchars() Function
To replace only single quotes, use this simple statement:
$string = str_replace("'", "\\'", $string);
You can use the addcslashes function to get this done like so:
echo addcslashes($text, "'\\");
After a long time fighting with this problem, I think I have found a better solution.
The combination of two functions makes it possible to escape a string to use as HTML.
One, to escape double quote if you use the string inside a JavaScript function call; and a second one to escape the single quote, avoiding those simple quotes that go around the argument.
Solution:
mysql_real_escape_string(htmlspecialchars($string))
Solve:
a PHP line created to call a JavaScript function like
echo
'onclick="javascript_function(\'' . mysql_real_escape_string(htmlspecialchars($string))"
I wrote the following function. It replaces the following:
Single quote ['] with a slash and a single quote [\'].
Backslash [\] with two backslashes [\\]
function escapePhpString($target) {
$replacements = array(
"'" => '\\\'',
"\\" => '\\\\'
);
return strtr($target, $replacements);
}
You can modify it to add or remove character replacements in the $replacements array. For example, to replace \r\n, it becomes "\r\n" => "\r\n" and "\n" => "\n".
/**
* With new line replacements too
*/
function escapePhpString($target) {
$replacements = array(
"'" => '\\\'',
"\\" => '\\\\',
"\r\n" => "\\r\\n",
"\n" => "\\n"
);
return strtr($target, $replacements);
}
The neat feature about strtr is that it will prefer long replacements.
Example, "Cool\r\nFeature" will escape \r\n rather than escaping \n along.
Here is how I did it. Silly, but simple.
$singlequote = "'";
$picturefile = getProductPicture($id);
echo showPicture('.$singlequote.$picturefile.$singlequote.');
I was working on outputting HTML that called JavaScript code to show a picture...
I am not sure what exactly you are doing with your data, but you could always try:
$string = str_replace("'", "%27", $string);
I use this whenever strings are sent to a database for storage.
%27 is the encoding for the ' character, and it also helps to prevent disruption of GET requests if a single ' character is contained in a string sent to your server. I would replace ' with %27 in both JavaScript and PHP just in case someone tries to manually send some data to your PHP function.
To make it prettier to your end user, just run an inverse replace function for all data you get back from your server and replace all %27 substrings with '.
Happy injection avoiding!

How you encode strings like \u00d6?

This is encoded: \u00d6
This is decoded: Ö
What function I have to use to decode that string into something readable?
\u00d6asdf -> Öasdf
To convert to UTF-8, do:
preg_replace('/\\\\u([0-9a-f]{4})/ie',
'mb_convert_encoding("&#x$1;", "UTF-8", "HTML-ENTITIES")',
$string);
Since this is the escaping used in JSON, another option would be json_decode. This would, however, also require escaping double quotes and backslashes before (except those of the \uXXXX escape sequences) and adding double quotes around the string. If, however, the string is indeed JSON-encoded and that's what originally motivated the question, the correct answer would naturally be use json_decode instead of the method above.
Normally this would be the urldecode method, but it does not apply to unicode characters, like yours. Try this one instead:
function unicode_urldecode($url)
{
preg_match_all('/%u([[:alnum:]]{4})/', $url, $a);
foreach ($a[1] as $uniord)
{
$utf = '&#x' . $uniord . ';';
$url = str_replace('%u'.$uniord, $utf, $url);
}
return urldecode($url);
}

Revert escaped characters

I saved some data in the database using mysql_real_escape_string() so the single quotes are escaped like this '. It looks ok in the browser, but how can I convert it back to single quote when I save the text in a txt file?
Please note that mysql_real_escape_string() does not turn apostrophes ' into ' Only HTML-oriented functions do, so you must have calls to htmlentities() somewhere in your script.
As for your question, the function you're looking for is html_entity_decode()
echo html_entity_decode(''', ENT_QUOTES);
This is the reason why you should not store encoded text in the database. You should have stored it in it's original format, and encoded it when you display it.
Now you have to check what characters the function does encode, and write string replacements that converts them back, in reverse order.
Pseudo-code example:
s = Replace(s, "'", "'")
s = Replace(s, "<", "<")
s = Replace(s, ">", ">")
s = Replace(s, "&", "&")
That is just an ascii value of "'", use chr to get it back to a character. Here's the code
$string = "Hello ' Man";
$string = preg_replace('|&#(\d{1,3});|e', 'chr(\1)', $string);
echo $string; # Hello ' Man

Categories