Escape brackets on php for javascript - php

For example i've a php script with this content:
<?php
$msg = addslashes("I'm a message. The what happened >:(");
echo "<script>alert($msg); return false;</script>";
?>
But the alert get broken by the last "(". How can i solve this?

You should enclose alert parameter with quotes:
echo "<script>alert('$msg'); return false;</script>";
What your code outputs to the browser was:
<script>alert(The what happened >:(); return false;</script>
which is not a valid javascript, after putting the quotes, it becomes:
<script>alert('The what happened >:('); return false;</script>
which is valid javascript.

You need to put it in a JavaScript string, otherwise it gets interpreted like this, which is meaningless and causes an error:
<script>alert(The what happened >:(); return false;</script>
Notice the single quotes in the alert() call which denote a JavaScript string (double quotes work too):
<?php
$msg = "The what happened >:(";
echo "<script>alert('$msg'); return false;</script>";
?>
It is also a good idea to escape the content inside to mitigate XSS, using htmlspecialchars().

The other answers are along the right lines, but it is not sufficient to just put quotes around the string, if it can be any arbitrary string. If the string itself contains a quote, backslash, or newline, that will break the JavaScript string literal. If the string contains </script (or just </ in some cases) that will break the <script> block. In either case, if user-supplied input is involved, that gives you a big old cross-site-scripting security hole.
Whilst you may not need it for this specific value of $msg, it's a good idea to get used to JS-string-literal-escaping any text you output into a JS string. Whilst you can do this manually by adding backslashes, it's generally much easier to just use the built-in JSON encoder, which will work for other types like arrays and objects as well as strings.
<script type="text/javascript">
alert(<?php echo json_encode($msg); ?>);
return false; // huh? return, in a <script> block??
</script>

alert() accepts a string argument; you must enclose the text you're passing to it in quotes (either single or double) and insure that any matching quotes within the string are escaped by backslashes.
In your case single quotes would suffice:
echo "<script>alert('$msg'); return false;</script>";

Depending on the context, you might also just do:
<?php
$msg = "The what happened >:(";
?>
<script>alert("<?php echo $msg ?>"); return false;</script>
If there is no need to echo HTML or JavaScript code, then don't do it. It is easier to maintain .

Related

Escaping string before assigning to innerHTML echoed by PHP

I'm encountering a problem involving escaping character that I think it's not simple at all. If this is done in javascript, nothing to say but the context is using echo command (in PHP) to write javascript code like this:
echo "<script>document.getElementById('spanID').innerHTML=\"$x\"</script>";
$x is a variable in PHP environment, which can contain both single and double quotes. What I do here is:
1. Keep the $x not change, and if $x contains any double quote, the above code won't work, the text echoed may look like:
<script>document.getElementById('spanID').innerHTML="leftside"rightside"</script>;
I supposed $x = leftside"rightside, and you can see it surely won't work.
Escape the double quotes in $x (change all " to "), then the text echoed may look like this:
document.getElementById('spanID').innerHTML="leftside"rightside";
The " won't be converted to " when it is assigned to innerHTML attribute of a Span (for e.g), so instead of my want, the innerHTML of my SPAN should be leftside"rightside, it will be leftside"rightside.
If I change the " to ' in the original echo, like this:
echo "<script>document.getElementById('spanID').innerHTML='$x'</script>";
It is the same because $x here can contain both single and double quotes.
I don't find out any other ways to escape quotes in this case. Could you please help me out?
Thanks!
You need to put between the quotes a string that is a valid string of JavaScript containing valid (and safe) HTML.
Your best option is to not use innerHTML and instead use document.createTextNode which means you only need to slash-escape the content.
Otherwise, you need to HTML escape, then slash escape the content. For correctness, your slash-escaping function should escape at least double-quotes, backslashes, and all JavaScript newlines (U+A, U+D, U+2028, U+2029). I believe PHP's addslashes does not handle U+2028 or U+2029 by default but How to escape string from PHP for javascript? has some alternatives.
To put it all together:
$x_escaped = json_encode($x, JSON_HEX_TAG);
echo "<script>document.getElementById('spanID').appendChild(document.createTextNode($x_escaped))</script>"
should do it. The JSON_HEX_TAG makes sure that $x_escaped will not contain </script> or any other content that prematurely ends your script tag. </script> will instead become \u003c/script\u003e.

Passing special characters from php to javascript

I am passing a string variable from php to javascript.
The string contains "
But javascript doesn't get it.
How can I escape this character?
UPD:
To be more clear, first I don't want to make many changes in the code (not written by me)...
The string is passed this way:
var string = '<? echo $string;?>' ;
Single quotes are used. Maybe there is a way to change smth. in the string itself?
You could use the json_encode method:
<script type="text/javascript">
var value = <?php echo json_encode($someValue); ?>;
alert(value);
</script>
Assuming a string delimited using double quotes, add_slashes will do the job in the particular case.
Wrapping the data in an associative array, running it through json_encode and altering the JS to expect the changed data structure is a safer approach though (since that will take care of other characters which are significant, such as literal new lines).
(Technically speaking, with the current implementation of json_encode you could skip wrapping it in an associative array … but a plain string isn't valid JSON and I'm inclined to avoid depending on a function that is supposed to generate JSON not throwing an exception when given a data structure that can't be turned into JSON).
If you are embedding the script in an HTML document you will also have to take steps to ensure that the resulting JS doesn't contain any HTML that could cause issues (such as " in an script included as an attribute value).
Use urlencode() function in php code to pass the string to javascript code and decodeuri() in javascript to decode that string.

Using innerhtml to write html with A LOT of quotes

I'm trying to call a function which writes a very long string of html to an element. The string will look similar to this;
'<div id='gaugearray8'>
<p id='ANCPUB' class='plot' style='height:100px;width:175px;float:left;' title='0.0011217599587192' onClick=LowerLevelPrint([{"NumberSelected":1,"TargetPerc":[237.5],"KpiDescription":["Contribution&nbspof&nbspExternal&nbspRevenue"],"KpiName":["revcontrubionkpi"],"ValuetoPrint":[0.0011217599587192],"ValueNow":[19],"ValueCompare":[1693767],"Target":["8"],"KpiUnits":["Pounds"],"PercentCompare":[0.0011217599587192]}]) onmouseover=TopLevelLabel({"NumberSelected":1,"Description":["Contribution&nbspof&nbspExternal&nbspRevenue"],"GroupDescription":"Ancillary&nbspService&nbspPerformance"}) onmouseout=clearnew()></p>
<p id='CSPUB' class='plot' style='height:100px;width:175px;float:left;' title='21.855170547342' onClick=LowerLevelPrint([{"NumberSelected":7,"TargetPerc":[206.03360584712,8.8767313176762,10.356186537289,12.5,12.5,237.5,10.356186537289],"KpiDescription":["Operating&nbspCost&nbspper&nbspService&nbspKm","Revenue&nbspper&nbspService&nbspKm","Total&nbspCost&nbspper&nbspService&nbspKm","Claims&nbspCost&nbspper&nbspVehicle","Claims&nbspCost&nbspper&nbspDriver","Number&nbspof&nbspClaims&nbspLodged&nbspper&nbsp100,000km","Overheads&nbspCost&nbspper&nbspService&nbspKm"],"KpiName":["opcostperkmkpi","revenueperkmkpi","totalcostperkmkpi","claimspervehkpi","claimsperdriverkpi","claimslodgedkpi","overheadskpi"],"ValuetoPrint":[110.47252736225,5.6435200058102,5.434671444334,0.35610369406272,0.35829645079956,12.666666666667,18.054408207469],"ValueNow":[10.301680292356,0.62137119223733,0.62137119223733,1,1,19,0.62137119223733],"ValueCompare":[9.32510601353,11.010348002623,11.433463800009,280.81708128079,279.09849449204,150,3.4416591510336],"Target":["5","7","6","8","8","8","6"],"KpiUnits":["Pounds&nbspper&nbspKm","Pounds&nbspper&nbspKm","Pounds&nbspper&nbspKm","Pounds&nbspper&nbspVehicle","Pounds&nbspper&nbspDriver","Claims","Pounds&nbspa&nbspkm"],"PercentCompare":[110.47252736225,5.6435200058102,5.434671444334,0.35610369406272,0.35829645079956,12.666666666667,18.054408207469]}]) onmouseover=TopLevelLabel({"NumberSelected":7,"Description":["Operating&nbspCost&nbspper&nbspService&nbspKm","Revenue&nbspper&nbspService&nbspKm","Total&nbspCost&nbspper&nbspService&nbspKm","Claims&nbspCost&nbspper&nbspVehicle","Claims&nbspCost&nbspper&nbspDriver","Number&nbspof&nbspClaims&nbspLodged&nbspper&nbsp100,000km","Overheads&nbspCost&nbspper&nbspService&nbspKm"],"GroupDescription":"Core&nbspService&nbspPerformance"}) onmouseout=clearnew()></p>
<p id='ROPTUB' class='plot' style='height:100px;width:175px;float:left;' title='9.7292765723395' onClick=LowerLevelPrint([{"NumberSelected":2,"TargetPerc":[12.5,207.23684210526],"KpiDescription":["Revenue&nbspExpenditure&nbspper&nbspPassenger&nbspJourney","Cost&nbspPer&nbspHeadcount"],"KpiName":["revexperjourneykpi","coststaffkpi"],"ValuetoPrint":[19.044041148259,0.41451199641943],"ValueNow":[1,16.578947368421],"ValueCompare":[5.2509863437855,3999.6302909519],"Target":["8","8"],"KpiUnits":["Pounds&nbspper&nbspJourney","Pounds&nbspper&nbspStaff"],"PercentCompare":[19.044041148259,0.41451199641943]}]) onmouseover=TopLevelLabel({"NumberSelected":2,"Description":["Revenue&nbspExpenditure&nbspper&nbspPassenger&nbspJourney","Cost&nbspPer&nbspHeadcount"],"GroupDescription":"Resource&nbspOptimisation"}) onmouseout=clearnew()></p></div>';
Don't worry about disecting that as it's just an example of what can be sent. I'm assuming the problem is the multitude of quotes inside this string, as the javascript on the page entirely stops working when I include this function.
The above string is actually generated in a php loops, and the function I'm trying to use calls attempts
document.getElementById('financearea').innerHTML =
'<?php $myview->PopulateContent($finance, 8, 'ub', 'UB', $a); ?>';
`
Which works correctly when its in the main page body, but won't run when using the innerHTML method.
Does anyone have any suggestions on how this could work?
This is the code on the php side - its created and echo'd in a loop
$thisgoesinfile =
"<p id='".$Group.$Depot."' class='plot' style='height:100px;width:175px;float:left;' title='".$TotalValuetoPrint."' onClick=LowerLevelPrint(".json_encode($result_set).") onmouseover=TopLevelLabel(".json_encode($Descriptions).") onmouseout=clearnew()></p>";
Edit: I tried removing all the single quotes in the php string so now the string looks like
document.getElementById('financearea').innerHTML = <div id=gaugearray8><p id=ANCPUB class=plot style=height:100px;width:175px;float:left; title=0.0011217599587192 onClick=LowerLevelPrint([{"NumberSelected":1,"TargetPerc":[237.5],"KpiDescription":["Contribution&nbspof&nbspExternal&nbspRevenue"],"KpiName":["revcontrubionkpi"],"ValuetoPrint":[0.0011217599587192],"ValueNow":[19],"ValueCompare":[1693767],"Target":["8"],"KpiUnits":["Pounds"],"PercentCompare":[0.0011217599587192]}]) onmouseover=TopLevelLabel({"NumberSelected":1,"Description":["Contribution&nbspof&nbspExternal&nbspRevenue"],"GroupDescription":"Ancillary&nbspService&nbspPerformance"}) onmouseout=clearnew()></p><p id=CSPUB class=plot style=height:100px;width:175px;float:left; title=21.855170547342 onClick=LowerLevelPrint([{"NumberSelected":7,"TargetPerc":[206.03360584712,8.8767313176762,10.356186537289,12.5,12.5,237.5,10.356186537289],"KpiDescription":["Operating&nbspCost&nbspper&nbspService&nbspKm","Revenue&nbspper&nbspService&nbspKm","Total&nbspCost&nbspper&nbspService&nbspKm","Claims&nbspCost&nbspper&nbspVehicle","Claims&nbspCost&nbspper&nbspDriver","Number&nbspof&nbspClaims&nbspLodged&nbspper&nbsp100,000km","Overheads&nbspCost&nbspper&nbspService&nbspKm"],"KpiName":["opcostperkmkpi","revenueperkmkpi","totalcostperkmkpi","claimspervehkpi","claimsperdriverkpi","claimslodgedkpi","overheadskpi"],"ValuetoPrint":[110.47252736225,5.6435200058102,5.434671444334,0.35610369406272,0.35829645079956,12.666666666667,18.054408207469],"ValueNow":[10.301680292356,0.62137119223733,0.62137119223733,1,1,19,0.62137119223733],"ValueCompare":[9.32510601353,11.010348002623,11.433463800009,280.81708128079,279.09849449204,150,3.4416591510336],"Target":["5","7","6","8","8","8","6"],"KpiUnits":["Pounds&nbspper&nbspKm","Pounds&nbspper&nbspKm","Pounds&nbspper&nbspKm","Pounds&nbspper&nbspVehicle","Pounds&nbspper&nbspDriver","Claims","Pounds&nbspa&nbspkm"],"PercentCompare":[110.47252736225,5.6435200058102,5.434671444334,0.35610369406272,0.35829645079956,12.666666666667,18.054408207469]}]) onmouseover=TopLevelLabel({"NumberSelected":7,"Description":["Operating&nbspCost&nbspper&nbspService&nbspKm","Revenue&nbspper&nbspService&nbspKm","Total&nbspCost&nbspper&nbspService&nbspKm","Claims&nbspCost&nbspper&nbspVehicle","Claims&nbspCost&nbspper&nbspDriver","Number&nbspof&nbspClaims&nbspLodged&nbspper&nbsp100,000km","Overheads&nbspCost&nbspper&nbspService&nbspKm"],"GroupDescription":"Core&nbspService&nbspPerformance"}) onmouseout=clearnew()></p><p id=ROPTUB class=plot style=height:100px;width:175px;float:left; title=9.7292765723395 onClick=LowerLevelPrint([{"NumberSelected":2,"TargetPerc":[12.5,207.23684210526],"KpiDescription":["Revenue&nbspExpenditure&nbspper&nbspPassenger&nbspJourney","Cost&nbspPer&nbspHeadcount"],"KpiName":["revexperjourneykpi","coststaffkpi"],"ValuetoPrint":[19.044041148259,0.41451199641943],"ValueNow":[1,16.578947368421],"ValueCompare":[5.2509863437855,3999.6302909519],"Target":["8","8"],"KpiUnits":["Pounds&nbspper&nbspJourney","Pounds&nbspper&nbspStaff"],"PercentCompare":[19.044041148259,0.41451199641943]}]) onmouseover=TopLevelLabel({"NumberSelected":2,"Description":["Revenue&nbspExpenditure&nbspper&nbspPassenger&nbspJourney","Cost&nbspPer&nbspHeadcount"],"GroupDescription":"Resource&nbspOptimisation"}) onmouseout=clearnew()></p></div>;
But still not working.
Use json_encode rather than wrapping the text in single quotes yourself:
document.getElementById('financearea').innerHTML = <?php echo json_encode($myview->PopulateContent($finance, 8, 'ub', 'UB', $a)); ?>;
When you pass a string into json_encode, it will get wrapped in quotes and any quotes and other special characters within it will get correctly encoded for use as a JavaScript literal string. (This is a by-product of the fact that JSON is a subset of JavaScript's literal syntax.)
(I've also added an echo there; I'm not much of a PHP-head, so remove it if it's not needed, but you're not using short-tags, so...)
Escape the single quotes in the PHP output! :)
Replace the ' with \'
Obviously you need to ensure you are escaping quotes within strings or the Javascript will break. A simple solution would be to use double-quotes inside the string, and use single-quotes to delimit the string.
'<div id="gaugearray8">'

How can I write a square bracket to a text file in php?

I'm trying to write a php script that will generate a variety of new php pages, but I'm finding that I'm unable to write a square bracket out. When I escape a square bracket in the same way as other characters (ie [ ) the leading \ is written to the new page, which results in code that doesnt work:
echo $row\['Value'\];
When I do not escape the bracket, the page fails, and the same thing happens when I try and substitute asc(91).
I have seen other examples that use code like $row->Value, but I tried that and it didn't work. If anyone can help me output a square bracket, or knows of another method by which I can fetch a value from a row without using one at all, I'd be very grateful
Your echo would appear as an array reference to PHP. Try this:
echo $row, "['Value'];"
assuming that you want the value of $row to be output, and not the literal text $row. If you want the literal text, (e.g. you're trying to build a PHP script on the fly), then either of these should do the trick:
echo '$row[\'Value\'];';
echo "\$row['Value'];";
How about this:
echo sprintf("\$row['%s']", $value); // either scenario
echo sprintf("%s['Value']", $row);
Keep in mind that PHP automatically parses double quote strings ("), and tries to find variabels within. So, the bracket is probably not the issue, the $ variable prefix (coupled with the parser) probably is.
There are a couple other answers that work but I want to elaborate:
The "echo" construct can take a variable or a string. You can't echo a string to the screen in the same way that you do a variable. For example: echo hello; will not behave as you might think. You need to include it in quotes such as echo "hello";
You can also use single quotes. Single quotes and double quotes behave differently. For example:
$foo = "bar";
echo $foo;
echo "$foo";
echo '$foo';
The first will echo "bar", the second will also echo "bar" because PHP looks for variables in double quotes strings. The third will echo '$foo' because PHP does not try to do variable substitution in a single quoted string. So you can do (as #mark-b said):
echo "\$row['Value']";
or
echo '$row[\'Value\']';
Now, that $row->value syntax that you saw, is object notation. It is assuming that $row is an object and not an array. Objects are a whole other ballgame.
You're talking about code generation in your question, so I expect you also want to output the 'echo' statement in the generated code. Assuming you want to save the output into a file so it can be easily executed, you want to use something like fwrite or file_put_contents, I expect. You need to think in terms of strings, which can be a bit tricky when you're seeing code.
Something like this should work:
fwrite($fp, 'echo $row[\'Value\'];'."\n");
Note how the single and double quotes work. \n is resolved to a newline, but anything in the single quotes is treated as a string and is printed as is, apart from \', which should print a literal single quote in the output file.
Hope this helps.

javascript quotes inside quotes, string literal issue

I am trying to display text in a javascript tooltip
I keep getting unterminated string literals even though:
a) the quotes are being slashed, b) there are no line breaks
The text I am trying to display is:
"No, we can't. This is going to be terrible."
(its a quotation from an individual and I want those quotes to display in the tooltip)
My tooltip function works like this
onMouseOver="Tip('string here')"
After I run the string through my function to clean for javascript
function jschars($str) {
echo preg_replace("/\r?\n/", "\\n", addslashes($str));
}
It comes out looking like this in HTML:
onMouseOver="Tip('\"No, we can\'t. This is going to be terrible.\"')"
This gives me the error unterminated string literal for the first \ in Tip('\
I'm guessing its because im trying to put quotes directly inside the single quotes, how can I get around this for situations like this? (I have tried htmlspecial chars, such as replacing the " with & quot ; - I still get the error
It's because you're putting double-quotes inside the value of an XML (or html) element:
<div onMouseOver="Tip('\".......
the back-slash doesn't escape it from the context of xml/html. Technically, you'll need to entity-encode the string (after you javascript-escape it). Something like this:
<div onMouseOver="Tip('\"No, we can\'t. This is going to be terrible.\"')" >
Various browsers may or may not deal with that properly. A much better way to approach it would be to give the element an id (or a class, or some other way for you to select it), then add the mouse over handler from a standalone script.
Because of the structure of what you're doing:
onMouseOver="Tip('string here')"
...you have to do two things:
As Lekensteyn said, you need to use htmlspecialchars to turn any special HTML characters into character escapes. It does things like turn " into ", which means you can safely enclose the attribute in " characters.
But you're not just using this as an attribute, you're also putting it inside a string literal, which means you also need to do JavaScript escaping on the string. Otherwise, (in your case) a single ' character or backslash will mess up the string. So your jschars function also needs to (in order) A) Convert \ to \\, B) Convert ' to \'. That's the minimum, anyway, really you need a thorough "make this safe to put inside a JavaScript literal" function. From your question, I sort of had the impression you were doing this manually, but better to automate it for consistency.
Off-topic: Separately, I would recommend moving away from using attributes to attach handlers. Instead, look into attachEvent (IE) and addEventListener (W3C), or better yet look at a library like jQuery, Closure, Prototype, YUI, or any of several others that will smooth things out for you. For instance, attaching a mouseover handler to:
You can use this handler to handle the mouseover:
function handler() {
Tip('Your message here');
}
...which you then hook up like this with raw DOM stuff (obviously you'd make a utility function for this):
var div = document.getElementById('foo');
if (div.attachEvent) {
// Uses "onmouseover", not "mouseover"
div.attachEvent('onmouseover', handler);
}
else if (div.addEventListener) {
// Uses "mouseover", not "onmouseover"
div.attachEvent('mouseover', handler, false);
}
else {
// Fallback to old DOM0 stuff
div.onmouseover = handler;
}
Here's how Prototype simplifies that hook-up process:
$('foo').observe('mouseover', handler);
Here's how jQuery does:
$('#foo').mouseover(handler);
You should use htmlspecialchars() for this purpose. The problem is ", but HTML won't understand javascript quoting, so it stops at \".
function jschars($str) {
echo htmlspecialchars(preg_replace("/\r?\n/", "\\n", $str), ENT_QUOTES);
}
You could keep the string in javascript instead of HTML. eg:
<a onmouseover="Tip(this, 123)">choice</a>
Then something like:
var texts = {
123:"No, we can't. This is going to be terrible.",
...
};
function Tip(elm, txtId){
showTip(elm, texts[txtid];
}

Categories