PHP Form data validation issue - php

I am making a basic content management system and I have got stuck with the validation of data being entered into a form.
For example, one form is to edit the name of a subject (in the navigation menu). The form contains a few different pieces of data but the main focus is the "menu_name" field (name of subject).
On form submission data in "menu_name" should be checked to ensure it is not empty and if it is then give an error. What is happening is that the form validation doesn't seem to be working as when I enter nothing the script continues to edit the subject name, in this case making it blank.
This is the script that is executed on form submission:
if (isset($_POST['submit']))
{
// Process the form
// Validations
$required_fields = array("menu_name", "position", "visible");
validate_presences($required_fields);
$fields_with_max_lengths = array("menu_name" => 30);
validate_max_lengths($fields_with_max_lengths);
// If errors occured, redirect
if(empty($errors))
{
// Perform update
// Assign POST data to variables
$id = $current_subject["id"];
$menu_name = mysql_prep($_POST["menu_name"]);
$position = (int) $_POST["position"];
$visible = (int) $_POST["visible"];
// 2. Perform database query
$query = "UPDATE subjects SET ";
$query .= "menu_name = '{$menu_name}', ";
$query .= "position = '{$position}', ";
$query .= "visible = '{$visible}' ";
$query .= "WHERE id = {$id} ";
$query .= "LIMIT 1";
$result = mysqli_query($connection, $query);
if ($result && mysqli_affected_rows($connection) >= 0)
{
// Success
$_SESSION["message"] = "Subject updated.";
redirect_to("manage_content.php");
}
else
{
// Failure
$message = "Subject update failed.";
}
}
}
The data is then checked by two custom validation functions as you can see, the second one is not my concern but the first function validate_presences(), here is the function:
function validate_presences($requried_fields)
{
GLOBAL $errors;
foreach($required_fields as $field)
{
$value = trim($_POST[$field]);
if (!has_presence($value))
{
$errors[$field] = fieldname_as_text($field) . " can't be blank";
}
}
}
You can see there that it references the has_presence() function, which is:
function has_presence($value)
{
return isset($value) && $value !== "";
}
If anyone has any ideas on what is wrong, any help is appreciated!
Just ask if you need some more information.
Thanks in advance!

Why don't you just return the error array instead of making it global? I think it will resolve your problem instantly ;)
function validate_presences($requried_fields)
{
$errors = array();
foreach($required_fields as $field)
{
$value = trim($_POST[$field]);
if (!has_presence($value))
{
$errors[$field] = fieldname_as_text($field) . " can't be blank";
}
}
return $errors;
}
Now set $errors = validate_presences($required_fields); and your ready to go!

It's not recommended to use variables in a global way like this. Rather pass the errors variable by reference to the validation functions.
$errors = array();
function validate_presences($requried_fields, &$errors)
{
foreach($required_fields as $field)
{
$value = trim($_POST[$field]);
if (!has_presence($value))
{
$errors[$field] = fieldname_as_text($field) . " can't be blank";
}
}
}
$required_fields = array("menu_name", "position", "visible");
validate_presences($required_fields, $errors);
$fields_with_max_lengths = array("menu_name" => 30);
validate_max_lengths($fields_with_max_lengths, $errors);
// If errors occured, redirect
if(empty($errors))
{

Related

Why does this "if" statement get triggered?

I've been working for the past 5 hours on why does this if get triggered...
Let me show you the code and explain you :
<?php
require_once "ConnectDB.php";
$link2 = $link;
$key = $posthwid = "";
$err = "";
if($_SERVER["REQUEST_METHOD"] == "POST"){
if(empty($_POST["key"])){
$err = "Thanks for the ip (" .$_SERVER['REMOTE_ADDR']. "), have a good day! (1)";
}
else{
$key = trim($_POST["key"]);
}
$hwid = $_POST["hwid"];
if(empty($err)){
$sql = "SELECT hwid, idkey, length, created_at FROM money WHERE idkey = '" .$key. "'";
$row = mysqli_query($link, $sql);
if(mysqli_num_rows($row) < 2){
while($result = mysqli_fetch_assoc($row)) {
if($result["idkey"] == $key)
{
$err = "key";
if($result["hwid"] == "")
{
$err = "nohwid";
$sql2 = "UPDATE IceCold SET hwid = '" .$hwid. "' WHERE idkey = '" .$key. "'";
if(mysqli_query($link2, $sql2)){
$hwid = $result["hwid"];
mysqli_close($link2);
echo "debug";
}
else {
$err = "Oops! Something went wrong. Contact the support.";
}
}
if ($hwid !== $result["hwid"]) {
$err = "Contact the support";
}
elseif($_SESSION["admin"] == true) {
//Do special stuff
}
else {
///do other checks
if($created_at > $date){
$err = $hwid;
} else {
$err = "The key date is too old, buy a new one.";
}
}
}
else{
$err = "The key you entered was not valid.";
}
} mysqli_close($link);
} else {
$err = "multiple entry, contact support";
}
}
} else {
$err = "Thanks for the ip (" .$_SERVER['REMOTE_ADDR']. "), have a good day! (3)";
}
echo $err;
?>
So basically, I have this Connect DB file with a mysqli_connect called $link and I'm designing a liscence API for my program. My program will send a request with the "idkey" and "hwid" and is waiting for the hwid to come back. I have an entry in my sql databse with only a key registered and I've trying to make my program wotk by generating POST request with the id and a random hwid but I've found no success. If variables are weirdly moved around, It's because of the debugging.
Right now, with my current setup, I get the Contact the support response which I don't understand why?!? The request and the key are correct if I'm able to get this awnser.
It's probably a stupid mistake but I jsut can't figure it out...
Thanks in advance for your help
Edit: the if statement I'm referring to is this:
if($hwid !== $result["hwid"])
There was a typo in the code that I fixed but it wasn't the issue,
as for the elseif, that would destroy the order of execution of the code and destroy the logic behind it(If that made sense).
Weirdly, after some tests, I found out that the second SQL request I send doesn't want to be executed ($sql2) and there is no error in httpd logs... Can you execute two requests? I tried to create $link2 but it doesn't change anything
EDIT : Found solution
if($result["hwid"] == "")
{
$sql2 = "UPDATE money SET hwid = '" .$_POST["hwid"]. "' WHERE idkey = '" .$key. "'";
if(mysqli_query($link2, $sql2)) {
$newhwid = $_POST["hwid"];
mysqli_close($link2);
}
else {
$err = "Oops! Something went wrong. Contact the support.";
}
}
elseif ($_POST["hwid"] != $result["hwid"]) {
$err = "Contact the support";
}
if($_POST["hwid"] == $newhwid || $_POST["hwid"] == $result["hwid"] ) {
/// do other checks
}
The condition before that one, if($row['hwid'] = ""), is an assignment. This code is changing the value of $row['hwid'] to an empty string, causing the condition after it to be true. I assume you meant to write == to test if $row['hwid'] is empty; otherwise it doesn't make sense to write this as an if statement.
By the way, it's not clear whether this if statement shouldn't be an else if. The rest of the branches here are else if (or elseif, which is the same in PHP), so you should consider whether you have missed out an else on this one too.

PHP validating multiple required input fields

I am validating some input fields before sending the email. I am using for each to loop through the array faster and check that every single input is not empty and return it as a response in jquery to show the errors. The problem is that email and message inputs are not being validated. Emails are being sent even if the inputs are empty.
the array elements come from the input name attributes from the html.
function e_($data) {
$data = trim($data);
$data = stripslashes($data);
$data = htmlspecialchars($data);
return $data;
}
#required fields
$required = array('name', 'email','lname','message','country' , 'city' ,'adcategory','plan' ,'company');
$success = false;
#non required fields
$website = e_($_POST['website']);
$addr = e_($_POST['address']);
foreach($required as $field) {
if (empty($_POST[$field]))
{
$success = false;
}
else if(!empty($_POST[$field])){
$success = true;
$name = e_($_POST['fname']);
$email = e_($_POST['email']); #this has issue
$lname = e_($_POST['lname']);
$msg = e_($_POST['message']); #this has issue
$country = e_($_POST['country']);
$city = e_($_POST['city']);
$adCategory = e_($_POST['adcategory']);
$plan = e_($_POST['plan']);
$companyName = e_($_POST['company']);
}
}
if($success)
echo "success";
else if (!$success)
echo json_encode(['errors'=>true]); #this will be manipulated in jquery
The problem is that you set $success = true; whenever you find a required field, and this undoes the $success = false; for a previous field. You also process all the fields in the else if, even though that just means that one of the required fields was found.
$success = true;
foreach ($required as $field) {
if (empty($_POST[$field])) {
$success = false;
$missing_field = $field;
break;
}
}
if (!$success) {
echo json_encode(['errors'=>true, 'missing' => $missing_field]);
exit();
}
$name = e_($_POST['fname']);
$email = e_($_POST['email']); #this has issue
$lname = e_($_POST['lname']);
$msg = e_($_POST['message']); #this has issue
$country = e_($_POST['country']);
$city = e_($_POST['city']);
$adCategory = e_($_POST['adcategory']);
$plan = e_($_POST['plan']);
$companyName = e_($_POST['company']);
echo "Success";
Your foreach loop is wrong. You have your if statement that checks if it's not empty inside your for loop that checks if it's empty. You need to check to see if all the values are empty first then run that if statement.
$success = true;
foreach($required as $field) {
if (empty($_POST[$field]))
{
$success = false;
break;
}
}
if($success)
{
// set your variables
} else {
// don't set your variables
}

Can't figure out how to format this logic statement in PHP

I have some PHP I'm using to validate a form, and once the validation is complete the data from the form is sent into a database. My problem isn't actually a code problem, it's just I can't figure out how to write the if-else statement blocks.
Basically I have all these if statements that check if one of the form fields is empty or doesn't meed the criteria, and then a corresponding else statement which simply holds the data they've entered, so when the form reloads they don't have to enter it in again. At the moment I have an else statement at the end which posts all the data into my database when all the fields are validated - the problem is that I have one too many else statements and it gives me errors for this.
So I figure I have to wrap the whole block of code in one if-else statement, that would basically say if there are no errrors, do the else which sends the data to the database.
Basically I have the else done, I just need help to think of what condition to put for the if
Here's my code
//Define the database connection
$conn = mysqli_connect("danu.nuigalway.ie","myb1608re","fa3xul", "mydb1608") or die (mysql_error());
## Initialise varialbes to null ##
$nameError ="";
$emailError ="";
$categoryError ="";
$messageError ="";
$validName ="";
$validEmail ="";
$validMessage ="";
## On submitting form below function will execute ##
if(isset($_POST['submit']))
{
//assign details to be posted to variables
$name = $_POST['name'];
$email = $_POST['email'];
$message = $_POST['message'];
$category = $_POST['category'];
//if name is less than 10 characters
if (empty($_POST["name"]) || strlen($name)<10)
{
$nameError ="* Name is too short";
}
else
{
$validName = $_POST["name"];
}
//if email is too short or is not the right format
if (empty($_POST["email"]) || !preg_match("/([\w\-]+\#[\w\-]+\.[\w\-]+)/", $email) || strlen($email)<10 )
{
$emailError = "* You did not enter a valid email";
$validEmail = $_POST["email"];
}
else
{
$validEmail = $_POST["email"];
}
//if a category is not chosen
if (empty($_POST["category"])) {
$categoryError = "* Please select a category";
}
//if the message is left blank
if (empty($_POST["message"]) || strlen($message)<25 ) {
$messageError = "* Your message is too short";
}
else {
$validMessage = $_POST["message"];
}
//If there are no errors, email details to admin
else {
// variables to send email
$to = "e.reilly4#nuigalway.ie";
$subject = "Contact Form";
$body = "\r\n
Category: $_POST[category] \r\n
Message: $_POST[message] \r\n
Name: $_POST[name] \r\n
Email: $_POST[email]";
// Email Function
mail($to,$subject,$body);
//Insert the data into the database
$conn->query("INSERT INTO Assignment(Name, Email, Category, Message)VALUES('$name', '$email', '$category', '$message')", MYSQLI_STORE_RESULT);
$conn->close();
echo "sent to database";
}
}
?> <!-- End of PHP -->
Essentially I need to figure out another if statement to put just after the first one, but for the life of me I can't think of a condition to have. I thought what if I made a boolean that was false, and once all the data is correct it is put to true, but I can't figure out how to implement it. Just looking for any ideas on how to go about it
When I do validation, I personally try to come up with a function that will validate each value similarly. There are a few checks you should be doing as you go. Here is a restructure of what you have with some notations:
<?php
//Define the database connection
$conn = mysqli_connect("danu.nuigalway.ie","myb1608re","fa3xul", "mydb1608") or die (mysql_error());
// I usually build a simple validate function
// This is just an example, you can edit based on your needs
function validate_var($value = false,$type = 'str')
{
// Validate the different options
if(!empty($value) && $value != false) {
switch ($type) {
case ('str'):
return (is_string($value))? true:false;
case ('num') :
return (is_numeric($value))? true:false;
case ('email'):
return (filter_var($value,FILTER_VALIDATE_EMAIL))? true:false;
}
// This will just check not empty and string length if numeric
if((is_numeric($type) && !empty($value)) && (strlen($value) >= $type))
return true;
}
// Return false if all else fails
return false;
}
// On post, proceed
if(isset($_POST['submit'])) {
//assign details to be posted to variables
$name = $_POST['name'];
$email = $_POST['email'];
// Strip the message of html as a precaution
// Since you are not binding in your sql lower down, you should probably use
// htmlspecialchars($_POST['message'],ENT_QUOTES))
// or use the binding from the mysqli_ library to escape the input
$message = htmlspecialchars(strip_tags($_POST['message']),ENT_QUOTES));
// Do a "just-incase" filter (based on what this is supposed to be)
$category = preg_replace('/[^a-zA-Z0-9]/',"",$_POST['category']);
// Validate string length of 10
if(!validate_var($name,10))
$error['name'] = true;
// Validate email
if(!validate_var($email,'email'))
$error['email'] = true;
// Validate message length
if(!validate_var($message,25))
$error['message'] = true;
// Validate your category
if(!validate_var($category))
$error['category'] = true;
// Check if there are errors set
if(!isset($error)) {
// Use the filtered variables,
// not the raw $_POST variables
$to = "e.reilly4#nuigalway.ie";
$subject = "Contact Form";
$body = "\r\n
Category: $category \r\n
Message: $message \r\n
Name: $name \r\n
Email: $email";
// Don't just send and insert, make sure you insert into your databases
// on successful send
if(mail($to,$subject,$body)) {
//Insert the data into the database
$conn->query("INSERT INTO Assignment(Name, Email, Category, Message)VALUES('$name', '$email', '$category', '$message')", MYSQLI_STORE_RESULT);
$conn->close();
echo "sent to database";
}
else
echo 'An error occurred.';
}
else {
// Loop through errors cast
foreach($error as $kind => $true) {
switch ($kind) {
case ('name') :
echo "* Name is too short";
break;
case ('email') :
echo "* You did not enter a valid email";
break;
case ('category') :
echo "* Please select a category";
break;
case ('message') :
echo "* Your message is too short";
break;
}
}
}
}
?>

Issues with a function and its return value

I made this kind of point system, where users can spend their points. The users points do get deducted. I didn't include alot of the variables, but they are all okay. The problem occurs at return($success) and return($error_message).
Here is the code:
function died($error) {
header("Location: error_points_on.php?error=" . $error);
die();
}
function success($success) {
header("Location: success_points_on.php?success=" . $success);
die();
}
function quote_smart($value, $handle) {
if (get_magic_quotes_gpc()) {
$value = stripslashes($value);
}
if (!is_numeric($value)) {
$value = "'" . mysql_real_escape_string($value, $handle) . "'";
}
return $value;
}
function product($price,$points, $name, $uname, $error_message, $success_message) {
$user_name = "cencord";
$pass_word = "cencord";
$database = "cencord";
$server = "cencord";
$db_handle = mysql_connect($server, $user_name, $pass_word);
$db_found = mysql_select_db($database, $db_handle);
if ($db_found) { // connect to DB
$uname = quote_smart($uname, $db_handle);
$SQL = mysql_query("SELECT points FROM members WHERE username=$uname");
$points = mysql_fetch_row($SQL);
$points = $points[0]; // make it a variable rather then an array
if ($points >= $price) {
$points = $points-$price; // fjern points
$points = quote_smart($points, $db_handle);
mysql_query("UPDATE members SET points=$points WHERE username = $uname");
$success_message .= "The " . $name . " has been mailed to your E-mail, please allow 5 minutes for it to arrive.<br />";
return($success_message);
}
else if ($points < $price) {
$error_message .= "You have " . $points . " you need " . $price . " points to purchase a " . $name;
return($error_message);
}
else if (!$db_found) {
$error_message .= "Could not connect to the database, please contact support";
return($error_message);
}
}
}
if($Checked1 == true) {
product(400, $points, "Some string", $uname, $error_message, $success_message); //price and name
}
if($Checked2 == true) {
product(400, $points, "Some string", $uname, $error_message, $success_message);
}
if(strlen($error_message) > 0) {
died($error_message);
}
if(strlen($success_message) > 0) {
success($success_message);
}
echo "error didnt pass at all";
I could add the
header("Location: success_points_on.php?success=" . $success);
instead of a return, but I want the user to be able to purchase multiple items, (adding it instead of a return does work).
Your logic nesting is wrong. Stripping out the guts and leaving just the if statements, you have in your product() function:
function product($price,$points, $name, $uname, $error_message, $success_message) {
if ($db_found) { // connect to DB
if ($points >= $price) {
$success_message = "blah";
return($success_message);
}
else if ($points < $price) { // This if () part is redundant, btw
$error_message = "blah";
return($error_message);
}
else if (!$db_found) {
$error_message .= "blah"; // This should be = instead of .=
return($error_message);
}
}
}
What you want instead is:
function product($price,$points, $name, $uname, &$error_message, &$success_message) {
if ($db_found) {
if ($points >= $price) {
$success_message = "blah";
return($success_message); // this is redundant actually
} else {
$error_message = "blah";
return($error_message); // this is redundant actually
}
} else {
$error_message = "blah";
return($error_message); // this is redundant actually
}
}
I would strongly recommend the use of some tool such as an IDE which can keep your code formatted correctly, this will make these types of problems easier to see.
EDIT
I also just noticed that you are not passing $error_message and $success_message by reference which will cause further problems. Changes made above (in second example) but this code is still not what I would call best practice.
I agree with everything #leftclickben said above, but would like to add one more observation. I seems that you are using the value of $error_message and $success_message in the code that follows your call to product(), but TO LET THE FUNCTION CHANGE THEIR VALUE, YOU MUST PASS THEM BY REFERENCE, using the & symbol.
Change your function prototype to
function product($price,$points, $name, $uname, &$error_message, &$success_message) {
and changes in the value will be available after the function returns.

Looping correctly though array

Okay so I'm looping through the results that contains two question IDs and two answers and I'm trying to match the two answers with the two answers from the form submission.
I'm not sure what I'm doing wrong.
<?php
// Include the database page
require ('../inc/dbconfig.php');
require ('../inc/global_functions.php');
//Login submitted
if (isset($_POST['submit'])) {
// Errors defined as not being any
$errors = false;
if (trim($_POST['answer1']) == '') { $errors = true; }
if (trim($_POST['answer2']) == '') { $errors = true; }
// Error checking, make sure all form fields have input
if ($errors) {
// Not all fields were entered error
$message = "You must enter values to all of the form fields!";
$output = array('errorsExist' => $errors, 'message' => $message);
} else {
$userID = mysqli_real_escape_string($dbc,$_POST['userID']);
$answer1Post = mysqli_real_escape_string($dbc,$_POST['answer1']);
$answer2Post = mysqli_real_escape_string($dbc,$_POST['answer2']);
$question1 = mysqli_real_escape_string($dbc,$_POST['question1']);
$question2 = mysqli_real_escape_string($dbc,$_POST['question2']);
$query = "SELECT * FROM manager_users_secretAnswers WHERE userID = '".$userID."'";
$result = mysqli_query($dbc,$query);
// Count number of returned results from query
if (mysqli_num_rows($result) > 0) {
while ($row = mysqli_fetch_array($result)) {
$answer = $row['answer'];
// Comparing the database password with the posted password
if (($answer == $answer1Post) && ($answer == $answer2Post)) {
} else {
$errors = true;
$message = "Your answers did not match the answers inside the database!";
$output = array('errorsExist' => $errors, 'message' => $message);
}
}
} else {
$errors = true;
$message = "We did not find any answers for your questions! Please consult the site administrator!";
$output = array('errorsExist' => $true, 'message' => $message);
}
}
}
//Output the result
$output = json_encode($output);
echo $output;
?>
Since your question is not clear in the first place, so I'm assuming that the question you are asking is "why you're not getting any matching results, when you've the correct answers in the database?". Please correct me, if this is wrong.
The logic can be like this:-
<?php
// Include the database page
require ('../inc/dbconfig.php');
require ('../inc/global_functions.php');
// Login submitted
if (isset($_POST['submit'])) {
// Errors defined as not being any
$errors = false;
if (trim($_POST['answer1']) == '') { $errors = true; }
if (trim($_POST['answer2']) == '') { $errors = true; }
// Error checking, make sure all form fields have input
if ($errors) {
// Not all fields were entered error
$message = "You must enter values to all of the form fields!";
$output = array('errorsExist' => $errors, 'message' => $message);
} else {
$userID = mysqli_real_escape_string($dbc, $_POST['userID']);
$answer1Post = mysqli_real_escape_string($dbc, $_POST['answer1']);
$answer2Post = mysqli_real_escape_string($dbc, $_POST['answer2']);
$question1 = mysqli_real_escape_string($dbc, $_POST['question1']);
$question2 = mysqli_real_escape_string($dbc, $_POST['question2']);
$query = "SELECT * FROM manager_users_secretAnswers WHERE userID = '".$userID."'";
$result = mysqli_query($dbc, $query);
// Count number of returned results from query
if (mysqli_num_rows($result) > 0) {
while ($row = mysqli_fetch_array($result)) {
$answer = $row['answer'];
// Comparing the database password with the posted password
if ($answer == $answer1Post) {
// The first answer is correct
$errors = false;
$message = "Your first answer is correct!";
} else if ($answer == $answer2Post) {
// The second answer is correct
$errors = false;
$message = "Your second answer is correct!";
} else {
$errors = true;
$message = "Your answers did not match the answers inside the
}
$output = array('errorsExist' => $errors, 'message' => $message);
}
} else {
$errors = true;
$message = "We did not find any answers for your questions! Please consult the site administrator!";
$output = array('errorsExist' => $true, 'message' => $message);
}
}
}
// Output the result
$output = json_encode($output);
echo $output;
?>
It's better to have more segregation of logical conditions. In this case, it's your two answers to check for.
Hope it helps.

Categories