Some values do not submit: two different SQL's - php

In my last question people said that I need to use prepared statements to avoid SQL injection.
I'm changing the previous SQL's now to prepared statements, as y'all wanted.
The thing is, it submits the settings, this part:
$stmt_setsettings = mysqli_stmt_init($conn);
if (!mysqli_stmt_prepare($stmt_setsettings, $usersettings_sql)) {
array_push($errors, "Safe SQL failed, could not insert settings. Contact the helpdesk.");
} else {
mysqli_stmt_bind_param($stmt_setsettings, "sssss", $email_show, $fname_show, $lname_show, $private_account, $profile_style);
mysqli_stmt_execute($stmt_setsettings);
}
But it submits none of the actual info I need (like the username, firstname, ...)
Also, at the end of the code below it should redirect to the new profile, normally if this feels it should display "Something went wrong, refer to the helpcenter. (SE100)" but it like refreshes the sign up page and throws no error, while there is an error: the not submitting info!
I tried searching up similar questions or fixes but nothing useful found.
Can you check out the following code and let me know what is the deal with the not submitting values? Thanks!
// Finally, register user if there are no errors in the form
if (count($errors) == 0) {
$password = md5($password_1); // Encrypt the password before saving in the database
$user_ip = $_SERVER['REMOTE_ADDR']; // Getting the IP of the user
$bio = $config['default-bio']; // Setting default biography
$profileimg = $config['default-profileimg']; // Setting default profile image
$timestamp = date('d.m.Y'); // Defining the current date
$activity = "on"; // Defining which state the user profile is in, online
$userdata_sql = "INSERT INTO users (username, bio, activity, profileimg, regdate, email, password, firstname, lastname, gender, birthday, country, ip)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
$usersettings_sql = "INSERT INTO usersettings (show_email, show_fname, show_lname, private_acc, profile_style)
VALUES (?, ?, ?, ?, ?)";
$stmt_signup = mysqli_stmt_init($conn);
if (!mysqli_stmt_prepare($stmt_signup, $userdata_sql)) {
array_push($errors, "Safe SQL failed, could not sign up. Contact the helpdesk.");
} else {
mysqli_stmt_bind_param($stmt_signup, "sssssssssssss", $username, $bio, $activity, $profileimg, $regdate, $email, $password, $fname, $lname, $sex, $bday, $country, $user_ip);
mysqli_stmt_execute($stmt_signup);
}
$stmt_setsettings = mysqli_stmt_init($conn);
if (!mysqli_stmt_prepare($stmt_setsettings, $usersettings_sql)) {
array_push($errors, "Safe SQL failed, could not insert settings. Contact the helpdesk.");
} else {
mysqli_stmt_bind_param($stmt_setsettings, "sssss", $email_show, $fname_show, $lname_show, $private_account, $profile_style);
mysqli_stmt_execute($stmt_setsettings);
}
session_regenerate_id();
$_SESSION['username'] = $username;
$_SESSION['loggedin'] = true;
// Generate user id
$generateid_sql = "SELECT id FROM users WHERE username=? ORDER BY id";
$stmt_generateid = mysqli_stmt_init($conn);
if (!mysqli_stmt_prepare($stmt_generateid, $generateid_sql)) {
array_push($errors, "Safe SQL failed, could not generate a new ID. Contact the helpdesk.");
} else {
mysqli_stmt_bind_param($stmt_generateid, "s", $username);
mysqli_stmt_execute($stmt_generateid);
$generateid_result = mysqli_stmt_get_result($stmt_generateid);
}
while ($id = mysqli_fetch_assoc($generateid_result)) {
if ($id['username'] <= 0) { // Checking if the user id is a valid id (not below or equal to 0), and if not, displaying a critical error
array_push($errors, "Something went wrong whilst signing up, please refer to the helpcenter. (SE100)");
}
if ($id['username'] > 0) { // Redirecting the user to his or her profile if it is a valid id
header('location: /content/users/profile?id=' . $id['username'] . '');
}
}
}
}

First off, PLEASE don't ever store passwords like this:
$password = md5($password_1); // <-- Totally insecure
Instead use the built-in password_hash() and password_verify() functions. See https://www.php.net/manual/en/faq.passwords.php for a good overview of why md5() is not secure and examples how to handle password storage correctly.
Also, I'd recommend pulling the user out of the database and validating the password, BEFORE setting $_SESSION['loggedin'] = true.
Regarding your question, I'd recommend adding some additional error handling and result checking around your calls to $conn->prepare() and $stmt->bind_param. See mysqli_stmt_execute() does not execute the prepared query for examples of how to check $stmt->errors.
Another general recommendation is checking $stmt->affected_rows to see if your insert statements are actually being executed as you expect. Your inserts should each be affecting 1 row.
Lastly, turning on the MySQL query log can be a great troubleshooting tool: How to show the last queries executed on MySQL? . Are all the SQL queries in your code showing up in the log? Try running the queries manually and see if the results look right.

// Finally, register user if there are no errors in the form
if (count($errors) == 0) {
$password = md5($password_1); // Encrypt the password before saving in the database
$user_ip = $_SERVER['REMOTE_ADDR']; // Getting the IP of the user
$bio = $config['default-bio']; // Setting default biography
$profileimg = $config['default-profileimg']; // Setting default profile image
$timestamp = date('d.m.Y'); // Defining the current date
$activity = "on"; // Defening wich state the user profile is in, online
$userdata_sql = "INSERT INTO users (`username`, `bio`, `activity`, `profileimg`, `regdate`, `email`, `password`, `firstname`, `lastname`, `gender`, `birthday`, `country`, `ip`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
$usersettings_sql = "INSERT INTO usersettings (`show_email`, `show_fname`, `show_lname`, `private_acc`, `profile_style`)
VALUES (?, ?, ?, ?, ?)";
$stmt_signup = $conn->prepare($userdata_sql);
$stmt_signup->bind_param("sssssssssssss", $username, $bio, $activity, $profileimg, $timestamp, $email, $password, $fname, $lname, $sex, $bday, $country, $user_ip);
if(!$stmt_signup->execute()){
array_push($errors,mysqli_error($conn));
}
$stmt_setsettings=$conn->prepare($usersettings_sql);
$stmt_setsettings->bind_param("sssss", $email_show, $fname_show, $lname_show, $private_account, $profile_style);
if(!$stmt_setsettings->execute()){
array_push($errors,mysqli_error($conn));
}
session_regenerate_id();
$_SESSION['username'] = $username;
$_SESSION['loggedin'] = true;
// Generate user id
$generateid_sql = "SELECT `id`,`username` FROM `users` WHERE `username`=? ORDER BY `id` limit 1";
$stmt_generateid=$conn->prepare($generateid_sql);
$stmt->generateid->bind_param("s", $username);
if(!$stmt_generateid->execute()){
array_push($errors,mysqli_error($conn));
}else{
$generateid_result = $stmt_generateid->get_result();
}
$username_assoc = mysqli_fetch_assoc($generateid_result);
if ($username_assoc['id'] > 0) {
// Redirecting the user to his or her profile if it is a valid id
header('location: /content/users/profile?id=' . $username_assoc['username'] . '');
}else{
array_push($errors, "Something went wrong whilst signing up, please refer to the helpcenter. (SE100)");
}
}

Related

bind_param doesn't replace ?s in my prepared statement

It registers the user successfully. But when I check it on my database, all of the values are 0s. What's the problem?
here's the function code:
public function insertUser($email, $firstName, $lastName, $encryptedPassword, $salt)
{
//SQL language - command to insert data
$sql = "INSERT INTO users (email, firstName, lastName, password, salt) VALUES (email=?, firstName=?, lastName=?, password=?, salt=?)";
//preparing SQL for execution by checking the validity
$statement = $this->conn->prepare($sql);
//if error
if (!$statement)
{
throw new Exception(($statement->error));
}
//assigning variables instead of '?', after checking the preparation and validity of the SQL command
$statement->bind_param('sssss', $email, $firstName, $lastName, $encryptedPassword, $salt);
//result will store the status/result of the execution of SQL command
$result = $statement->execute();
return $result;
}
The parameters for the function get set with the correct values when called, I tested it
I'm pretty new to PHP. If i correct my function, it doesn't create a new user. It doesn't even print out anything in the browser window. Here's the piece of code that calls this one (maybe it helps you with finding the solution):
$result = $access->insertUser($email, $firstName, $lastName, $encryptedPassword, $salt);
//result is positive
if ($result)
{
//throw back the user details
$return['status'] = '200';
$return['message'] = 'Successfully registered';
$return['email'] = $email;
$return['firstName'] = $firstName;
$return['lastName'] = $lastName;
echo json_encode($return);
$access->disconnect();
}
Your query is wrong.
//columns are declared here
$sql = "INSERT INTO users (email, firstName, lastName, password, salt) VALUES (email=?, firstName=?, lastName=?, password=?, salt=?)";
//you do not need to declare your columns again
Simple change your query to
$sql = "INSERT INTO users (email, firstName, lastName, password, salt) VALUES (?, ?, ?, ?, ?)";
Also, it appears as though you are storing your password and the salt separately, that tells me you are rolling your own hashing algorithm, there isn't really a need for this. I would remove your salt column, and use password_hash() for your password column.
remove the column=?
$sql = "INSERT INTO users (email, firstName, lastName, password, salt) VALUES (?, ?, ?, ?, ?)";
the code
column=?
in your value assignment is evalued as boolean condition that return false (0)

Prevent Duplicate Entries in PHP MySQL

I have the following in my PHP.
$stmt = $conn->prepare("INSERT IGNORE INTO savesearch (user, searchedFor, sortOrder, buildURLString, aspectFilters, oneSignalId, totalEntries)
VALUES (?, ?, ?, ?, ?, ?, ?)");
$stmt->bind_param("sssssss", $user, $searchedFor, $sortOrder, $buildURLString, $aspectFilters, $oneSignalId, $totalEntries);
// set parameters and execute
$user = $_POST['user'];
$searchedFor = $_POST["searchedFor"];
$sortOrder = $_POST["sortOrder"];
$buildURLString = $_POST["buildURLString"];
$aspectFilters = $_POST["aspectFilters"];
$oneSignalId = $_POST["oneSignalId"];
$totalEntries = $_POST["totalEntries"];
if ($stmt->execute()) {
$output->success = true;
echo json_encode($output);
} else {
$error->error = mysqli_error($conn);
echo json_encode($error);
}
However, IGNORE is not being picked up, it continues to add entries. Is there another good way to fix this?
Id like to see if the USER and the URL is the same, dont add, echo duplicate entry.
IGNORE is actually mostly for the opposite of what you want here. Instead, you can amend your MySQL table something like:
ALTER TABLE savesearch ADD UNIQUE KEY(user, buildURLString)
Then remove your IGNORE keyword

How to fix stmt prepare and bind

I am having trouble using this prepare and bind. I have tried the same thing with less variables to bind. I have been successful using prepare with just Fname, Lname, Password, $UserID and using sssi with the bind_param object. Can someone explain what I am doing wrong when using more variables in my bind code? With the code below it only prints out the same data from mysqli and doesn't update it.
if ($stmt = $con->prepare("UPDATE users SET Fname = ?, Lname = ?, Password = ?, UserLevel = ?, Email = ?, WHERE UserID= ?"))
{
$stmt->bind_param("ssssssi", $firstname, $lastname, $PW, $UserLevel, $EM, $UserID);
$stmt->execute();
$stmt->close();
}
// show an error message if the query has an error
else
{
echo "ERROR: could not prepare SQL statement.";
}
// redirect the user once the form is updated
header("Location: admin.php");
Although you haven't specified the data types which makes this tricky, I'll hazard a guess.
Fname = s
Lname = s
Password = s
UserLevel = i (?)
Email = s
I count 4 s' there, yet you have 6.
Try this,
$stmt->bind_param("sssisi", $firstname, $lastname, $PW, $UserLevel, $EM, $UserID);
Edit 1
As #Fred-ii- said, your SQL query is wrong.
Change
"UPDATE users SET Fname = ?, Lname = ?, Password = ?, UserLevel = ?, Email = ?, WHERE UserID= ?"
to,
"UPDATE users SET Fname = ?, Lname = ?, Password = ?, UserLevel = ?, Email = ? WHERE UserID= ?"
You had a training ,.

Mysqli prepared statements register

Okay I have one question. I need to check if the user already exists but the question is now what I need to type in the if() I can't fetch because I have closed but if I didn't close i got an error because there can't run 2 statements. So I think if there are someone who can help me? I have the rest code but I only give the code here.
Here is my code:
$result = $mysqli->prepare("SELECT username FROM user WHERE username=?");
$result->bind_param("s", $username);
$result->execute();
$result->bind_result($username);
$result->close();
if (){
$register = $mysqli->prepare("INSERT INTO user
(username, password, email, rr, rank)
VALUES (?, ?, ?, ?, ?)");
$register->bind_param("sssii", $username, $kode, $email, $rr, $rank);
$register->execute();
$register->close();
} else {
echo "User already exists!";
}
UPDATED: more logical statement
$result = $mysqli->prepare("SELECT username FROM user WHERE username=?");
$result->bind_param("s", $username);
$result->execute();
$found = $result->fetch();
$result->close();
if ($found){
echo "User already exists!";
} else {
$register = $mysqli->prepare("INSERT INTO user
(username, password, email, rr, rank)
VALUES (?, ?, ?, ?, ?)");
$register->bind_param("sssii", $username, $kode, $email, $rr, $rank);
$register->execute();
$register->close();
}

Mysqli Procedural Insert Into Table not working

I am trying to insert into a table with Procedural Mysqli. It is not posting any errors nor is it posting the information to the database. Here is my code:
$query = "INSERT INTO Accounts (FirstName, LastName, Username, Password, Access) VALUES ({$_POST['FirstNameTbx']}, {$_POST['LastNameTbx']}, {$_POST['UsernameTbx']}, {$_POST['PasswordTbx']}, {$_POST['AccessDDL']})";
mysqli_query($link, $query);
mysqli_close($link);
$Error .= "$query";
Update:
I changed to prepared statement, now I am getting:
Warning: mysqli_stmt::bind_param() [mysqli-stmt.bind-param]: Number of elements in type definition string doesn't match number of bind variables in /home/bryantrx/public_html/ec/add_user.php on line 19
There are only 5 variables that need to be bound, and the UserID auto increments, so it doesn't need to be bound or referenced in the statement..
if ($stmt = $link->prepare("INSERT INTO Accounts (FirstName, LastName, Username, Password, Access) VALUES (?, ?, ?, ?, ?)")){
$stmt->bind_param($_POST['FirstNameTbx'], $_POST['LastNameTbx'], $_POST['UsernameTbx'], $_POST['PasswordTbx'], $_POST['AccessDDL']);
$stmt->execute();
$Error .= "success";
$stmt->close();
} else {
echo $link->error;
}
To get an error message you need to call mysqli_error:
$error = mysqli_error($link);
You would also make life easier (and more secure) for yourself if you built your queries using prepare and parameters:
$query = "INSERT INTO Accounts (FirstName, LastName, Username, Password, Access)
VALUES ( ?, ?, ?, ?, ?)";
if ($stmt = mysqli_stmt_prepare($link, $query)) {
mysqli_stmt_bind_param($stmt, "sssss",
$_POST['FirstNameTbx'],
$_POST['LastNameTbx'],
$_POST['UsernameTbx'],
$_POST['PasswordTbx'],
$_POST['AccessDDL']);
if (!mysqli_stmt_execute($stmt)) {
$error = mysqli_stmt_error($stmt);
}
mysqli_stmt_close($stmt);
} else {
$error = mysqli_error($link);
}
mysqli_close($link);
UPDATE - ok, you've swapped to OO which is fine. When using bind_param the first parameter describes the data you are binding. In this case if it is five strings, you would put 5 "s" like so:
$stmt->bind_param("sssss",
$_POST['FirstNameTbx'],
$_POST['LastNameTbx'],
$_POST['UsernameTbx'],
$_POST['PasswordTbx'],
$_POST['AccessDDL']);

Categories