please check validation - php

i am inserting day value to database,i want validation like if the day already exist it should say day already exist else it should innsert..please can anyone check the following code... thanks in advance
$dexist=$_POST['ext'];
$res=mysql_query("select Day from mess where Day='".$dexist."' ");
while($row=mysql_fetch_array($res))
{
$dy=$row['Day'];
}
if($dy==$dexist)
{
echo "<script language=\"javascript\">";
echo "window.alert ('File already exist');";
echo "//--></script>";
}
else
{
mysql_query("insert into mess (Date,Day,Breakfast,StartTimeb,EndTimeb,Lunch,StartTimel,EndTimel,Dinner,StartTimed,EndTimed) values('".$date."','".$day."','".$bre."','".$bres."','".$bree."','".$lun."','".$luns."','".$lune."','".$dinn."','".$dins."','".$dine."')");
}

Your script screams "SQL INJECTION!" Please pwn my site!
Also: your code is vulnerable to synchronization issues. For example, a file might be created AFTER you ran a select statement, but BEFORE you ran the INSERT statement. This will cause weird failures. That's why you should do the "select and insert" as a single stored proc (read up on atomic operations - more specifically, this is an instance of a "compare and swap").

Firstly never, ever pass unchecked POST/GET data into a MySQL query, it's a massive security hole. Use mysql_real_escape_string instead:
$res=mysql_query("select Day from mess where Day='" . mysql_real_escape_string($dexist) . "' ");
And similar for the latter call.
Secondly, it's not clear what you're asking... please tell us if the code is not working somewhere, and any errors you're getting. I think you have a problem with this line:
if(file_exists($dy==$dexist))
That is passing a boolean value ($dy==$dexist will evaluate to true or false) into the file_exists function. You need to pass the filename in.

Don't do that in PHP, it's difficult (impossible?) to do safely. Do it in MySQL by adding a unique index on the Day column:
ALTER TABLE mess ADD UNIQUE (Day);
You can then catch failures of that kind by looking for ER_DUP_UNIQUE from MySQL.
Use PHP's mysql_errno to check for error 1169 to catch unique constraint failure.
$query_result = mysql_query("insert into mess (Date,Day,Breakfast,StartTimeb,EndTimeb,Lunch,StartTimel,EndTimel,Dinner,StartTimed,EndTimed) values('".$date."','".$day."','".$bre."','".$bres."','".$bree."','".$lun."','".$luns."','".$lune."','".$dinn."','".$dins."','".$dine."')");
// 1169 means a unique constraint failure
if (!$query_result && mysql_errno() == 1169) {
echo "Oh noes, you tried to insert a value twice!";
}

This is a repost of your question.
searching for the original..
found it..
Want to check day already exist

Related

Insert multiple checkbox answers into database

I have a checkbox list and I want to insert each item checked into the database. Since it is a checkbox, I only have one value to pass to the database, but I am also passing a variable (primary key) grabbed from a previous database insertion.
My problem is that I can't get it to post to the database. I have tried multiple ways to do this through posts here and nothing seems to work. I am at a loss. I am also fairly new to PHP and mysqli, so I am sure there are better ways to do what I am trying to do, so please help me out.
The table consists of three columns (school_id, graduate_id, schoolName). The school_id is the AI primary key and graduate_id will be populated with the variable $graduateID grabbed from the previous query.
Here is what I have:
if (isset($_POST['school'])) {
$school=$_POST['school'];
$schoolQuery="";
foreach($school as $value) {
if(!$schoolQuery) {
$schoolQuery="INSERT INTO schoolReunion (graduate_id, schoolName) VALUES ($graduateID, '$value')";
} else {
$schoolQuery .= ", ($graduateID, '$value')";
mysqli_store_result($schoolQuery);
}
}
$schoolQuery .=";";
if (mysqli_multi_query ($schoolQuery)) {
echo "Files have been updated successfully.";
} else {
echo "Error: " . $schoolQuery . "<br/>" . mysqli_error($dbc);
}
}
When the error code prints out, it looks fine, but it just won't post anything and gives me no errors. Can you help me?
#Maximus & #Eko Junaidi Salam, while you may be right, I don't see any evidence that there are issues with the front-end/form.
#jeroen, you are totally correct.
CarR is dealing with a single concatenated query, so mysqli_query is suitable.
I recommend wrapping the user-supplied variable in mysqli_real_escape_string() to cover the query vulnerability.
mysqli_store_result() is to be used on queries that return a result set; mysqli_affected_rows() is the function that yields a measure of success with INSERT/UPDATE/DELETE type queries.
Lastly, you are right to correct MrTechie. I don't think he realized the query concatenation.
Assuming the form is delivering the necessary values, I'll suggest a new query build section:
$schoolQuery="";
foreach($school as $value){
if(!$schoolQuery) {
$schoolQuery="INSERT INTO schoolReunion (graduate_id,schoolName) VALUES ";
}else{
$schoolQuery.=",";
}
$schoolQuery.="('$graduateID','".mysqli_real_escape_string($dbc,$value)."')";
}
$schoolQuery.=";";
$graduateID IS NOT escaped because I am assuming it comes from a safe place; $value IS escaped because it comes from user input.
Now to deliver the built query. Your code has syntax and logic errors, so try this:
if($schoolResult=mysqli_query($dbc,$schoolQuery)){
$total_rows=mysqli_affected_rows($dbc);
echo $total_rows," file",($total_rows!=1?"s have":" has")," been added.";
// if($total_rows<1){echo "Query Logic Error, # $schoolQuery";}
}else{
// echo "Query Syntax Error # $schoolQuery<br>".mysqli_error($dbc);
}
Uncomment the error lines while you are testing, then re-comment or delete for production.
This should sufficiently fix all the issues that are apparent in your snippet of code. Beyond that are the assumed issues...
Since you mention that you are employing a previous query to declare $graduateID, I will assume you have acquired the value via a SELECT query. Be sure to check that you have used
mysqli_free_result($graduateResult); // I assumed this variable name
to avoid any conflicts with subsequent queries. This is sometimes overlooked.
mysqli_multi_query() is best used when you are dealing with queries that are dependent on a prerequisite query. It seems your $schoolQuery is dependent on the success of what I will call "$graduateQuery". If you wish, you could use mysqli_multi_query() to run $graduateQuery then $schoolQuery. To help you with this implementation, I would need to see more of your code. If you wish to go down that road, it might be best to message me directly or start a new post (after you've had a try at it yourself.) Here is half of your job done: Strict Standards: mysqli_next_result() error with mysqli_multi_query

PHP PDO workflow

I've been using PDO for quite some while now, but I'm wondering whether I'm checking for errors too much or not enough. This is how my stuff generally looks:
$STH = $DBH->prepare("SELECT something FROM table WHERE field=:field AND field2=:field2");
$STH->bindParam(":field",$field);
$STH->bindParam(":field2",$field2);
if($STH->execute()){
if($STH->rowCount() == 1){
echo "This is what is returned";
}else{
echo "Something went wrong.";
}
}else{
echo "Something went wrong.";
}
Of course the $STH->rowCount()-check depends on what I'm expecting. For example when a user logs in, only one result can be found with that username. Now of course this is already checked in the database, yet I double check it here again. Is this necesary?
Also the if(STH->execute())-check I'm not sure if it's really necessary. What are the best practices?
According to the documentation 'http://php.net/pdostatement.rowcount' it's a bad practice to use rowcount with SELECT statements because many databases can not return the number of rows affected by a SELECT statement. For checking user it's better to use:
Select count(*) ..... and PDOStatement:execute + PDOStatement:fetchColumn.
Also keep in mind (STH->execute() doesn't check anything it only says that your query is executed without errors.

Update query running but not updating table php

Here's the code i am using withing a for loop which run 10 times:
$query = "UPDATE fblikes SET likes = '$var[$i]' WHERE link = '$web[$i]'";
if(mysql_query($query))
{
echo $query;
}
else
{
echo mysql_error();
}
The code runs, I do get ok! printed 10 times but nothing happens in the table. I also checked the 2 arrays i.e. $var and $web, they contain the correct values.
The query looks okay to me. Here's what i got (one of the 10 outputs) : UPDATE fblikes SET likes = '5' WHERE link = 'xxxxxxx.com/xxxx/iet.php';
I don't know what the problem exactly is, and to figure out you should print the value of $query, and show us what you get. More, please tell us the value of mysql_affected_rows() after the call to mysql_query().
However, your code implements some wrong patterns.
First of all, you are not escaping $var[$i] and $web[$i] with two potential effects:
You can produce wrong queries
You don't sanitize the input to the database, thus exposing your application to security issues
Moreover, you perform several similar queries that differ only on the inputs provided.
The solution, for both issues, is the use of prepared statements that will give you more control, security and performance. Consider abandoning mysql_* functions and switching to mysqli_* or PDO, and read about prepared statements.

Pause foreach and continue

I'm trying to loop data from a api and then post these values to a MySQL db.
something like this:
$values = json_decode(file_get_contents("my-json-file"));
$SQL = new mysqli(SQL_HOST, SQL_USER, SQL_PASS, DB_NAME);
$SQL->autocommit(FALSE);
foreach($values As $item)
{
$query = "INSERT INTO my_table VALUES ('".$item->value1."', '".$item->value2.";)";
$SQL->query($query);
if(!$SQL->commit())
{
echo "ERROR ON INSERT: [" . $query . "]<hr/>";
}
}
$SQL->close();
Since the loop is too fast, the SQL can't catch up. (Yea!)
I would then need something like this:
foreach($values As $item)
{
/**** STOP/PAUSE LOOP ****/
$query = "INSERT INTO my_table VALUES ('".$item->value1."', '".$item->value2.";");
$SQL->query($query);
if($SQL->commit())
{
/**** START THE LOOP AGAIN ****/
}
else
{
echo "ERROR ON INSERT: [" . $query . "]<hr/>";
}
}
Or how should I do this the right way?
EDIT: It inserts random posts every time.
EDIT 2: This is just example code. It does escape and all that, and yes the semi colon is wrong here but since so many commented on it i will not change it. This was not the problem in the real case.
I tried to run it on another server and there it worked. The problem was fixed by restarting MAMP.
Firstly, your idea that the loop runs too fast for MySQL to keep up is completely totally wrong. The $SQL->query() call will wait for the MySQL to return a response before proceeding, so the loop won't run any faster than MySQL is responding.
Now onto the actual problem.... your query:
$query = "INSERT INTO my_table VALUES ('".$item->value1."', '".$item->value2.";)";
There's a semi-colon in there at the end, after value2 which is invalid. I guess you intended to type a quote mark there? The semi-colon will be causing all your queries to fail and throw errors.
This may be the cause of your problem but you haven't got any error checking in there, so you won't know. Add some error checking to your code after calling the query; even if the query is right, it's still possible to get errors, and your code should check for them. See the examples on this manual page: http://www.php.net/manual/en/mysqli-stmt.error.php
Finally, since you're using the mysqli API, it's worth mentioning that your code would be a lot better and probably more secure if you used prepared statements. See the examples in PHP manual here: http://www.php.net/manual/en/mysqli-stmt.bind-param.php
[EDIT]
Another possible reason your query is failing is that you're not escaping the input values. If any of the input values contains a quote character (or any other character that is illegal in SQL) then the query will fail. In addition, this problem makes your code vulnerable to a SQL injection hacking attack.
You need to escape your input using $SQL->real_escape_string() OR by changing your query to use prepared statements (as recommended above).
Your query is inside the loop, which means that the loop will wait until your query finished executing before it continue, php code is processed in order...
Has #phpalix said, PHP goes in order, and waits for the previous action to finish.
I think you SQL is wrong. Try replacing your INSERT with this:
$query = "INSERT INTO my_table VALUES ('".$item->value1."', '".$item->value2."');";
And don't forget to run at least mysql_real_escape_string for each variable, for security measures.
As many of the answers and comments say, it does not continue until the SQL is done. The problem was in my local apache/mysql server. It was fixed by restarting it. Yes, stupid post.

Can I detect and handle MySQL Warnings with PHP?

I'm dealing with a MySQL table that defines the JobName column as UNIQUE. If somebody tries to save a new Job to the database using a JobName that is already in the database, MySQL throws a warning.
I would like to be able to detect this warning, just like an error, in my PHP script and deal with it appropriately. Ideally I would like to know what kind of warning MySQL has thrown so that I can branch the code to handle it.
Is this possible? If not, is it because MySQL doesn't have this ability, PHP doesn't have this ability, or both?
For warnings to be "flagged" to PHP natively would require changes to the mysql/mysqli driver, which is obviously beyond the scope of this question. Instead you're going to have to basically check every query you make on the database for warnings:
$warningCountResult = mysql_query("SELECT ##warning_count");
if ($warningCountResult) {
$warningCount = mysql_fetch_row($warningCountResult );
if ($warningCount[0] > 0) {
//Have warnings
$warningDetailResult = mysql_query("SHOW WARNINGS");
if ($warningDetailResult ) {
while ($warning = mysql_fetch_assoc($warningDetailResult) {
//Process it
}
}
}//Else no warnings
}
Obviously this is going to be hideously expensive to apply en-mass, so you might need to carefully think about when and how warnings may arise (which may lead you to refactor to eliminate them).
For reference, MySQL SHOW WARNINGS
Of course, you could dispense with the initial query for the SELECT ##warning_count, which would save you a query per execution, but I included it for pedantic completeness.
First, you should turn warnings off so that your visitors don't see your MySQL errors. Second, when you call mysql_query(), you should check to see if it returned false. If it did, call mysql_errno() to find out what went wrong. Match the number returned to the error codes on this page.
It looks like this is the error number you're looking for:
Error: 1169 SQLSTATE: 23000 (ER_DUP_UNIQUE)
Message: Can't write, because of unique constraint, to table '%s'
ini_set('mysql.trace_mode', 1)
may be what you are looking for.
The PHP errors can then be handled with a custom PHP error handler, but you can also just turn off displaying php errors as they are usually logged into a log file (depends on your php configuration).
depending on what (if any) framework you're using, I suggest you do a query to check for the jobname yourself and create the proper information to user in with the rest of the validations for the form.
Depending on the number of jobnames, you could send the names to the view that contains the form and use javascript to tell use which is taken.
If this doesnt make sense to you, then to sum my view it's this: dont design your program and / or user to try to do illegal things and catch the errors when they do and handle it then. It is much better, imho, to design your system to not create errors. Keep the errors to actual bugs :)
Updated to remove the stuff about errno functions which I now realize don't apply in your situation...
One thing in MySQL to be wary of for UPDATE statements: mysqli_affected_rows() will return zero even if the WHERE clause matched rows, but the SET clause didn't actually change the data values. I only mention this because that behaviour caused a bug in a system I once looked at--the programmer used that return value to check for errors after an update, assuming a zero meant that some error had occurred. It just meant that the user didn't change any existing values before clicking the update button.
So I guess using mysqli_affected_rows() can't be relied upon to find such warnings either, unless you have something like an update_time column in your table that will always be assigned a new timestamp value when updated. That sort of workaround seems kinda kludgey though.
You can detect Unique key violations using mysqli statement error no. The mysqli statement returns error 1062 , that is ER_DUP_ENTRY. You can look for error 1062 and print a suitable error message. If you want to print your column (jobName) also as part of your error message then you should parse the statement error string.
if($stmt = $mysqli->prepare($sql)){
$stmt->bind_param("sss",
$name,
$identKey,
$domain);
$stmt->execute();
if($mysqli->affected_rows != 1) {
//This will return errorno 1062
trigger_error('mysql error >> '.$stmt->errno .'::' .$stmt->error, E_USER_ERROR);
exit(1);
}
$stmt->close();
} else {
trigger_error('mysql error >> '. $mysqli->errno.'::'.$mysqli->error,E_USER_ERROR);
}
It is possible to get the warnings, and in a more efficient way with mysqli than with mysql.
Here is the code suggested on the manual page on php.net for the property mysqli->warning_count:
$mysqli->query($query);
if ($mysqli->warning_count) {
if ($result = $mysqli->query("SHOW WARNINGS")) {
$row = $result->fetch_row();
printf("%s (%d): %s\n", $row[0], $row[1], $row[2]);
$result->close();
}
}
Note on suppressing warnings: Generally, it is not a good idea to prevent warnings from being displayed since you might be missing something important. If you absolutely must hide warnings for some reason, you can do it on an individual basis by placing an # sign in front of the statement. That way you don't have to turn off all warning reporting and can limit it to a specific instance.
Example:
// this suppresses warnings that might result if there is no field titled "field" in the result
$field_value = #mysql_result($result, 0, "field");

Categories