MySqli adding multiple rows to db - php

I'm sending data to a db from a web form but every time I run it the data is stored in the db in six new rows rather than just one.
The form is just a standard form with inputs for email/password and a submit button. The action of the form runs this:
<?php
// connect to db
$link = new mysqli("localhost", "root", "", "db_name");
if (!$link) {die('Database Error: Could not connect: ' . mysql_error());}
// username and password sent from form
$email = $_POST['email'];
$password = ($_POST['password']);
// encrypt
$salt = substr(base64_encode(mcrypt_create_iv(16, MCRYPT_DEV_URANDOM)), 0, 16);
$em = crypt($email, '$6$'.$salt);
$pw = crypt($password, '$6$'.$salt);
// insert to db
$insert = "INSERT INTO users (email, password) VALUES ('$em', '$pw')";
$link -> query($insert);
// check succes/fail
if ($link->query($insert) === TRUE) {
echo "New record created successfully";}
else {
echo "Error: " . $sql . "<br>" . $link->error;
}
// close the db connection
$link->close();
I know this brings up a question about sanitizing inputs with encryption/salting. This page says that it's a reasonable method. Please feel free to bring that up, but I'm not really looking for an argument over best practices for sanitizing user inputs.
I'm wondering if anyone cal tell me why the data would be stored 6 times instead of just once. I changed the $6$ to $1$ but it still added 6 rows.

You have some silly seo-friendly links implementation on your site that makes it run your php code on every reques, and 5 links to non-existent resources in your html.

Related

How to fix "Array index out of range?"

When logging into my Unity project, I get error "Array index is out of range" at this line of my C# code
if (www.text[0] == '0')
www.text pulls from this php script (www.text is returning null when debugging so it must be an error with my script).
<?php
$con = mysqli_connect('localhost', 'root', 'root', 'unityaccess');
//check that connection happened
if (mysqli_connect_errno())
{
echo "1: Connection failed"; //error code #1 = connection failed
exit();
}
$username = $_POST["name"];
$password = $_POST["password"];
//check if name exists
$namecheckquery = "SELECT username, salt, hash, score FROM players WHERE
username = ' " . $username . "';";
$namecheck = mysqli_query($con, $namecheckquery) or die("2: Name check query
failed"); //error code #2 - name check query failed
if (mysqli_num_rows($namecheck) != 1)
{
echo "5: Either no user with name, or more than one";
exit();
}
//get login info from query
$existinginfo = mysqli_fetch_assoc($namecheck)
$salt= $existinginfo["salt"];
$hash = $existinginfo["hash"];
$loginhash = crypt($password, $salt);
if($hash != $loginhash)
{
echo "6: Incorrect password"; //error code #6 - password does not hash to
match table
exit();
}
echo "0\t" . $existinginfo["score"];
?>
I'm following a tutorial and am new to php and sql.
https://www.youtube.com/watch?v=NVdjlXgbiMM
In the tutorial his code is exactly the same as mine. Looking at it myself I would assume that the echo "0\t" . $existinginfo["score"]; is the problem, and that putting a tab isn't separating it into an array. In his code he runs it and it's fine though, so I must be missing something else?
You have a space after the ' in the query on this line:
$namecheckquery = "SELECT username, salt, hash, score FROM players WHERE
username = ' " . $username . "';";
So if the username entered is user1 it will look in the database for <space>user1 (where <space> means a space character). Remove that space.
$namecheckquery = "SELECT username, salt, hash, score FROM players WHERE
username = '" . $username . "';";
Actually, it would be even better if you learned to use prepared statements, then problems like this are nearly impossible, as well as making the code safe from SQL-injection. Read How can I prevent SQL injection in PHP?

Pulling a hashed username from MySQL database

I'm working on a project where both the username and password need to be hashed with Argon2. I'm not having any trouble hashing them both in the registration and inserting them into the database, but I'm unable to pull the information for the login. Here is my login script:
<?php session_start(); ?>
<?php
include 'config.php';
if(isset($_POST['submit'])){
$submittedUser = $_POST['username'];
$submittedPass = $_POST['password'];
$encrypteduser = password_hash($submittedUser, PASSWORD_ARGON2I);
$con=mysqli_connect($servername, $dbusername, $dbpassword, $dbname);
// Check connection
if (mysqli_connect_errno())
{
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
if ($stmt = mysqli_prepare($con, "SELECT * FROM users Where username =?")) {
mysqli_stmt_bind_param($stmt, "s", $encrypteduser);
mysqli_stmt_execute($stmt);
$result = mysqli_stmt_get_result($stmt);
}
while($row = mysqli_fetch_array($result))
{
$username = $row['username'];
$password = $row['password'];
}
if (password_verify($submittedUser, $username) && password_verify($submittedPass, $password))
{
$_SESSION['user']=$username;
echo "<script> location.href='index.php'; </script>";
exit;
}
else
{
echo "<script> location.href='login.php'; </script>";
exit;
}
mysqli_close($con);
}
?>
My current theory is that the hash being generated and stored in $encrypteduser does not match the one in the database. That would explain why no result is being pulled. Is there a way to get around this?
This does not encrypt, it hashes:
$encrypteduser = password_hash($submittedUser, PASSWORD_ARGON2I);
I.e., it's one way. You (theoretically) can never get the original text back from it. It will also generate a different result every time you run it. As a result, you'll never be able to run a query with a WHERE clause to pick out one matching user. Rather, you'd have to iterate over every user in the system, running password_verify() against each of them.
So... don't do that. Leave the username in plain text so that you can benefit from the database index.
What you want to do cannot be done because having the username stored in clear is exactly what allows to you determine what exact credentials (i.e. table row) you need to validate against.
Imagine you tried anyway. You want to validate john.doe. You would have to loop on every stored username hash, grab the corresponding salt so you can calculate the hash with john.doe and current row salt and then compare both username hashes. If there's no match, go to next row... until you eventually get a match and can finally determine what password hash to check. All this, with al algorithm specifically designed to be slow. Go figure.

PHP login script using bind_result in subsequent query mysqli

I'm trying to build a relatively simple PHP login script to connect to MySQL database running on my home server. I know the connection works as I've gotten some data returned as I would expect. However, I am having trouble getting the full script to work.
Essentially, I'm taking in a username/password from the user, and I first do a lookup to get the user_id from the users table. I then want to use that user_id value to do a comparison from user_pswd table (i'm storing usernames and passwords in separate database tables). At one point, I was able to echo the correct user_id based on the username input. But I haven't been able to get all the issues worked out, as I'm pretty new to PHP and don't really know where to see errors since I load this onto my server from a remote desktop. Can anyone offer some advice/corrections to my code?
The end result is I want to send the user to another page, but the echo "test" is just to see if I can get this much working. Thanks so much for the help!
<?php
ob_start();
$con = new mysqli("localhost","username","password","database");
// check connection
if (mysqli_connect_errno()) {
trigger_error('Database connection failed: ' . $con->connect_error, E_USER_ERROR);
}
$users_name = $_POST['user'];
$users_pass = $_POST['pass'];
$user_esc = $con->real_escape_string($users_name);
$pass_esc = $con->real_escape_string($users_pass);
$query1 = "SELECT user_id FROM users WHERE username = ?;";
if ($result1 = $con->prepare($query1)) {
$result1->bind_param("s",$user_esc);
$result1->execute();
$result1->bind_result($userid);
$result1->fetch();
$query2 = "SELECT user_pswd_id FROM user_pswd WHERE active = 1 AND user_id = ? AND user_pswd = ?;";
if ($result2 = $con->prepare($query2)) {
$result2->bind_param("is",$userid,$pass_esc);
$result2->execute();
$result2->bind_result($userpswd);
$result2->fetch();
echo "test", $userpswd;
$result2->free_result();
$result2->close();
} else {
echo "failed password";
}
$result1->free_result();
$result1->close();
}
$con->close();
ob_end_clean();
?>

How to store data from form builder in database

I am trying to create a form builder that will enable users generate survey form/page.
After the form is generated the form attribute is stored on a table.
Question 1:
Where can I store the form attribute knowing fully well that the number of fields user might add in the form is unknown.
Question 2:
Where and how do I store data submitted through the generated form when some one for example completes the survey form.
Should I create new tables on fly for each of the form attributes? If yes what if over a million forma are created which translates to a million tables.
Is this where multi-tenancy comes into play.
Please provide your answer based on best practices.
I think I get what you're asking, but why not create one table with 100 columns, labelled 1-100. Set a limit on the amount of fields a user can create(Limit 100).
Then, POST the fields and add a sql query to store the values...?
COMMENT ANSWER
If the user is already signed in filling this form I would personally do the POST request on the same page.
<?php if (isset($_POST['field1'])){
$valueforField1 = $_POST['field1'];
$valueforField2 = $_POST['field2'];
$valueforField3 = $_POST['field3'];
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDB";
// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
$sql = "INSERT INTO Survey (field1, field2, field3) // I guess you would `have to add 100 fields here to accommodate the fields in your DB Also, you can set a default value in MySQL that way if field 56-100 is not set it has a value like 0 or add the value in this php file`
VALUES ('$valueforField1', '$valueforField2', '$valueforField3')";
if ($conn->query($sql) === TRUE) {
echo "New record created successfully";
} else {
echo "Error: " . $sql . "<br>" . $conn->error;
}
$conn->close(); ?>
COMMENT ANSWER or if you want to wait for the user to log in you can store all the values in a SESSION variable.
<?php
session_start();
if (isset($_POST['field1'];)){
if (!(isset($_SESSION['email']))){
$_SESSION['field1'] = $_POST['field1'];
// You would have to do 100 of these
}
}
?>

Data not inserting in MySQL

I am making a script for a guy and he uses Advanced Outgoing API (not familiar). He gives me this URL where the POST variable will be stored in http://example.com/your_script.php?email_address={u_email}&firstname={u_firstname}. So here is my php code. The problem is it cannot read the post values. When I echo it, it's empty.
NOTE: This is the instruction from the API Manual.
Advanced Outgoing API
You can have up to 5 URLs for each Product/Podcast/RSS Feed/Membership be notified whenever a subscriber event happens. You can enter these URLs by clicking on "Edit Notifications/Custom Fields" for a particular item. The system will then POST the following variables to the URLs you've entered. You can also include any of the variables below as a "tags" in your URL and the system will replace the tag with the actual value. This way you can post the values to an existing script that expects a variable name to be different than the ones listed below. For example, your notification URL could be: http://example.com/your_script.php?email_address={u_email}&firstname={u_firstname} . The system would then post all the variables below to: http://example.com/your_script.php?email_address=joe#example.com&firstname=Joe
$con = mysql_connect("localhost","xyz","xyz","xyz"); // Establish connection to insert in the first table.
$username = $_POST['paypal_email']; // username of the user.
$rawpass = $_POST['access_code']; // Raw password.
$pass = md5($rawpass); // Password of the user encrypted with md5.
$email = $_POST['email_address']; // E-mail of the user.
$time = date("Y-m-d H:i:s");
echo $username;
echo $pass;
echo $email;
echo $time;
mysql_query("INSERT INTO wpinrootusers ('user_login', 'user_pass', 'user_email', user_registered, 'user_status') VALUES ('$username', '$pass', '$email', '$time', 0), $con"); // Insertion into wpinrootusers table.
mysql_close($con); // Close connection.
$con = mysql_connect("localhost","xyz","xyz","xyz"); // Establish connection to insert in the second table.
mysql_query("INSERT INTO customers ('receipt', 'prod_num', 'email') VALUES ('$rawpass', '6', '$email')", $con); // Insertion into customers table.
mysql_close($con); // Close second connection.
With mysql you have to do:
$con = mysql_connect("localhost","xyz","xyz");
and then select the database:
$db = mysql_select_db("xyz");
The code you used to connect to database works with mysqli (i stands for improved) and you should consider switching from mysql to mysqli
When you send the variable as GET parameters you have to use $_GET of course.

Categories