The value of the onclick attribute should be escaped like any other HTML attribute, using htmlspecialchars(). Actual Javascript strings inside the code should be encoded using json_encode(). For example:
<?php
$message = 'Some \' problematic \\ chars " ...';
$jscode = 'alert('.json_encode($message).');';
echo '<a onclick="' . htmlspecialchars($jscode) . '">Click me</a>';
That being said... onclick (or any other event) attributes are so 2005. Do yourself a favor and separate your javascript code from your html code, preferably to external file, and attach the events using DOM functions (or jQuery, which wraps it up nicely)
Answer from shesek on Stack OverflowThe value of the onclick attribute should be escaped like any other HTML attribute, using htmlspecialchars(). Actual Javascript strings inside the code should be encoded using json_encode(). For example:
<?php
$message = 'Some \' problematic \\ chars " ...';
$jscode = 'alert('.json_encode($message).');';
echo '<a onclick="' . htmlspecialchars($jscode) . '">Click me</a>';
That being said... onclick (or any other event) attributes are so 2005. Do yourself a favor and separate your javascript code from your html code, preferably to external file, and attach the events using DOM functions (or jQuery, which wraps it up nicely)
I'm really just re-wording what @Marshall House says here, but:
In HTML, a double quote (") will always end an attribute, regardless of a backslash - so it sees: onclick="var a = prompt('New value: ', 'aaaa\". The solution that @Marshall offers is to separate your code out into a function. This way you can print escaped PHP into it without a problem.
E.g.:
<script>
// This is a function, wrapping your code to be called onclick.
function doOnClickStuff() {
// You should no longer need to escape your string. E.g.:
//var a = prompt('new value:','<?php echo
i]; ?>');
// Although the following could be safer
var a = prompt('new value:',<?php json_encode(
i]); ?>);
if (a) { <!--javascript code--> }
else { <!--javascript code--> }
}
</script>
<someelement onclick="doOnClickStuff();"> <!-- this calls the javascript function doOnClickStuff, defined above -->
Pass a PHP variable to a JavaScript variable - Stack Overflow
javascript - JS inside PHP Escape String (for functions) - Stack Overflow
plugins - How to proper escape echo inside a javascript tag - WordPress Development Stack Exchange
php - Preventing XSS attacks with proper escaping - Code Review Stack Exchange
Expanding on someone else's answer:
<script>
var myvar = <?= json_encode($myVarValue, JSON_UNESCAPED_UNICODE); ?>;
</script>
Using json_encode() requires:
- PHP 5.2.0 or greater
$myVarValueencoded as UTF-8 (or US-ASCII, of course)
Since UTF-8 supports full Unicode, it should be safe to convert on the fly.
Please note that if you use this in html attributes like onclick, you need to pass the result of json_encode to htmlspecialchars(), like the following:
htmlspecialchars(json_encode($string), ENT_QUOTES);
or else you could get problems with, for example, &bar; in foo()&&bar; being interpreted as an HTML entity.
encode it with JSON
Same as always: encode as JSON.
echo '<a onClick="myFunctionTakesPHPValues('.json_encode($element[0]).','.json_encode($element[1]).')">'.$element[2].'</a>';
- Never echo JS from PHP. Escape from PHP mode instead, it will save you a lot of slashes and nerves.
- Every value have to be escaped properly, as explained in this article
So, for the JS values you have to escape them with json_encode() and, as they are going into HTML attribute, escape them as HTML too.
For the last element only HTML encoding is required.
foreach ($array as $element)
{
$param1 = htmlspecialchars(json_encode($element[0])); // better give them
$param2 = htmlspecialchars(json_encode($element[1])); // meaningful names
$param3 = htmlspecialchars($element[2]);
?>
<a onClick="myFunctionTakesPHPValues(<?=$param1?>,<?=$param2?>)">
<?=$param3?>
</a>
<? }
And yes, using raw JS in HTML attributes considered as a bad practice.
There are already native functions to escape for HTML and JS strings: htmlspecialchars() and json_encode(). See this related question on Stack Overflow
As for innerHTML, simply don't use it. Use textContent instead. If you wish to allow for formatting (for example, in comments or posts), I recommend Markdown
My other answer explains the general best practice, let's go over your code.
You can pass an array to
str_replace()so that it replaces every occurence of matching substrings with their replacement array counterparts with the same index:return str_replace(["/", "\n"], ["\\/", "\\n"], $subject)You aren't escaping
;for JavaScript strings, that can be used to break out of the context.You shouldn't really care about JavaScript replacement. Data comes from the server, that's where all escaping should be.
ES5 has the
Array.isArray()static method to check if a given parameter is an array. For strings,typeof strwill returnstring. So your getType function is a bit redundant:function isString(str) { return typeof str === 'string'; } function isArray(arr) { return Array.isArray(arr); }Also, ES5 has
Array.prototype.forEachfor iterating over an array, and is considered a better alternative tofor.