Dynamically turning undefined index using isset() - php

I'm writing a generic function that will take a large number of fields from $_POST and build an SQL insert into a table. In this case, I have a number of Undefined indexes and from reading other posts on SO, I am using a ternary to test if the variable exists. This works perfectly when I use it in interactive php, especially since there are no $_POST variables defined.
But when I use it in my form, I seem to get a extra quote and a few returns but I cannot see where they are coming from. I've beaten about this in different ways but am hoping someone can help me see what I'm not seeing.
function SaveDonation($form) {
try {
$querystr = "INSERT INTO GeneralDonations(donationForm, firstName, startYear)"
. "VALUES(" . "'" . $form . "', "
. ((!isset($_POST['firstName']))
? "'', " : ("'" . mysql_real_escape_string($_POST['firstName'])."', "))
. ((isset($_POST['startDate']))
? ("'" . mysql_real_escape_string($_POST['startDate'])."' ") : "'' ")
.")";
echo "<pre>query = "; var_dump($querystr);die;
$donation = $this->db->insertRow($querystr);
$result = true;
} catch(MysqlException $e) {
$result = false;
$this->errorMsg = $e->getMessage();
}
return $result;
}
The startDate is the undefined index value. This is the browser output using var_dump. It appears that the x-debug output is showing instead of the variable. But all table, no useful data? Please help me see what's different here?
string 'INSERT INTO GeneralDonations(
donationForm, firstName, startYear)VALUES('buy-a-foot', 's',
'<br />\r\n<font size=\'1\'><table class=\'xdebug-error xe-notice\'
dir=\'ltr\' border=\'1\' cellspacing=\'0\' cellpadding=\'1\'>\r\n
<tr><th align=\'left\' bgcolor=\'#f57900\' colspan=' )' (length=284)

Your code has some problems:
Please use prepared statements (see below)!
The error message (which is not entirely shown) would continue with "Undefined index firstName", since there's an ! too much in (!isset($_POST['firstName'])).
The error message is incomplete because your xdebug shortens var_dump output. You can change this behaviour with the settings xdebug.overload_var_dump and xdebug.var_display_max_data. See xdebug documentation.
If you can't use prepared statements, consider using some sprintf() construction to improve readability.
// Prepared statements (untested)
$stmt = $db->prepare("
INSERT INTO GeneralDonations(donationForm, firstName, startYear)
VALUES (?, ?, ?)");
$stmt->execute(array(
$form,
isset($_POST['firstName']) ? $_POST['firstName'] : '',
isset($_POST['startDate']) ? $_POST['startDate'] : ''
));

Related

PHP 5.5, can't get call_user_func_array to work with bing_param

I have PHP version 5.5.9-1 and having trouble with call_user_func_array and bind_param for stmt. I have the following code
$query = "SELECT * FROM studentTable WHERE firstname = ?";
if(!($stmt = $conn->prepare($query))){
echo "Prepare failed: (" . $conn->errno . ") " . $conn->error;
return;
}
$paramType= 's';
$paramValue= 'bob';
$a_params = array(&$paramType, &$paramValue);
call_user_func_array(array($stmt, 'bind_param'),$a_params)
I am getting the following error and I don't know why
Binding parameters failed: (0)
I have tried wrapping the strings "'s'" but that reports that there is not enough arguments. What am i doing wrong?
Thank you
UPDATE
I have tried the code from php5.3 - mysqli_stmt:bind_params with call_user_func_array warnings but still not working
I had a similar problem (I just don't remember exactly what problem it was), I've solved this situation using ReflectionMethod.
$type = 's';
$parameter = 'bob';
$values = [$type , &$parameter];
$reflectionMethod = new \ReflectionMethod($statement , 'bind_param');
$reflectionMethod->invokeArgs($statement , $values);
$statement->execute();
The code above comes from a simple study case of my own. Created with PHP 5.5 and tested with PHP 7 (a long time ago...) on Debian Jessie.
After all, your code should work as well. With reflection, this code does the same thing as your code.
Ps.: as you can read in comments below, it slower than call_user_func_array and should be avoided in production.

PHP / MySQLi execute() on non-object

This question applies specifically to issues in the Openwall tutorial on PHP password hashing. Please read the edit below.
This question has been asked hundreds of times, but none of the answers found my issue.
$app->post("/movies", function() use ($app, $log){
$db = new mysqli(db_address,db_user,db_pass,db_database,db_port);
if ($db->connect_errno) {
$log->emergency("EM[MYSQL] Can't connect to MySQL: " . $db->error);
}
($stmt = $db->prepare("INSERT INTO movies (MovieName, MovieCover, MovieDescription, MovieDirector, MovieDate) VALUES (':title', ':cover', ':description', ':director', ':release_date')") || $log->error('ER[MYSQL] Could not prepare statement: ' . $db->error));
echo $db->error;
var_dump($stmt);
$title = grabPostVar('title');
$cover = grabPostVar('cover');
$desc = grabPostVar('desc');
$director = grabPostVar('director');
$release_date = grabPostVar('release_date');
if(!($stmt->execute(array(':title' => $title, ':cover' => $cover, ':description' => $desc, ':director' => $director, ':release_date' => $release_date))))
{
$log->emergency('EM[MYSQL] Misc issue: ' . $db->errno);
} else{
$log->info('I[MOVIE] Movie "' . $title . '" created, by user (u)$current_user(/u).');
}
$stmt->close();
$db->close();
}
On the front of this, it looks exactly the same as the other questions, but var_dump($stmt) retuns true, and according to the documentation
mysqli_prepare() returns a statement object or FALSE if an error occurred.
I used the following lines to check for this:
echo $db->error;
var_dump($stmt);
No error is printed, and var_dump yields bool(true). Any ideas? A statement very like this was working 100% very recently, but with no MySQL error return I'm completely stumped.
Edit:
Yes it was all to do with that stupid OR comparison, thank you for your answers.
if(!($stmt = $db->prepare('INSERT INTO movies (MovieName, MovieCover, MovieDescription, MovieDirector) values (?, ?, ?, ?)'))){
$log->error('ER[MYSQL] Could not prepare statment: ' . $db->error);
}
On a sidenote, I suggest that anyone following the Openwall tutorial on password hashing should change to if statements as well.
You have an issue with your parenthesis, which is causing '$stmt' to be evaluated to the result of the logical or represented by || in the line:
($stmt = $db->prepare("INSERT INTO movies (MovieName, MovieCover, MovieDescription, MovieDirector, MovieDate) VALUES (':title', ':cover', ':description', ':director', ':release_date')") || $log->error('ER[MYSQL] Could not prepare statement: ' . $db->error));
Changing it to:
($stmt = $db->prepare("INSERT INTO movies (MovieName, MovieCover, MovieDescription, MovieDirector, MovieDate) VALUES (':title', ':cover', ':description', ':director', ':release_date')")) || $log->error('ER[MYSQL] Could not prepare statement: ' . $db->error);
Will fix it, though you might consider making your code cleaner.

function to dynamic insert to Database using mysqli prepare

i need help with my function thet i build , i trying to use MYSQLI prepare but i am not so good .
this is my function :
function insertToDb($table,$rowsarray,$valuequestionmarks,$lenstrings,$valarray){
$this->mysqli->set_charset("utf8");
if ($insert_stmt = $this->mysqli->prepare(
"INSERT INTO $table ($rowsarray)
VALUES
($valuequestionmarks)"
))
{
$insert_stmt->bind_param("$lenstrings",$valarray);
// Execute the prepared query.
if(!$insert_stmt->execute())
{
die("Execute failed: (" . $insert_stmt->errno . ") " . $insert_stmt->error);
}
}
}
And this is how i call :
$img = "something.jpg";
$uip = ulUtils::GetRemoteIP(false);
$table='forgotpassqm';
$rowsarray = 'email,text,img,ip';
$valuequestionmarks ='?,?,?,?';
$lenstrings ='ssss';
$valarray ='$email,$text,$img,$uip';
$func->insertToDb($table,$rowsarray,$valuequestionmarks,$lenstrings,$valarray);
And i keep get this error :
Warning: mysqli_stmt::bind_param(): Number of elements in type definition string doesn't match number of bind variables
And the execute error :
Execute failed: (2031) No data supplied for parameters in prepared statement
i tryed allot of combination none work , i read other question none as my , and none worked or help either.
And i know this is about the ssss , but i using 4 and its seem to be alright so where i wrong here ?
Thanks allot.
EDIT :
$table output : forgotpassqm .
$rowsaray output: email,text,img,ip .
$valuequestionmarks output : ?,?,?,? .
$lenstrings output: ssss.
$valarray output: $email,$text,$img,$uip.
I think the problem is at $valarray.
Judging by the looks of it you are attempting to send a comma-delimited list of variables as an array (not how an array works) and you are using single quotes so variables aren't being interpolated to their values.
bind_param() expects a list of arguments after the type definitions. You aren't sending a list, you are sending the string '$email,$text,$img,$uip'.
Your call to that function should look like this:
$stmt->bind_param("ssss", $email, $text, $img, $uip);

Explain the difference between these 3 queries and which is the best to use?

I searched a lot but unable to find any question which is related to my problem so I posted this one.
I came to know that this following 3 line do the same work.
$q="insert into employee values('".$e."','".$nm."','".$desg."','".$sal."')";
$q="insert into employee values('$e','$nm','$desg','$sal')";
$q="insert into employee values('{$e}','{$nm}','{$desg}','{$sal}')";
$e, $name, &desg, &sal are variables.
I'm confused which one is best and why these 3 working same. 1st one is totally clear to me that it substitutes the variables with value and creates the query.
But in the 2nd and 3rd, its not clear to me how variables are substituted. That is from where I'm learning they says that if I insert a variable into a echo then it should be enclosed with {} or concatenated.
ex: echo "This is {$name}" / echo "This is ".$name;
So I'm confused.
There are not the different ways of writing queries, these are merely different ways to write strings in PHP. To clear any confusion, you should go through PHP strings manual and read about all possible ways to create strings. The documentation explains the four possible syntax plus how variables within strings are "parsed".
Before you write queries (safe ones) you must understand how strings work in PHP. You can then go through these answers to find out the proper way of writing queries.
As people have started to point out in the comments, none of these methods is advisable or safe.
The problem is SQL injection as explained here.
You want to use PDO. See this tutorial or this reference.
So to connect:
$dsn="mysql:host=127.0.0.1;dbname=myDatabase";
$username="myUsername";
$password="myPassword";
try {
$DBH=new PDO($dsn,$username,$password);
} catch(PDOException $e) {
echo $e->getMessage();
}
And a sample insertion:
$STH = $DBH->prepare("INSERT INTO job (snum, date, length, type, ref) VALUES (:u,:d,:l,:t,:r)");
$STH->bindParam(':u', $myVariable1);
$STH->bindParam(':d', $myVariable2);
$STH->bindParam(':l', $myVariable3);
$STH->bindParam(':t', $myVariable4);
$STH->bindParam(':r', $myVariable5);
try {
$STH->execute();
} catch(PDOException $e) {
echo $e->getMessage();
}
To answer your question:
This is simple string concatenation:
$q="insert into employee values('" . $e . "','" . $nm . "','" . $desg . "','" . $sal . "')";
This is value substitution, which PHP will do with string literals that use " ":
$q="insert into employee values('$e','$nm','$desg','$sal')";
The third sample is not correct. { and } are only necessary when you want to use the substitution from #2 with array values:
$q="insert into employee values('{$e[0]}','{$nm[0]}','{$desg['somekey']}','{$sal[o]}')";
As mentioned repeatedly, you seriously do not want to be using any of these to build a query string. Both PDO and the MySQLi library have parameterizing functions that are much safer.
On comparison of these four queries we got:
echo "My name is $name" //0.00099992752075195
echo "My name is ".$name; //0.00099992752075195
echo "My name is {$name}"; //0.0010001659393311
echo "My name is '{$name}'"; //0.0010001659393311
which proves first query will perform better.
these three are good in general use but are most vulnerable to sql injection better use:
use Prepared statements.
eg :
<?php
$q = 'Insert INTO counter(num) values (?);
$stmt = mysqli_prepare($dbc, 'i'); // check weather only integer is passed
mysqli_stmt_bind_param($stmt, 'i', $n);
for($n=1;$n<= 100; $n++)
{
mysqli_stmt_execute($stmt);
}
?>
`
Use PDO objects in php.

Error only on server with PDO: "Only variables can be passed by reference"/"Cannot pass parameter 2 by reference pdo"

I'm getting the following errors when trying to loop through an array on my server to bind statements with PDO:
"Only variables can be passed by reference"
or
"Cannot pass parameter 2 by reference pdo"
Works fine on my local XAMPP.
Code:
$sql = rest of sql query etc.
$loop = 1;
foreach ($animal_array $ani)
{
if ($loop == 1) {$sql .= " WHERE animal.id= :animal_id".$loop; }
else {$sql .= " OR animal.id= :animal_id".$loop;}
$loop++;
}
$stmt = $crud->db->prepare($sql);
$loop = 1;
foreach ($animal_array as $ani)
{
$stmt->bindParam(':animal_id'.$loop, $ani['animal_id'], PDO::PARAM_STR);
$loop++;
}
Also tried this at the end as I read somewhere that concatonations sometimes aren't liked:
foreach ($animal_array as $ani)
{
$ref = ":animal_id".$loop;
$stmt->bindParam($ref, $ani['animal_id'], PDO::PARAM_STR);
$loop++;
}
.
EDIT:
The array contains other values, sort of like this:
$animal_array['animal_id'];
$animal_array['name'];
$animal_array['colour'];
$animal_array['quantity']; etc
You ought to use bindValue for pure input parameters. The bindParam method is reserved for binding variables which can be used as input but also return query results (output).
Though that doesn't explain your issue. But we don't know what your array contains.
It's not the key generation / concatenation for sure.
It feels like you're overcomplicating matters... why not just pass the array to execute directly:
$sql .= 'WHERE animal.id IN ('
. '?'.str_repeat(',?', count($animal_array['animal_id'])-1)
. ')';
$qry = $crud->db->prepare($sql);
$qry->execute($animal_array['animal_id']);

Categories