How to encode a URL as javascript string in PHP-generated HTML? - php

Given this PHP code:
<a onclick="javascript:window.location.href='<?php echo $url;?>'"
What if there is a ' in $url?
I tried using json_encode($url) but it won't be able to handle this.

json_encode will work. You just have to use it the right way:
<a onclick="javascript:window.location.href=<?php echo htmlspecialchars(json_encode($url)); ?>">
This will work since json_encode already returns an JavaScript expression with quotes. And htmlspecialchars is needed to escape possible HTML meta characters.

Related

Quotes in a php var

I am quite new in php. I have to store a img tag in a var. I think this is ok:
$fotoTag1 = "<img src='42.png'
alt='text alt'>";
But the problem comes if there is a single quote in the name of the photo or in the alt?. For intance, don't
What I have tried:
$fotoTag1 = "<img src='don't.svg' alt='don't>'";
echo htmlspecialchars ($fotoTag1);
echo addslashes($fotoTag1);
$fotoTag2 = "<img src='don\'t.svg' alt='don\'t'>";
echo $fotoTag2;
(This is a simplified example but the url and alt comes from a sql database and of course, I cannot change the text manually. I need a general solution)
Use htmlspecialchars() to properly encode the text fragments you use to build the HTML fragment, not the HTML you built:
$fotoTag1 = '<img src="'.htmlspecialchars("don't.svg").'" alt="'.htmlspecialchars("don't").'">';
Or, to be more clear:
// Wrapped for clarity
$fotoTag1 = sprintf(
'<img src="%s" alt="%s">',
htmlspecialchars("don't.svg"),
htmlspecialchars("don't")
);
Read about sprintf() and the different ways to specify a string in PHP.
addslashes() doesn't help when you build HTML content. As a side note, it is an obsolete function that doesn't have many usages nowadays.
$fotoTag2 = "<img src=\"don't.svg\" alt=\"don't\">";
echo $fotoTag2;
$fotoTag1 = "<img src='don't.svg' alt='don't>'";
Your problem here has nothing to do with PHP.
You have an HTML attribute value delimited with apostrophe characters and you want to use an apostrophe inside that value.
When you want to represent a character with special meaning in HTML as that raw character, you can use a character reference.
This can be a named entity (&apos;) or one of the numeric references to the position of the character in unicode (');
<img src='don&apos;t.svg' alt='don't'>
Beware: &apos; was added to HTML relatively late. Old versions of IE do not support it.
Alternatively you could change your HTML so you use double quotes to delimit the data:
<img src="don't.svg" alt="don't">
This would introduce a PHP problem because you are using them to delimit the string literal.
In this case you would need to escape the data for PHP, which you do with a backslash character.
$fotoTag1 = "<img src=\"don't.svg\" alt=\"don't\">";
Alternatively, you could use some other form of string generation, such as HEREDOC.
$fotoTag1 = <<<END
<img src="don't.svg" alt="don't">
END;
As a rule of thumb, it is better to avoid storing HTML in variables in the first place.
When you want to output data, just switch to output mode:
?>
<img src="don't.svg" alt="don't">
<?php
You can always drop back into PHP mode if you need a variable.
$src = "don't.svg";
$alt = "don't";
?>
<img src="<?php echo htmlspecialchars($src); ?>" alt="<?php echo htmlspecialchars($alt); ?>">
<?php
(Note that for the characters involved, htmlspecialchars isn't needed in this example, but it does protect you when dealing with programmatically acquired data that you can't guarantee to be HTML safe).
You had the right idea using htmlspecialchars(), the issue with this specific example is that function does not escape ' by default. You need to add the flag ENT_QUOTES to escape single quotes with htmlspecialchars().
You should also be applying this function just to strings you wish to escape, not the entire html line. This could, and most likely will in most cases, cause unintended side effects of escaping characters you didn't want escaped.
Try this, it's working:
$fotoTag1 = '<img src="'.htmlspecialchars("don't.svg").'"
alt="'.htmlspecialchars("don't").'">';
echo $fotoTag1;
You should use the html ascii codes, so for your example:
$fotoTag2 = "<img src='don't.svg' alt='don't'>";
Since ' is the ascii code for single quote.

Sending HTML string via POST to PHP. Get weird characters when ECHOing it out

So I am making a simple script where I send a HTML string via POST to PHP and when I try to echo it out it gets encoded with some weird characters
The string Im sending:
'Yo <i>whats up</i>'
What I get when I echo it out with PHP
Yo+%3Ci%3Ewhats+up%3C%2Fi%3E
What is going on here? Is there some PHP method I can use to revert it back to the original HTML string?
You want to use
echo htmlspecialchars(urldecode('Yo+%3Ci%3Ewhats+up%3C%2Fi%3E'));
The reason is that your data gets x-www-form-urlencoded for posting. So on the server-side, you have to decode it again - that's what urldecode() does.
htmlspecialchars() prevents your HTML-Tags to be rendered as such so they are just displayed as a string (if that's what you want).
So, in an HTML context, echo urldecode('Yo+%3Ci%3Ewhats+up%3C%2Fi%3E'); would output
Yo whats up
And if you also wrap it with htmlspecialchars(), your output would be
Yo <i>whats up</i>
again.
It looks like your post string is being encoded for url.
you can use urldecode to remove these characters
echo urldecode($_POST['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">'

Proper way to pass complex variables to javascript through HTML

I was trying to get away from using PHP's htmlentities and here's where I stopped:
<?php
echo '<img ... onclick="MP.view(\''.$i->name.'\') />';
?>
But then I thought, instead of doing replaces and checks for special characters, I'll just JSON the entire object.
<?php
echo '<img ... onclick="MP.view('.json_encode($i).') />';
?>
And this provided a much undesired result putting in a ton of double quotation marks.
So how should I do this? Should I assign a numerical unique id to every image and just pass the id, and then look up the rest of the data from a JS array?
The correct approach in such cases would be:
htmlspecialchars(json_encode($var), ENT_QUOTES, "UTF-8")
htmlspecialchars turns any double quotes into the proper HTML escapes, making the resulting string suitable for most attributes. The ENT_QUOTES parameter also takes care of single quotes; but you probably don't need that in your example.
It would take a whole lot less escaping (and fewer bytes) to pass the data something like this:
echo '<script>var myObj = '.json_encode($i).'</script>';
Then, your code could look more like this:
echo '<img ... onclick="MP.view(myObj)" />';

php echoing angle brackets

I want to display text on the page, the text should look like this:
<sometext> ... but when I echo this, nothing appears!!
How ca I do this?
A "page" is written in HTML, so < means "Start a tag".
You have to represent characters with special meaning in HTML using entities.
You can write them directly, or make use of the htmlspecialchars function.
echo "<sometext>";
echo htmlspecialchars("<sometext>");
You probably want <sometext>.
If that text is coming from user input, you should definitely use htmlspecialchars() on it, to help prevent XSS.
This is because the browser assumes it is an unknown tag. If you want the browser to show it, use:
echo '<sometext>';
or use the htmlentities function like so:
echo htmlentities('<sometext>');
You need to call htmlentities() to convert the HTML metacharacters into something that will display properly.

Categories