The problem with Mr O\\'Hara

While testing my first PHP site, I create a user with a name like Mr O’Hara, and then try to create a session for the new user, with this…

include INCLUDE_PATH . 'magicquotes.inc.php';
...
$userid = mysqli_real_escape_string($con, $_POST['userid']);

… and then I check $userid against the database to ensure it is unique, and if so…

$_SESSION['valid_user'] = $userid;

Now if I echo out $userid, I get “Mr O\'Hara”

If I try to write a comment on an existing post, the poster name within the database shows as “Mr O\”. The comment appears on the webpage as “posted by Mr O\”.

I’m also using this before outputting to the browser:


$poster = nl2br(htmlspecialchars($row['poster'], ENT_QUOTES, 'utf-8'));

What am I misunderstanding here? magicquotes.inc.php (which I’ve verified IS being found by the include statement) should be stripping out any slashes from the input to the database IF magic_quotes_gpc is running. If magic_quotes_gpc isn’t running, then magicquotes.inc.php will do nothing at all.
Then mysqli_real_escape_string should be escaping any apostrophes from the database input. It seems to be doing that, but now the escape character is also being entered into the database, and also being output to the browser. What would prevent that? I would expect that htmlspecialchars would prevent the escape character from displaying within browser output, but it isn’t doing that.

What else needs to be done to remove that “\” and show the name properly as “O’Hara”.

Note that I tried using stripslashes instead of mysqli_real_escape_string, but had the same result.

Glad that got it for you. If you are anything like me you will fall for that one again too.

For a while this may tend to push you towards using the single quotes and concatenation method when using echo, rather than double quotes all the time.

You are still going to do some escaping and unescaping when you have strings like ;


"Mine's a pint!" said Mr O'Hara 

That worked!!! My hours (actually more than a full day) of struggling are over!

This left me wondering…WHY did that work?
And then…:lightbulb

(For others following, and hoping their lightbulb might light up also…consider what happens when you replace $userid with Mr O’Hara in the following:

echo "<input type=‘hidden’ name=‘poster’ value=‘$userid’><br>
"

… now you have … value=‘Mr O’Hara’ … :slight_smile:

Thanks to everyone for their assistance with this. Sorry to be so dense, but something just isn’t going right at all and I still can’t spot the trouble.

A look into PHPMyAdmin ‘comments’ table confirms the ‘poster’ as “Mr O\”. And this is for a post I just now created. Oddly, in the ‘users’ table he is listed as “Mr O’Hara”. I’ll check into this… I think that may have just revealed where I’m doing it right, and where I’m doing it wrong. If mysqli_real_escape_string isn’t causing the slashes to be entered into the db, then what else could possibly be responsible?

And can you give an example of a ‘prepare statement’?

mysqli_real_escape_string shouldn’t be adding the slashes into the database itself unless they are already there since it only adds them to allow the data to be identified within the SQL. That’s why you use mysqli_real_escape_string instead of addslashes.

Of course you can avoid that whole issue with the SQL by using prepare statements

sorry, should have explained that better.

When you run the input query use the mysqli_real_escape_string to allow the input.
When you display it on the page, use stripslashes to remove the escape character.

You can do it where you want to display it to the screen. You do not want to do that before you put it into the database, as that is the point of using mysql_real_escape_string in the first place.

:confused:
Stripslashes? I expect that would basically just un-do what mysqli_real_escape_string is doing?

But OK, you wouldn’t have suggested it if that was the case. So where do I put it (before or after I run mysqli_real_escape_string on the $_POST data?)

stripslashes() :wink:

htmlspecialchars() doesn’t remove the “/”, it replaces html tags with their display equivalents, so you can display html tags on a page. You are thinking of stripslashes() I think.

Changing your HTML to use “double quoted” attributes will stop the O’Hara breaking them, but will stop working once you get a value containing double quotes. You need to be encoding those characters for display with [fphp]htmlspecialchars[/fphp] or [fphp]htmlentities[/fphp]

How it should work is:

  1. Disable magic quotes. That setting shouldn’t exist
  2. Escape data before using it in an SQL statement
  3. Encode data before displaying it

If your DB now contains slashes you’ll need to remove them. stripslashes might do, but you’ll feel cleaner if you actually get them out of the DB instead of just filtering them on display.

echo "<input type=‘hidden’ name=‘poster’ value=‘$userid’><br>
";

Change that to:

echo ‘<input type=“hidden” name=“poster” value="’ . $userid . '"><br>
’ ;

and see what happens.

A little progress. Please ignore my most recent post.
I’ve got the problem narrowed down quite a bit, but its still a mystery.
The userid and fullname are being entered perfectly into the ‘users’ table. But the ‘comments’ table still shows Mr O’Hara incorrectly…as “Mr O”.

Using echo statements, I’ve noticed that the session variable now echoes exactly as it should before the form in newcomment.inc.php.

//echo $_SESSION['valid_recipe_user'];   The session variable still has the slash within a name like O'Hara 
    $userid = stripslashes($_SESSION['valid_recipe_user']);
	//echo $userid;  Using stripslashes on the session variable removed the \\, and 
        //[COLOR="Red"]the user's name echoes exactly as it should even with an apostrophe[/COLOR]
    echo "<form action='index.php' method='post'>\
";
    echo "<h2>Enter your comment</h2>";
    echo "<textarea rows='5' cols='44' name='comment'></textarea><br>\
";

 	echo "<input type='hidden' name='poster' value='$userid'><br>\
";
    echo "<input type='hidden' name='recipeid' value='$recipeid'>\
";
    echo "<input type='hidden' name='content' value='addcomment'>\
";
    echo "<br><input type='submit' value='Submit'>\
";
    echo "</form>\
";

I’ve checked the db to confirm that the comments table allows ‘poster’ values up to 12 characters, so that’s not causing any truncation. But when addcomment.inc.php runs, an echo statement right after the initial includes will show $_POST[‘poster’] (which was assigned to the value of $userid in newcomment.inc.php) as “Mr O”. This is before $userid is inserted into the comments table.

include INCLUDE_PATH . 'magicquotes.inc.php';

//echo $_POST['poster']; this reveals Mr O
$recipeid = mysqli_real_escape_string($con, $_POST['recipeid']);
$poster = mysqli_real_escape_string($con, ($_POST['poster']));
$comment = mysqli_real_escape_string($con, $_POST['comment']);
$date = date("Y-m-d");
//echo $poster; this also reveals Mr O

How can ‘poster’ change from “Mr O’Hara” to “Mr O” from one script to the next?

Here is an excerpt from the ‘addcomment.inc.php’ script. Other than putting a “\” into “O’Hara”, this works fine. Even if $comment contains contractions, they do not have the “\” before the apostrophe…only $poster has that problem.

include INCLUDE_PATH . 'magicquotes.inc.php';
$recipeid = mysqli_real_escape_string($con, $_POST['recipeid']);
$poster = mysqli_real_escape_string($con, $_POST['poster']);
$comment = mysqli_real_escape_string($con, $_POST['comment']);
$date = date("Y-m-d");


$con = mysqli_connect(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME) or die('Could not connect to server');
$query = "INSERT INTO comments (recipeid, poster, date, comment) " .
" VALUES ('$recipeid', '$poster', '$date', '$comment')";
$result = mysqli_query($con, $query);

OK. htmlspecialchars won’t remove that escape character, but what will?