3

I've this PHP page:

<?php

$lines = array();
$lines[] = "I am happy";
$lines[] = "I'm happy";

foreach ($lines as $line){
    $message = htmlspecialchars($line);
    ?>
    <div onclick="alert('<?=$message?>');"><div>
    <?php
}

It generates this HTML results:

<div onclick="alert('I am happy');"><div>
<div onclick="alert('I&#039;m happy');"><div>

This code seems to be correct, however, clicking on second "div" element an error occurs.

The &#039; char is equivalent to ' and javascript generates an error:

alert('I'm happy');"

I solved this problem adding to code addslashes() PHP function:

$lines = array();
$lines[] = "I am happy";
$lines[] = "I'm happy";

foreach ($lines as $line){
    $message = htmlspecialchars(addslashes($line));
    ?>
    <div onclick="alert('<?=$message?>');"><div>
    <?php
}

Correct results:

<div onclick="alert('I am happy');"><div>
<div onclick="alert('I\&#039;m happy');"><div>

My question:

Is this the right/best solution? Which is the best practice to manage this kind of problems?

2
  • Why do you use htmlspecialchars in the first place, since the text comes from your server to the user? Commented Aug 26, 2015 at 13:11
  • 1
    @RoumelisGeorge — It's good practise for any time the input is supposed to be plain text. You never know when the strings will get special characters added to them because another developer makes a change or someone puts some unexpected data in a database. Commented Aug 26, 2015 at 13:23

3 Answers 3

5

Don't try to generate JavaScript string literals by mashing strings together. json_encode will do it for you along with all the escaping (', ", new lines, etc) that you need for JS. It is preferred to addslashes because it is designed for the target data format and isn't generic (generic escaping solutions tend to miss things).

Encode data for HTML attribute values as the last thing you do to the data before putting it in the value. Don't encode for HTML before putting data into JavaScript.

foreach ($lines as $line){
    $message = json_encode($line);
    $javascript = "alert($message)";
    $html = htmlspecialchars($javascript);
    ?>
    <div onclick="<?= $html ?>"><div>
    <?php
}

That said, a modern approach would generally keep the JavaScript separate and store the data in a data attribute.

You should also avoid putting click events on div elements, they aren't designed to be user controls so they can't (without more mucking about) be triggered by (for example) focusing the element and pressing enter which creates accessibility problems.

foreach ($lines as $line){
    $html = htmlspecialchars($line);
    ?>
    <button type="button" data-message="<?= $html ?>">...</button>
    <?php
}

with

<script>
function buttonAlert(event) {
    var message = event.target.dataset.message;
    if (message) {
        alert(message);
    }
}
addEventListener("click", buttonAlert);
</script>
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for your time @Quentin I appreciate that!
1

Your correct result is actually wrong, and would output I&#039;m happy instead of I'm happy.

Asside from that, yes your solution will work and i don't see any problem with that way of doing in your particular context.

Comments

0

You can use below code

  <?php
    $lines = array();
    $lines[] = "I am happy";
    $lines[] = "I'm happy";
    foreach ($lines as $line){ ?>
  <div onclick="alert('<?=addslashes($line); ?>');"><div>
    <?php } ?>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.