Properly escape javascript object - javascript

Given an object: {"key":"pairs","are":"fun"} that is echoed into a variable like const foo = <?php echo $bar ?>;. What is the proper way to escape the object? I've tried encode_json which escapes all the double quotes {\"key\":\"pairs\",\"are\":\"fun\"} disallowing the object to render. I have also tried esc_js which converts the double quotes to & quot;. How do i properly escape the object and return the object to foo? The out should be {"key":"pairs","are":"fun"} escaped of any malicious content.

If you use wp_json_encode to produce the JSON string itself, the output where you assign the JSON to a JavaScript variable in the browser should be reasonably safe. The wp_json_encode function will escape the characters that might otherwise allow someone to inject code at the point of assignment.
However, you also have to consider how your values in the key/value pairs will be used. If you're expecting an integer, maybe run the value through intval or if you are expecting plaintext that you're injecting into the page later, perhaps run it through esc_html.
For example:
<?php
$map = [
'key' => 'pairs',
'are' => '"; I document.write(\'fun trying to break out\')',
'i_am_expecting_plaintext' => esc_html('Hello<script>evilscript();</script>'),
'i_expect_an_integer' => intval("90i"),
'some_html_allowed' => wp_kses('here<script>dangerous();</script>', ['a' => array('href'=>array())]),
];
?>
<script>const foo = <?php echo wp_json_encode($map, JSON_PRETTY_PRINT); ?>;</script>
Produces the following output:
<script>const foo = {
"key": "pairs",
"are": "\"; I document.write('fun trying to break out')",
"i_am_expecting_plaintext": "<a href="evillinkhere">Hello<\/a><script>evilscript();<\/script>",
"i_expect_an_integer": 90,
"some_html_allowed": "<a href=\"http:\/\/nisamerica.com\/\">here<\/a>dangerous();"
};</script>
Addendum:
The reason wp_json_encode was giving you {\"key\":\"pairs\",\"are\":\"fun\"} before is that you were providing it a string that was already in JSON-notation. What wp_json_encode does is take native PHP variables and escape them as JSON. It's a pretty thin wrapper around json_encode really. My suggestion above is really to just produce the map in PHP, and feed that to the encode function instead of making your string representation and then trying to make it safe.

Related

Print PHP JSON encoded array, to JavaScript and decode it, produces errors

I have to use some data from PHP to JavaScript. I am using JSON for that. I encode the array with PHP's json_encode function and then I want to decode it with JavaScript.
<?php
$data = array(
"..."=>"...",
.....
);
?>
<script>
var data = jQuery.parseJSON('<?php echo json_encode($data); ?>');
console.log(data);
</script>
The problem is sometimes produces errors in javascript console on parsing the JSON, most of times when $data contains HTML.
How can I print a json encoded code inside javascript, dinamically with PHP?
Thank you!
JSON is in fact JavaScript Object Notation, it can be echoed directly in a variable, and doesn't need parsing.
var data = <?= json_encode($data); ?>;
The errors will typically come from when the data contains ' (which prematurely terminate your string literal) or new line characters (which get parsed by the JS parser and render the JSON invalid).
You could get around this by explicitly escaping such characters (with a string replacement function run on the generated JSON), but that is more effort than is worth going to.
Since JSON is a subset of the JavaScript literal syntax, you can just treat it as JavaScript directly. You don't need to wrap it in a string and then parse that string to the JS data structure.
var data = <?php echo json_encode($data); ?>

Generate JSON array

I want to generate a JSON array with PHP, but it doesn't work well.
My PHP array looks like this:
protected $resultArray = array("1.0" => 0, "1.3" => 0);
then I do this:
return json_encode($resultArray);
but then i've got this:
var array = [{"1.0":2,"1.3":1}];
Why is " replaced with "?
quot; is a quote character (") encoded as HMTL. json_encode() does not produce HTML encoded sequences.
Replace return with echo in return json_encode($resultArray); and you'll see this for yourself.
Most probably the returned string is passed further to a function that runs it through htmlspecialchars() or htmlentities() and this is the correct way to work with it if you put it into an HMTL context.
Use a different viewer class if you need to output only the json_encode()-ed string. I don't know TYPO3 but I guess you should use JsonView; pass it $resultArray as-is and it will call json_encode() for you.
I think you may using etended library for example in wamp server I tested this code and it's work fine
$str = "<div style='position:relative'><img src='/assets/ui/success.png' /><span
style='position:relative;top:-15px;'>Nachricht empfangen!</span></div>";
echo json_encode(array('prompt' => $str));
//output
//{"prompt":"<div style='position:relative'><img src='\/assets\/ui\/success.png' \/><span style='position:relative;top:-15px;'>Nachricht empfangen!<\/span><\/div>"}
Thanks guys for help!
The solution is (only for typo3). To get a properly correct JSON-Array in the view the JS code has to be improved the following way:
var array = {f:format.htmlentitiesDecode(value:chartarray)};

Why do we need json or php's serialization method to access php array in JS , if we can achieve the same thing without them?

Usually we use json(as it is a better option than php's serialization) to transfer a php array into JS to access it from there, or we can use cookie.
But can't we do the same thing without those? For example lets take a look at the first code.
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<?php
$elements = array('myname', 'myage');
?>
<script type="text/javascript">
var elements = <?php echo json_encode($elements) ; ?> ;
//use the elements array afterwards
</script>
</body>
</html>
But we can access that php array without using json, like this way also
<script type="text/javascript">
var elements = [];
<?php foreach($elements as $element) : ?>
elements.push("<?php echo $element; ?>");
<?php endforeach; ?>
//use the elements array afterwards
</script>
So other than secutity reason why do we need json here?
There are a number of special cases you would need to address when embedding php variables in javascript (which json_encode already handles for you).
For strings:
Any newline characters in a php string need to be escaped
Any quotation marks of the same type as the surrounding quotes will need to be escaped
The string must be quoted
For numbers:
The number should not be quoted - otherwise, the data type on the javascript end will change
For arrays:
Each element could be of a different type, so you'd need a recursive function to handle the encoding correctly. Also, PHP associative arrays map to json objects, while numeric arrays map to json arrays. This is somewhat awkward to handle in your own code.
** Not an exhaustive list, there are probably a few other cases.
It's very easy to make a mistake when writing your own encoding script, and it'll most likely run slower than the PHP json_encode function.
Keep in mind that you are actually printing a lot of javascript push functions.
I guess the real advantages of JSON comes at the time when using AJAX calls. You'll have no help from PHP to parse the information straight into your javascript script block.
jsonencode() converts the php array into a string in json format. It is one php call handled locally by the server.
The foreach alternative mixes server and js execution to obtain a similar result. It is more complex to read and longer to execute, both for the server and the javascript client.
Javascript strings can be delimited by " or '. If they are delimited by " and the string contains ", that would signal an end of string, the remainder or the string would be handled as code, leading to a parsing error. Therefore, the " must be escaped like so \". json_encode() does that for you, echo doesn't.
So keep to the first.

Using and retrieving PHP variables within JSON

I've just started using JSON to throw around information between pages and I simply can't figure this one out.
Basically, I have one page that's using jquery getJSON to get some JSON data from another page. But the PHP variables won't/can't get replaced with the necessary content.
Here's the jquery script (which is working fine I believe)
$.getJSON("./menu-controller.php", { editId: getEditId, getEditInfo: true },function(data) {
console.log(data);
var id = data.itemId;
alert(id);
});
I can get it to work just fine when using this code on the other page
$json = '{ "itemId":"4" }';
echo $json;
HOWEVER, if I use this, then it won't work
$menuId = 4;
$json = '{ "itemId":$menuId }';
echo $json;
So my question is, how can I get $menuId to actually replace itself with the number and come back on the other page correctly?
I've tried messing with the quotes and re-arranging the quotes for 4 hours. It either comes up with an error or it doesn't replace $menuId with the actual number.
You should make a PHP array instead and then convert it to JSON.
For instance:
$array = array();
$array['itemId'] = $menuId;
echo json_encode($array);
Note: there is also a json_decode function that takes in a JSON string and converts it into PHP as well. You might find that useful.
FYI, PHP variables are interpolated in double quotes only and not in single quotes. So, you've to do something like this:
$json = "{ \"itemId\":$menuId }";
echo $json;
Please see the demonstration over here: http://codepad.viper-7.com/CDC0oM
In this sample:
$menuId = 4;
$json = '{ "itemId":$menuId }';
echo $json;
You have wrapped your JSON string in single quotes. PHP substitutes values in double quotes, so the value is not substituted here, and the vale you echo is
{ "itemId":$menuid } - this is not valid JSON.
You're better off creating a PHP array and using json_encode() to create the SON string:
echo json_encode(array("itemId"=>$menuId));
The problem is that you've enclosed your PHP variable within single (rather than double) quotes, so PHP isn't looking in the string for variables to replace.
So this should work:
$json = "{ \"itemId\": $menuId}";
As well as the json_encode method suggested by Cezary Wojcik (which is going to be a lot more flexible if the data gets more complex!).

js, make a json object a string - the easy way?

I have tried lots of different ways, and using many diffent PHP and JS functions to try to achieve this.
Hoe to i turn this json object ;
"lines" : ["text line 1<br/>","text line 2<br/>","text line 3<br/>","text line 4<br/>"]
Into this string, so that i can add to a HTMl div
text line 1<br/> text line 2<br/> text line 3<br/> text line 4<br/>
No, quotes, brackets or anything else.
In it's simplest form all i have is stringify;
lines = JSON.stringify(obj.lines)
but the above outputs, brackets, quotes, and commas
Sorry if this is a simple and silly question, but i h (finishing now (embarrassed!)) ave searched everywhere for a simple answers. Nothing stands out.
Check out Array.join:
var html = obj.lines.join("");
Example: http://jsfiddle.net/VXbs7/
You have a JSON string. You need to parse it into a data structure, then get the array of strings, and loop over them (outputting as you go).
If you're doing this from javascript, it's quite easy. JSON is native to javascript and can be interpreted as an object quite simply. It looks like you only have half your JSON object pasted in your question though. A whole JSON object is wrapped in [] or {} (unless it's just a string or number type, but then it's not an object).
Anyway, if you're in PHP - you can easily json_decode() this string and loop it like so:
<?php
$arr = json_decode($json_string, true); //true makes it an array instead of object
foreach ($arr['lines'] as $line)
{
echo $line;
}
If you're trying to accomplish it in javascript (in the browser), it's also quite easy (assuming your string is stored in a php variable, and that you're using jquery for dom manipulation)
<script type="text/javascript">
var obj = <?= $json_string; ?>,
mydiv = $('#mydiv);
for (key in obj['lines'])
{
var line = obj['lines'][key];
mydiv.append(line);
}
</script>
both of those should give you the output you're looking for

Categories