Search code examples
phpvalidationescapinghtmlspecialchars

Why is htmlspecialchars consistently displaying " and ' instead of the actual quotes in PHP?


I have data being processed from a user, that is sanitized and validated, using filter_var() in both cases. It's then stored in the database, and accessed later on a different page of the site. I escape the output using htmlspecialchars($var, ENT_QUOTES);

However, if a user enters a single quote or a double quote at any point in their input, it gets displayed as " for double quotes and ' for single quotes. It is also stored in the database as " and '

I need the browser to render the actual quote and not this code.

I've looked everywhere on stackoverflow and I can't seem to find a specific answer to my problem.

Below is a snippet of some of the data that gets sanitized - Data is then validated for length, and whether it's empty or not, and formatting in some cases like postal code.

$contact_postal = filter_var($_POST['contact-postal'], FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_HIGH);
$contact_address = filter_var($_POST['contact-address'], FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_HIGH);
$contact_person = filter_var($_POST['contact-person'], FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_HIGH);
$contact_person_phone = filter_var($_POST['contact-person-phone'], FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_HIGH);
$contact_additional_details = filter_var($_POST['contact-additional-details'], FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_HIGH);

Here's some of the data that gets retrieved for display

$postal_code = htmlspecialchars(safeDecrypt($row['postal_code'], $enc_key), ENT_QUOTES);

if (!empty($row['address'])) $address = htmlspecialchars(safeDecrypt($row['address'], $enc_key), ENT_QUOTES);

$contact_person = htmlspecialchars($row['contact_person'], ENT_QUOTES);

if (!empty($contact_person) && !empty($contact_person_phone)) $contact_person_phone = htmlspecialchars(safeDecrypt($row['contact_person_phone'], $enc_key), ENT_QUOTES);

$contact_details = htmlentities($row['contact_details'], ENT_QUOTES, "UTF-8"); //used alternatively to test (but same problem occurs)

The safeDecrypt function simply decrypts the data that was previously encrypted. It is highly unlikely that it is the problem, as the ' problem occurs with or without it.


Solution

  • If you want to prevent htmlspecialchars from converting ' or " you can use the ENT_NOQUOTES flag instead e.g.:

    $contact_details = htmlentities($row['contact_details'], ENT_NOQUOTES, "UTF-8"); 
    

    htmlspecialchars docs


    If you're wanting to preserve the quotes when using filter_var you can use the FILTER_FLAG_NO_ENCODE_QUOTES e.g.

    $contact_postal = filter_var($_POST['contact-postal'], FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_HIGH | FILTER_FLAG_NO_ENCODE_QUOTES);
    

    sanitize filters