Good day everyone, I'm trying to prevent duplicate records from being injected into a database of mine, I'm using the following code to prevent the data:
$con=mysqli_connect("localhost","root","","dbPos");
$first=trim($_POST['first']);
$last=trim($_POST['last']);
$emailaddress=trim($_POST['emailaddress']);
$queryF = "SELECT firstname FROM tbData WHERE firstname=='$first'";
$queryL = "SELECT lastname FROM tbData WHERE lastname=='$last";
$queryE = "SELECT emailaddress FROM tbData WHERE emailaddress=='$emailaddress'";
$resultF = mysqli_query($queryF);
$resultL = mysqli_query($queryL);
$resultE = mysqli_query($queryE);
if(mysqli_num_rows($con,$resultF) > 0 && mysqli_num_rows($con,$resultL) > 0 && mysqli_num_rows($con,$resultE) > 0)
{
header("Location: https://www.youtube.com"); //Just to check if it ignores the input.
}else{
mysqli_query($con,"INSERT INTO tbData VALUES (
'$first',
'$last',
'$emailaddress')");
header("Location: HOME.php");}
mysqli_close($con);
So I need it to check the first, and last name and the email address if there's a duplicate of it on the database, before it goes to the part of the code where it injects the data. Unfortunately, the code block where I check if there's a duplicate returns '0', so it proceeds on injecting the code in.
*Basically, the App should ignore the data inputted if it has the same first name, last name, and email address.
Any help would be highly appreciated!
You shouldn't be doing 3 separate queries, since the found values might be in different rows. If someone enters John Jones, you would match John Smith and Fred Jones, so it would think there's a duplicate when there isn't.
You should do a single query for all 3 columns:
SELECT 1 FROM tbData
WHERE firstname = '$first' AND lastname = '$last' AND emailaddress = '$emailaddress'
As mentioned in the comments, you should also learn how to use prepared queries, or at least use mysqli_real_escape_string() to sanitize user input.
You're also calling mysqli_num_rows() wrong. It should just be:
mysqli_num_rows($result)
without the $con argument.
Used the following logic with code below:
$resultFLE = mysqli_query($con,"SELECT * FROM tbData WHERE firstname='$first' AND lastname='$last' AND emailaddress='$emailaddress'");
$countFLE = mysqli_num_rows($resultFLE);
if($countFLE != null ){
header("Location: HOME.php");
}else{
mysqli_query($con,"INSERT INTO tbData VALUES (
...
header("Location: HOME.php");
}
I tried to simplified things, and think of it again; tried to locate affected row first by comparing it to the inputted data one by one, counted it just to see if it hits my counter, and then routed the page to wherever I want to based on the result.
Related
Column count doesn't match value count at row 1
Can someone help me pls? I can't figure it out ...
if (isset($_POST['prodotto_cat'])) {
$product_cat = mysqli_real_escape_string($conn,$_POST['prodotto_cat']);
$category_cat = mysqli_real_escape_string($conn, $_POST['categoria_cat']);
$details_cat = mysqli_real_escape_string($conn, $_POST['dettagli_cat']);
$sql = mysqli_query($conn, "SELECT id FROM prodotti_cat WHERE product_cat='$product_cat' LIMIT 1");
$productMatch_cat = mysqli_num_rows($sql); // count the output amount
if ($productMatch_cat > 0) {
echo 'Mi dispiace, hai inserito un duplicato "Nome prodotto" nel sistema, RITORNA';
exit();
}
$sql = mysqli_query($conn, "INSERT INTO prodotti_cat (product_cat, details_cat, category_cat)
VALUES('$product_cat','$details_cat','$category_cat',now())") or die (mysqli_error($conn));
$pid_cat = mysqli_insert_id($conn);
You are trying to insert 4 values into 3 columns. Observe:
INSERT INTO prodotti_cat (product_cat, details_cat, category_cat)
VALUES ('$product_cat', '$details_cat', '$category_cat', now())
What column should hold that now() value?
Either add the fourth column to the column list, or remove the 4th value from the value list.
While you're at it, you should also start looking into what SQL Injection is, because currently your code is potentially open to it. This is a good place to start, as is this. While you are trying to prevent the problem by sanitizing input, that alone is not enough. Instead of trying to prevent users from inputting malicious code, simply don't execute user input as code in the first place.
I'm trying to Implement the facebook registration. It works and i'm getting back all the data I need. Now I want to assign a username to the user like this:
$username = ''.$first_name.'.'.$lastname.'';
The problem is that I don't know if a user with the same name and last name will register to the website and i would like to check if the username is taken and add a sequence number to the basic $username (facebook does the same), like this:
name.lastname
name.lastname.1
name.lastname.2
etc
I tried with:
$temp_username = ''.$first_name.''.$last_name.'';
$check_username = mysql_query("SELECT username FROM users WHERE username = '$temp_username'");
$num_rows = mysql_num_rows($check_username);
if ($num_rows == 0){
$username = strtolower($temp_username);
} else {
$username = strtolower(''.$temp_username.'.'.$num_rows.'');
}
but of course it doesn't work because there is always just one user with that username.
EDIT*** this is how I fix it (thanks to zander):
$temp_username = ''.$first_name.''.$last_name.'';
$num_rows = mysql_num_rows(mysql_query("SELECT username FROM users WHERE username = '$temp_username' OR username LIKE '$temp_username%' "));
$username = strtolower(''.$temp_username.'.'.$num_rows.'');
$num_rows = mysql_num_rows(mysql_query("SELECT username FROM users WHERE username = '$temp_username' OR username LIKE '$temp_username.%' ")); will return the number of rows you actually expect. Then, use $username = strtolower(''.$temp_username.'.'.$num_rows.''); to get it done. No need of loops.
The following SELECT determines the user with the highest number if there are any
select max(reverse(SUBSTRING(reverse(username), 1, LOCATE('.', reverse(username))-1))) trail
from users
where username like 'John.Smith.%';
SQL Fiddle Demo
Add it to PHP like this
...
if ($num_rows == 0){
$username = strtolower($temp_username);
} else {
... query for the max number here
... concatenate the username with the max number
}
Ah and last but not least. Make sure your code is not vulnerable to SQL injection. Use bind parameters. Good start is this answer: Best way to defend against mysql injection and cross site scripting
There are many existing answers that correctly suggest using the LIKE operator in your WHERE clause. But there is one critical issue that none of the existing answers have addressed.
Two people could attempt to add the same username at the same (or nearly the same) time. Each would SELECT the count of existing usernames that are LIKE that name, and they each would generate the same number suffix, and you still get duplicates.
I am neither a mysql developer nor php developer, so I won't provide much in the way of specific syntax.
You will want to make sure your users table uses the InnoDB storage engine. Your code will need to:
START TRANSACTION
SELECT FOR UPDATE to make sure only one person can get the count of
a particular username at a given time
INSERT your new user
COMMIT your transaction.
See Select for update for more information.
Use this code instead:
$check_username = mysql_query("SELECT username FROM users WHERE username = '$temp_username' OR username LIKE '$temp_username.%' ");
example this will match:
johnsmith or joshnsmith.X where x will be 1 , 2 , 3 .......etc
DB Dump
CREATE TABLE Users (
`username` varchar(255) PRIMARY KEY,
`firstname` varchar(255),
`lastname` varchar(255)
);
INSERT INTO Users (`username`, `firstname`, `lastname`) VALUES (
'praveen.kumar', 'Praveen', 'Kumar'
),(
'praveen.kumar.1', 'Praveen', 'Kumar'
),(
'praveen.kumar.2', 'Praveen', 'Kumar'
);
Now to the SQL, we can do this way:
SELECT *
FROM `Users`
WHERE `username` LIKE "praveen.kumar%"
ORDER BY `username` DESC
Gives an output:
+-----------------+-----------+----------+
| USERNAME | FIRSTNAME | LASTNAME |
+-----------------+-----------+----------+
| praveen.kumar.2 | Praveen | Kumar |
| praveen.kumar.1 | Praveen | Kumar |
| praveen.kumar | Praveen | Kumar |
+-----------------+-----------+----------+
And you can get the latest one this way:
SELECT *
FROM `Users`
WHERE `username` LIKE "praveen.kumar%"
ORDER BY `username` DESC
LIMIT 1
The PHP Code:
<?php
# Outputs the largest number with that username.
$nextUser = substr($userNameFromDB, strrpos($userNameFromDB, "."));
$nextUser++;
?>
SQL Fiddle: http://sqlfiddle.com/#!2/ad149/1
Use the count() function and the like operator:
$check_username = mysql_query("
SELECT count(username)
FROM users
WHERE username like '$temp_username%'
");
It will return the number of existent names. No need to call mysql_num_rows.
You should use the count() function
$query = mysql_query("
SELECT count(user_name) cnt
FROM users
WHERE username = '$just_registered_username'
");
and then fetch the result using
$row = sql_fetchrow($query);
And then get the count of users as
$next_index = $row->cnt;
Then append it to the new username
$new_username = "{$just_registered_username}.{$next_index}";
Don't forget to add comments to your final code.
Also try and use PDO for database access.
If you want to find a user name that does not exist, you have to try combinations, until you find a non existing username.
Therefore, loop until you find a non existing name:
$temp_username = $first_name . $last_name;
$i=1;
$found = false;
while(!$found) {
$check_username = mysql_query(
"SELECT username FROM users WHERE username = '$temp_username'");
$found = mysql_num_rows($check_username);
if ($found){
$username = strtolower($temp_username);
}
else{
$temp_username = $first_name . $last_name . '.' . $i;
$i++
}
}
I need to verify that a user registering for a website enters a unique 16 digit number that no one else prior to him/her has entered.
The relevant database information is that the 16 digit numbers are stored in a column called card1, the name of the entire table is users, and the user-entered number is stored in $card1.
Here is what I have so far...
$query2 = "SELECT card1 FROM users WHERE card1='$card1' LIMIT 1";
$result2 = smart_mysql_query($query2);
if (mysql_num_rows($result2) != 0)
{
header ("Location: register.php?msg=exists");
exit();
}
The idea is that it will find any examples already in the database and if it finds a duplicate, it will display and error message.
The problem is that it is continuing to allow users to register(submit their registration form to the db) even when there is a duplicate. Immediately after this block of code is the insertion call to the db with all of the user information collected from the form.
NOTE: I'm not very familiar with handling PHP error messages and what I've used is just an example that I found in another instance in the example code.
Make the if statement like this:
$query2 = "SELECT * FROM users WHERE card1='$card1'";
$result2 = mysql_query($query2);
if ($result2 !== false)
{
header ("Location: register.php?msg=exists");
exit();
}
Should fix the problem:)
The correct way to do this is to add a unique index on the field that holds the number that the use has entered (card1).
You will then try and INSERT the new row without trying to SELECT it first, and if this operation fails you redirect the user to the msg=exists page. This lets the database handle the duplicate detection and removes the problem inherent in your method - if two users submit the same number at the same time, there is no guarantee that SELECT -> INSERT will detect it. A unique index will detect and prevent this.
This will also have the advantage of reducing database traffic, since only one query is executed in order to get this happen.
First of all, create unique index in DB on this column.
This is best practice:
ALTER TABLE `users`
ADD UNIQUE INDEX `card1` (`card1`);
I should modify your SQL as follows:
$query2 = "SELECT COUNT(1) FROM users WHERE card1='$card1'";
$res = mysql_query($query2);
$data = mysql_fetch_array($res);
if ($data == 1)
{
header ("Location: register.php?msg=exists");
exit();
}
It will check for existence of row within table and return 0 or 1.
If exists (1) then it will redirect you.
try this one
$query2 = "SELECT card1 FROM users WHERE card1='".$card1."' LIMIT 1";
$result2 = mysql_query($query2);
if (mysql_num_rows($result2) > 0)
{
header ("Location: register.php?msg=exists");
exit();
}
I am having trouble with a function that checks if a set of user entered info (username and password) exists within either of the two possible tables where this information is stored.
The first table is the users table. It contains the first set of specific user information.
The last table is the listings table. It contains the second set of specific user information.
I have basically modified my original code to include the new listings table, and hence the trouble coming from within that task. The old code basically counted the number of results in the users table, if the result was greater than 0, then the function returned true, else false.
Now I have been stuck on the best way to go about adding another table to the query, and function. So I have been playing around with a union.
This was the original query:
SELECT COUNT(*) FROM users
WHERE id='$accNum' AND password='$password'
This returned a count of either 0 or 1 based on the info stored in the users table.
This is how I have reworked the query to include a count of the additional listings table:
SELECT count . *
FROM (
SELECT COUNT( * )
FROM users
WHERE id = '$accNum'
AND PASSWORD = '$password'
UNION (
SELECT COUNT( * )
FROM listings
WHERE id = '$accNum'
AND PASSWORD = '$password'
)
)count
This returned a result set of two rows, the first relating to the users table, and the second relating to the listings table. Then a column called COUNT (*) that contained the result count. This is the result set that I see within php myadmin.
Now this is the function:
function databaseContainsUser($accNum, $password)
{
include $_SERVER['DOCUMENT_ROOT'] . '/../../includes/db.inc.php';
$accNum = mysqli_real_escape_string($link, $accNum);
$password = mysqli_real_escape_string($link, $password);
$sql = "SELECT count . *
FROM (
SELECT COUNT( * )
FROM users
WHERE id = '$accNum'
AND PASSWORD = '$password'
UNION (
SELECT COUNT( * )
FROM listings
WHERE id = '$accNum'
AND PASSWORD = '$password'
)
)count
";
$result = mysqli_query($link, $sql);
if (!$result)
{
$error = 'Error searching for user.';
include 'error.html.php';
exit();
}
$row = mysqli_fetch_array($result);
if ($row[0] > 0)
{
return TRUE;
}
else
{
return FALSE;
}
}
The problem that I have, is trying to work out how exactly to check the results to ascertain if the given log in credentials are valid.
I tried this: if (($row[0] > 0) || ($row[0] > 0)) But a var dump on $row showed that only the first row (count of users table) was being added to the array.
So I decided that this was complicated, and a long way to the final result.
So I tried selecting only the id column of the result as in:
...
`COUNT( * )` to `id`
...
$data = mysql_query($sql);
$num_sql = mysql_num_rows($data);
if ($num_sql > 0)
...
But this did not work out for me either.
But in either instance, my hours of trial and error have provided me with no success... So I've decided to seek help from the knowledgeable members of Stack Overflow!
So my question is this, what would be a logical way of going about this task? I am looking for any suggestions, or positive input what so ever here.
As I am fairly new to dabbling with PHP and mysql, if you would like to provide some code to explain your suggestions or input on the matter, it would more than likely help me to better understand the answer.
If you are checking existence only try doing this that way:
select case when
exists (SELECT 1 FROM users WHERE id = '$accNum' AND PASSWORD = '$password') or
exists (SELECT 1 FROM listings WHERE id = '$accNum' AND PASSWORD = '$password')
then 1 else 0
end as itDoesExist
It returns always one row with one column with 1 when record exists in at last one table (else 0).
Do not use count to check whether some specific record/-s exist/-s in table, it's usually slower than simple exists.
Looks like you're going to get two rows in the result no matter what. Try this:
$sql = "SELECT id,password
FROM users
WHERE id = '$accNum' AND password = '$password'
UNION
SELECT id,password
FROM listings
WHERE id = '$accNum' AND password = '$password'
";
Now you can just check mysql_num_rows() to see if there's a match in either of the tables.
There are a couple of ways to go about this; if we are to stick with the approach you started with; you can simplify the query to:
$sql = "SELECT COUNT(1) FROM users
WHERE id = '$accNum'
AND PASSWORD = '$password'
UNION (SELECT COUNT(1) FROM listings
WHERE id = '$accNum'
AND PASSWORD = '$password')";
The reason you are only seeing one result, is because thats the way mysql_fetch_array() works, try doing this to get all results:
while ($row = mysql_fetch_array($result)) {
$data[] = $row;
}
var_dump($data);
Now you should have both values in there to validate with your conditional statements.
(Beginners question here...be gentle)
My php script is a response to a form. Assuming I have already connected to a database and extracted the post variables (just two - emailAddress and username), like so
mysql_connect('localhost', 'dbusername', 'dbpassword');
mysql_select_db('database');
extract($_REQUEST);
..and knowing that within the 'users' table, there are 'emailAddress', 'username' and 'address' fields. (The email addresses will all be unique..)
How would I search thru the table to get at the specific 'address' after receiving the emailAddress and username (and output something else if there is no name and address which matches)?
seems absurdly difficult to get an answer. this must be a very very very very very very difficult question.
Extra-special thanks to users who told me the problem was very easy, and yet couldn't come up with an answer. I salute your indefatigability, your magnificent courage, and your willingness to help.
A possible answer to my question is:
$result = mysql_query("SELECT * FROM users WHERE emailAddress='".$emailAddress."' AND username='".$username."'");
$row = mysql_fetch_array($result);
if ($row['username'] == "") {
// no results
} else if ($row['emailAddress'] == $emailAddress AND $row['username'] == $username) {
// found result
echo "The address is ".$row['address'];
} else {
// i guess something else happened
}
Be sure to tell me how this is wrong, and the real answer is easy, and yet not come up with an answer.
to get individual elements, you do "select column_name from table where criteria".
in your example it would be
select address from users where emailaddress = 'email#domain.com' and name = 'John Doe'
the column_name section can be multiple items comma seperated, so, for example, if you wanted name and address, you would do
select name, address from users where emailaddress = 'email#domain.com' and name = 'John Doe'
you have to take this sql request into a variable then execute it after that u can verify if the array is empty or not.. if it is it means that there are no combination with both that name and that email corresponding into your database.. and it's done!`$req= "Select name,address from users where emailaddress=$email and name=$name";
$result = mysql_query($req);
if !isset($result){
/// some stuffs there when everything okkay
}
else{
/// some stuffs if there is no record corresponding
}`
in vrac.. some sample exemple in the idea.. note that the sql query give the result into an array so u have to manipulate an array or hash
You can use a SELECT statement. Note this code is not safe to SQL injection.
SELECT * FROM Users WHERE emailAddress = 'someemail#gmail.com'