When inserting (or updating) a record in mysql using prepared statements and binding of values, I ran into a problem trying to insert the word child’s which contains the extended ascii character 145 (right single quotation mark). All data after the "d" is truncated. This is true for inserting any of the MS Word odd characters. My table is encoded as utf8_general_ci and I'm utf-8 all the way through in my code. The field is of type "text."
Of course I can escape them or do a str_replace() to remove them (which is what I am choosing to do), but I'd like to understand why I can't insert them directly since I always thought prepared statements handled this.
Sample insert code - incomplete, but it shows the essential
$q = "INSERT INTO mytable (userid, title, descr) VALUES (?,?,?)";
if (!($stmt = $this->mysqli->prepare($q))) {
error_log("You have a problem...");
return false;
}
/* bind parameters for markers */
$stmt->bind_param("iss", $userid, $title, $descr);
/* execute query */
$stmt->execute();
if ($stmt->errno) {
$e = new Exception;
error_log("\r\nSql Error: " . $q . ' Sql error #: ' . $stmt->errno . ' - ' . $stmt->error . "\r\n" . $e->getTraceAsString());
return false;
} else {
$lastinsertedid = $this->mysqli->insert_id;
/* close statement */
$stmt->close();
return $lastinsertedid;
}
This should not be an issue, binding the param as a string should escape any quotes as needed.
Try this to see if you can see what the error is.
$stmt = $this->mysqli->prepare($q);
if (!is_object($stmt))
error_log("You have a problem...");
var_dump($this->mysqli);
}
P.S. Don't forget $stmt->close() after $stmt->execute() as you will run into out of sync issues when attempting multiple prepared statements
I can offer some tips on syntax clean up too, take your updated question:
$q = "INSERT INTO mytable (userid, title, descr) VALUES (?,?,?)";
$stmt = $this->mysql->prepare($q);
if (!is_object($stmt))
error_log("You have a problem...");
var_dump($this->mysqli);
}
/* bind parameters for markers */
$stmt->bind_param("iss", $userid, $title, $descr);
/* execute query */
$stmt->execute();
if ($stmt->errno) {
$stmt->close(); // Still need to close here
$e = new Exception;
error_log("\r\nSql Error: " . $q . ' Sql error #: ' . $stmt->errno . ' - ' . $stmt->error . "\r\n" . $e->getTraceAsString());
return false;
}
/* close statement */
$stmt->close();
return $this->mysqli->insert_id;
The encoding for ’ was not utf8. That is the only problem. Your code may be utf8 throughout, but the data was not.
The fact that child’s truncated after the d is the symptom non-utf8 bytes being fed into otherwise good code.
Find out what application or code is generating the ’, either figure out what encoding it is generating or figure out whether it can be made to generate utf8. In the former case, we need to change one setting, in the other case, no code change need be made.
HEX('’') is E282AC in utf8.
Related
I have the following code:
function dbPublish($status)
{
global $dbcon, $dbtable;
if(isset($_GET['itemId']))
{
$sqlQuery = 'UPDATE ' . $dbtable . ' SET active = ? WHERE id = ?';
$stmt = $dbcon->prepare($sqlQuery);
$stmt->bind_param('ii', $status, $_GET['itemId']);
$stmt->execute();
$stmt->close();
}
}
Do I need to mysql_real_escape_string in this case or am i okay?
No, you don't have to escape value yourself (i.e. no you don't need to call mysqli_real_escape_string), when you are using prepared statements : the DB engine will do that itself.
(Actually, if you were calling mysql_real_escape_string and using bound parameters, your strings would get escaped twice -- which would not be great : you'd end up with escaping characters everywhere...)
As a sidenote : your values are passed as integers (as indicated by the 'ii'), so you wouldn't have to call mysql_real_escape_string, even if you were not using prepared statements : as its name indicates, this function is used to escape... strings.
For integers, I generally just use intval to make sure the data I inject into my SQL queries really are integers.
(But, as you are using prepared queries, once again, you don't have to do that kind of escaping yourself)
No, you must not. Combining the two would result
in visible escape characters showing up in your data.
function dbPublish($status)
{
global $dbcon, $dbtable;
if(isset($_GET['itemId']))
{
$sqlQuery = 'UPDATE ' . $dbtable . ' SET active = ? WHERE id = ?';
$stmt = $dbcon->prepare($sqlQuery);
$stmt->bind_param('ii', $status, $_GET['itemId']);
$stmt->execute();
$stmt->close();
}
}
I've just learning to use prepared statement in mysqli & php. Here's the snippet of the code in question.
$stmt = $mysqli->prepare ("UPDATE courses set id=?, title=?, description=?, videourl=?, article=?, colcount=?, questiondisplayed=?, onfield=? WHERE id = ?");
if ($stmt == false) { die ('prepare() failed: ' . htmlspecialchars($mysqli->error)); }
$res = $stmt->bind_param("sssssiiis", $id, $title, $description2, $videourl, $article2, $colcount, $questiondisplayed, $onfield, $oldid);
if ($res == false) { die ('bind_param() failed: ' . htmlspecialchars($mysqli->error)); }
$res = $stmt->execute();
if ($res == false) die ('execute() failed: ' . htmlspecialchars($mysqli->error));
The problem is, even after these codes run successfully (the die function never gets called), the database is not updated at all. But it's updated successfully if I'm not using prepared statement (construct the SQL query string manually). I want to convert from using manually constructed SQL query string into prepared statement. But I'm stuck in this area. Btw, the variables supplied in bind param have been set right before these codes run. I've run a print_r ($_POST); and it shows that my POST values are contain the right data. Where's the problem? Thanks.
When I was learning about SQL security and preventing SQL injection, I learnt that its better to use bindparam when fetching results for an id like this:
//Prepare Statement
$stmt = $mysqli->prepare("SELECT * FROM my_table WHERE id=?");
if ( false===$stmt ) {
die('prepare() failed: ' . htmlspecialchars($mysqli->error));
}
$rc = $stmt->bind_param("i", $id);
if ( false===$rc ) {
die('bind_param() failed: ' . htmlspecialchars($stmt->error));
}
$rc = $stmt->execute();
if ( false===$rc ) {
die('execute() failed: ' . htmlspecialchars($stmt->error));
}
// Get the data result from the query. You need to bind results for each column that is called in the prepare statement above
$stmt->bind_result($col1, $col2, $col3, $col4);
/* fetch values and store them to each variables */
while ($stmt->fetch()) {
$id = $col1;
$abc = $col2;
$def = $col3;
$xyz = $col4;
}
$stmt->close();
$mysqli->close();
Atm, when I am fetching all results, I am using this:
$query= "SELECT * FROM my_table";
$result=mysqli_query($connect, $query);
if (!$result)
{
die('Error fetching results: ' . mysqli_error());
exit();
}
echo '<table border="1">'; // start a table tag in the HTML
//Storing the results in an Array
while ($row = mysqli_fetch_array($result)) //Creates a loop to loop through results
{
echo "<tr><td>" . $row['abc'] . "</td><td>" . $row['def'] . "</td><td>" . $row['xyz'] . "</td></tr>";
}
echo '</table>'; //Close the table in HTML
My question is:
For my second code, do I need to use bind_result when fetching all results for any security reasons similar to my first example?
If yes, how can I use prepare statement with bind_result when I am fetching all results and not using $id?
If I use the second example the way it is for fetching all results, are there any security issues?
1) For my second code, do I need to use bind_result when fetching all results for any security reasons similar to my first example?
No. bind_result() has nothing to do with security. You can use whatever method you wish with any query.
2) If yes, how can I use prepare statement with bind_result when I am fetching all results and not using $id?
Exactly the same way as with any other query. There is no difference actually. and having any particular variable doesn't matter at all.
3) If I use the second example the way it is for fetching all results, are there any security issues?
There is always a security issue. But none from the area of SQL injection in this snippet. You may wish to check for XSS issues.
Just to clarify your ambiguous question:
In case you are confusing bind_result with bind_param, here is a rule of thumb: you have to use a placeholder (and thus bind_param()) for the every variable that is going into query. Always. No exceptions.
From this rule you can simply tell if you need to use prepare() or not in any particular case.
Also, there is no need for such a long and windy code in the first example.
$stmt = $mysqli->prepare("SELECT * FROM my_table WHERE id=?");
$rc = $stmt->bind_param("i", $id);
$rc = $stmt->execute();
$stmt->bind_result($id, $abc, $def, $xyz);
while ($stmt->fetch()) {
echo $id;
}
Just set mysqli in exception mode before connect:
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
I am creating a blogging application using PHP5/SQLite3 . To insert a post in database I am executing query written below.
$db=connectToDatabase();
$tempcontent=$db->escapeString($tempcontent);
$query = "INSERT INTO posts VALUES (null,$temptitle, $tempcontent, $tempcategory, $tempauthor)";
$db->query($query);
$db=disconnectToDatabase();
I am having problem when the text input contain ' or " . when there is ', the query is not getting executed at all . If ' is not there then " is displayed with escape (\") in browser .
Sorry, I forgot to mention :
connectTodatabase() function is providing very general way to connect to database. as :
try {
$db1 = new PDO("sqlite:blog.db");
}catch( PDOException $exception ){
die($exception->getMessage());
}
return $db1;
Just post the whole class because we are not mind readers or psychics here.
The probably problem is you are not escaping data you include in your query.
Use either mysql_real_escape_string():
http://php.net/manual/en/function.mysql-real-escape-string.php
Or PDO prepared statements:
http://www.php.net/manual/en/pdo.prepare.php
I have the following code:
function dbPublish($status)
{
global $dbcon, $dbtable;
if(isset($_GET['itemId']))
{
$sqlQuery = 'UPDATE ' . $dbtable . ' SET active = ? WHERE id = ?';
$stmt = $dbcon->prepare($sqlQuery);
$stmt->bind_param('ii', $status, $_GET['itemId']);
$stmt->execute();
$stmt->close();
}
}
Do I need to mysql_real_escape_string in this case or am i okay?
No, you don't have to escape value yourself (i.e. no you don't need to call mysqli_real_escape_string), when you are using prepared statements : the DB engine will do that itself.
(Actually, if you were calling mysql_real_escape_string and using bound parameters, your strings would get escaped twice -- which would not be great : you'd end up with escaping characters everywhere...)
As a sidenote : your values are passed as integers (as indicated by the 'ii'), so you wouldn't have to call mysql_real_escape_string, even if you were not using prepared statements : as its name indicates, this function is used to escape... strings.
For integers, I generally just use intval to make sure the data I inject into my SQL queries really are integers.
(But, as you are using prepared queries, once again, you don't have to do that kind of escaping yourself)
No, you must not. Combining the two would result
in visible escape characters showing up in your data.
function dbPublish($status)
{
global $dbcon, $dbtable;
if(isset($_GET['itemId']))
{
$sqlQuery = 'UPDATE ' . $dbtable . ' SET active = ? WHERE id = ?';
$stmt = $dbcon->prepare($sqlQuery);
$stmt->bind_param('ii', $status, $_GET['itemId']);
$stmt->execute();
$stmt->close();
}
}