PHP Form must be submitted twice to update checkbox - php

I'm still relatively new to PHP. I'm trying to build a privacy settings page for members to opt out of automatic emails for triggered events (i.e. private message notification). I want the checkbox set automatically based on the database setting. As of now, the form does update the database correctly, but the checkbox status does not show the correct setting unless the Submit button is pressed twice, or the page is reloaded. Setting would be '0' for unchecked, '1' for checked. I'd love to use Ajax or jQuery to handle this, but I don't know those at all.
privacysettings.php
<?php
$id = "";
$pm_mail_able = "";
$pm_email = "";
if (isset($_GET['id'])) {
$id = preg_replace('#[^0-9]#i', '', $_GET['id']); // filter everything but numbers
} else if (isset($_SESSION['idx'])) {
$id = $logOptions_id;
} else {
header("location: index.php");
exit();
}
//query to get checkbox status
$sql = mysql_query("SELECT * FROM members WHERE id='$id'");
while($row = mysql_fetch_array($sql)){
$pm_mail_able = $row['pm_mail_able'];
}
switch ($pm_mail_able) {
case 0:
$pm_setting = NULL;
break;
case 1:
$pm_setting = "checked=\"checked\"";
break;
}
if(isset($_GET['pm_email']) && !empty($_GET['pm_email'])) {
$updateqry = mysql_query("UPDATE members SET pm_mail_able='1' WHERE id='$id'");
} else {
$updateqry = mysql_query("UPDATE members SET pm_mail_able='0' WHERE id='$id'");
}
?>
<html>
Email Notifications<br />
<form name="testform" method="get" action="PvResult.php">
When a friend sends me a private message
<input type="checkbox" name="pm_email" value="on"<?php echo $pm_setting;?> />
<br /><br />
<input type="submit" value="Submit" />
</form>
</html>
PvResult.php
<?php
$url = 'http://www.mywebsite.com';
//If the form isn't submitted, redirect to the form
if(!isset($_GET['Submit']))
header('Location: '.$url.'/privacysettings.php');
//Redirect to the correct location based on form input
$pm_email = $_GET['pm_email'];
$url .= '/privacysettings.php?pm_email='.$pm_email;
header('Location: '.$url);
?>

Okay, hopefully this won't just answer your question, but give you a few best practices you might want to consider.
You can combine these two scripts into one relatively easily. Also, I'd highly suggest using a POST instead of GET; GET is very limited and is not intended to submit data like you're using it. If you're going to be changing data in a back-end store, using GET will bite you. Maybe not today, maybe not tomorrow, but it will, trust me.
You really should consider moving to PDO instead of the mysql_ functions. PDO is a lot better in handling parameterized queries, which you really should have here for better security, and it's more portable if someday you want to move to a different database system.
I'm still a little hazy on how your app is getting the $id. Most apps get it from a $_SESSION variable, making sure that the user has successfully validated a login. If you're not doing that, please do. You might want to thoroughly digest this article, it's got a lot of juicy best practices regarding authentication and "remember me"-type functionality.
Here's a bit of a rewrite. I haven't actually tested it, but it should give you a pretty good idea on where to go with your immediate needs. If it throws any errors (remember the disclaimer: I haven't actually tested it!), let me know and I'll try to debug it.
<?php
$message = '';
$pm_setting = '';
$id = 0;
// Put your $id retrieval logic here. It should look something like:
if (isset($_SESSION['id'])) {
$id = $_SESSION['id'];
if (!preg_match('/^\\d{1,10}$/', $id) > 0) {
// Someone is trying to hack your site.
header("location: scum.php");
exit();
}
$id = intval($id);
}
// Quick security note: You might want to read up on a topic called
// session hijacking if you want to ensure your site is secure and
// this $id isn't spoofed.
if (isset($_POST['Submit'])) {
// The form is being submitted. We don't need to read the current
// pm_mail_able setting from the database because we're going to
// overwrite it anyway.
if ($id > 0) {
$pm_mail_able = 0;
if (isset($_POST['pm_email']) && $_POST['pm_email'] === 'on') {
$pm_mail_able = 1;
$pm_setting = 'checked ';
}
$query = 'UPDATE members SET pm_mail_able='.$pm_mail_able.
' WHERE id = '.$id;
mysql_query($query);
// Another quick security note: You REALLY need to consider
// updating to PDO so that you can bind these parameters
// instead. The mysql_ functions are probably going to be
// deprecated soon anyway.
if (mysql_affected_rows($query) > 0)
$message = '<p style="color: #00a000;">Settings saved!</p>';
else
$message = '<p style="color: #a00000;">User id not valid.</p>';
}
else
$message = '<p style="color: #a00000;">User id not valid.</p>';
}
else {
// This is the first load of the form, we need to just display it
// with the existing setting.
if ($id > 0) {
$query = mysql_query('SELECT * FROM members WHERE id = '.$id);
if (($row = mysql_fetch_array($query, MYSQL_ASSOC)) !== FALSE)
if ($row['pm_mail_able'] === 1) $pm_setting = 'checked ';
}
}
?>
<html>
<body>
<?= $message ?>
<!-- Without action parameter, form submitted to this script. -->
<form name="testform" method="post">
E-mail notifications<br />
<input type="checkbox" name="pm_email" value="on" <?= $pm_setting ?>/>
When a friend sends me a private message
<br /><br />
<input type="submit" value="Submit" />
</form>
</body>
</html>

Try to do these settings and see if it will work:
1) You need to add an space between "on" and "checked=checked"
<input type="checkbox" name="pm_email" value="on" <?php echo $pm_setting;?> />
2) You have to reference the submit button by its name, not its value
<input type="submit" name="Submit" value="Send" />
3) When the setting is "0", set $pm_setting as a empty string, instead of NULL
case 0:
$pm_setting = '';
4) Maybe there is some problem with $_GET['pm_email'] and the else is always being executed
5) If the things work when you press the Submit button twice, it means that the form is passing some GET var that make the code work, so try to discover what var is this

Related

Search-engine: Php get data from anchor-tag

I have this html search here:
<form action="index.php" method="POST">
<input id="search" type="text" placeholder="Search for Friends" name="search_name">
<input class="submit" type="submit" name="search-submit" value="Search">
</form>
And this php code for the search engine:
<?php
if (isset($_POST['search-submit'])) {
$search_name = $_POST['search_name'];
$aVar = mysqli_connect('localhost','root','','socialnetwork');
$result = mysqli_query($aVar, "SELECT username FROM users WHERE username LIKE '%$search_name%'");
$found = 1;
while ($row = mysqli_fetch_assoc($result)) {
$username = $row['username'];
#$output .= '<h2 class="friends-display">'.$username.'</h2><hr>';
}
}
?>
Now this code is working fine. It allows the user to search for other users.
The anchor tag "friends-display" shows the result of the code by using the variable $output. The $output is then echoed later in the aside.
My problem is the following: I want to make an if-statement so when the anchor tag "friends-display" is clicked by the user it should show the profile of the username the user has clicked on.
Example: you search for Mike and you find this username. Than you click on it and it should show the profile of Mike. How can I make this with an anchor tag?
I have tried if isset(), but it did not work for me.
Change the output variable like below
....
while ($row = mysqli_fetch_assoc($result)) {
$username = $row['username'];
#$output .= '<h2 class="friends-display">'.$username.'</h2><hr>';
}
....
Create a new file profile.php and add the following basic line.
<?php
If(isset($_GET['user']) && !empty($_GET['user'])){
$username = $_GET['user'];
// check for username found in database.
// if not found exit with error "user not found"
// else show user profile
}else{
Die("unothrized access");
}
I hope this will guide you to achieve your target..
Happy coding :)

Login returns password does not match in php

I hope you are doing great. I have within my project a login functionality. when I try to login. It gives me this strange error that I did not write within my login.php script. I wrote it somewhere else and did not make an import to it. I hope you guys can help me identify the problem.
Thanks in Advance. Cheers,
Some useful pieces of my code:
Login.php Script:
<?php
include_once 'Header.php';
?>
<style>
#container {
height: 92vh;
}
</style>
<div id="container">
<br>
<?php
$_SESSION['logged'] = null;
//in this page we do things slightly differently - the code for validation and displaying messages is done
//before we display the form
echo '<div id = "div_1"><h1>Login</h1>';
//display the form
echo '<div id="div_2"><div id="div_2">
<form action="Login.php" method="post">
<label>Email<br>
<span class="small">enter your Email</span>
</label>
<input type="text" name="Email" value=""/>
<label><br>Password<br>
<span class="small">enter your password</span>
</label>
<input type="password" name="Password" />
<button type="submit" name="submit" value="Login" />Log in</button>
<input type ="hidden" name="submitted" value="1">
</form>
</div>
</div>';
if (isset($_POST['submitted'])) {
//require_once is similar to 'include' but ensures the code is not copied multiple times
require_once('LoginFunctions.php');
$name3 = $_POST['Email'];
$pwd3 = $_POST['Password'];
echo $name3;
echo $pwd3;
//list() is a way of assigning multiple values at the same time
//checkLogin() function returns an array so list here assigns the values in the array to $check and $data
list($check, $data) = checkLogin($_POST['Email'], $_POST['Password']);
if ($check) {
setcookie('FName', $data['FName'], time() + 900); //cookie expires after 15 mins
setcookie('LName', $data['LName'], time() + 900);
//
//use session variables instead of cookies
//these variables should now be available to all pages in the application as long as the users session exists
$_SESSION['FName'] = $data['FName'];
$_SESSION['LName'] = $data['LName'];
$_SESSION['Email'] = $data['Email'];
//to enable $_SESSION array to be populated we always need to call start_session() - this is done in header.php
//print_r is will print out the contents of an array
print_r($_SESSION);
//
//Redirect to another page
$url = absolute_url('Index.php'); //function defined in Loginfunctions.php to give absolute path for required page
$_SESSION['logged'] = TRUE;
echo $_SESSION['logged'];
//this version of the header function is used to redirect to another page
echo "<script>setTimeout(\"location.href = '" . $url . "';\",10000);</script>"; //since we have entered correct login details we are now being directed to the home page
exit();
} else {
$errors = $data;
}
}
//create a sopace between the button and the error messages
//echo'<div class="spacer"></div>';
if (!empty($errors)) {
echo '<br/> <p class="error">The following errors occurred: <br />';
//foreach is a simplified version of the 'for' loop
foreach ($errors as $err) {
echo "$err <br />";
}
echo '</p>';
}
//this is the end of the <div> that contains the form
echo '</div>';
/* */
?>
</div>
<?php
include 'Footer.php';
?>
My loginFunctions.php class:
<?php
function absolute_url($page = 'Index.php')
{
//header('Location: http:\\localhost');
//exit(); //terminates the script
$url = 'http://' . $_SERVER['HTTP_HOST'] . dirname($_SERVER['PHP_SELF']);
$url = rtrim($url, '/\\');
$url .= '/' . $page;
return $url;
}
function checkLogin($Email = '', $password = '')
{
$errors = array();
if(empty($Email))
$errors[] = 'You must enter a Email';
if(empty($password))
$errors[] = 'You must enter a password';
if(empty($errors))
{
////set up database econnection
include 'DBConn.php';
$db = new DBConn();
$dbc = $db->getDBConnection();
$q = "select Email, FName, LName from Users_1 where Email = '$Email' and Password = '$password'";
$r = mysqli_query($dbc, $q);
if($r)
{
if(mysqli_affected_rows($dbc) != 0)
{
$row = mysqli_fetch_array($r, MYSQLI_ASSOC);
return array(true, $row);
}
else
{
$errors[] = 'Passwords do not match';
}
}
else{
echo '<p class="error"> Oh dear. There was a database error</p>';
echo '<p class = "error">' . mysqli_error($dbc) .'</p>';
}
}
return array(false, $errors);
}
?>
mysqli_affected_rows is used for returning rows affected by insert, update and delete operation. For select statement you must use mysqli_num_rows
if($r) {
if(mysqli_num_rows($r) != 0){
$row = mysqli_fetch_array($r, MYSQLI_ASSOC);
return array(true, $row);
}else {
$errors[] = 'Passwords do not match';
}
}
For better security: you can use password_hash() function to make your password stronger and later match the hash you saved in the field (Password- datatype would be varchar with a length of 255). You match this hash using password_verify() function which has two parameters: the string that user typed and the hash saved in the database.
For example:
echo password_hash("rasmuslerdorf", PASSWORD_DEFAULT)."\n";
will print:
$2y$10$.vGA1O9wmRjrwAVXD98HNOgsNpDczlqm3Jq7KnEd1rVAGv3Fykk1a
When a user login using rasmuslerdorf as password, you query the database and match the stored hash password $2y$10$.vGA1O9wmRjrwAVXD98HNOgsNpDczlqm3Jq7KnEd1rVAGv3Fykk1a with rasmuslerdorf using password_verify :
$q= mysqli_query($dbc, "SELECT Password FROM `Users_1`
WHERE `Email` = '$Email' and `Password` = '$password'");
$res = mysqli_fetch_assoc($q);
$hash = $res['Password'];
if (password_verify('rasmuslerdorf', $hash)) {
echo 'Password is valid!';
} else {
echo 'Invalid password.';
}
This is a fairly non-technical answer but it contains my advice based on my own experience.
When I was just learning html and had no real idea about php or javascript, I would spend hours trying to figure out how logins worked.
After a while I found out about php and javascript, and I had a friends php login script to go on.
I managed to get a database working, however the signup did not which is why I posted this question.
Eventually I got the login working, however my limited knowledge meant that I could have been storing peoples (and friends) private information such as passwords that they use elsewhere, on a website that could have had a major flaw.
Now don't get me wrong, I am not saying don't do this I am simply saying DO YOUR RESEARCH. Take time watching videos like this:
https://www.youtube.com/watch?v=8ZtInClXe1Q
How NOT to Store Passwords! - Computerphile
and then spend some more time doing database queries that don't involve passwords.
Once you have a good understanding of how to use queries and feel confident doing them, begin researching hashing methods in php.
Please take a look into:
Salting your passwords where you essentially add random
characters to the password that is being hashed so that you cant use
a hashing table to reverse a hashed password.
SQL Injection where people use the input (name field or any other field) on your form to change the syntax of your question, and essentially add code to your website. This is dangerous because then they can (depending on what permissions the user has) drop tables, drop databases, select *, and many other harmful things. This topic is also mentioned in the video mentioned before about "How NOT to Store Passwords!".
Do more research (don't only use that link it does not contain everything)...when you are storing peoples information you can never be too safe. Don't think of these tips as overkill, think of them as a responsibility to your users, that they can TRUST that nothing will happen to their password!
Good luck!

How to redirect to another page in php?

Here is the code for registration. Values are inserted properly but page is not redirected to another page:
if(isset($_POST['submit'])){
$company_name = $_POST['company_name'];//check whether form is submitted or not
$email = filter_var($_POST['email'],FILTER_SANITIZE_EMAIL);//email validation
$password = sha1($_POST['password']);
$phone = $_POST['phone'];
$city = $_POST['city'];
$profession = $_POST['profession'];
check validation of email
if(!filter_var($email,FILTER_SANITIZE_EMAIL)){
echo 'invalid email';
}
else
{
$result = mysql_query("SELECT * FROM registerpro WHERE email = '$email'");selecting email from database
$data = mysql_num_rows($result);//check if there is result
if($data==0){
$qry = mysql_query("INSERT INTO registerpro (company_name,email,password,phone,city,profession) VALUES ('$company_name','$email','$password','$phone','$city','$profession')");
here i is the problem as page is not redirecting to another page so please tell me how to fix it
if($qry){
header("Location : company_info.php");//redirect to company_info
}
else`enter code here`
{
echo 'error';
}
}else{
echo 'invalid email';
}
}
}
?>
After registration page is not redirecting to company_info.
Remove extra space after Location
So, change
header("Location : company_info.php");//redirect to company_info
To:
header("Location: company_info.php");//redirect to company_info
// ^ here
I finally figured this out after struggling a bit. If you perform a web search on the PHP header() function you will find that it must be used at the very top of the file before any output is sent.
My first reaction was "well that doesn't help", but it does because when the submit button is clicked from the HTML input tag then the header() function will get run at the top.
To demonstrate this you can put a section of PHP code at the very top with the following line...
print_r($_POST);
When you then press the "Submit" button on your web page you will see the $_POST value change.
In my case I wanted a user to accept the Terms & Agreement before being redirected to another URL.
At the top of the file before the HTML tag I put the following code:
<?php
$chkboxwarn = 0;
/* Continue button was clicked */
if(!empty($_POST['continue']) && $_POST['continue']=='Continue'){
/* Agree button was checked */
if(!empty($_POST['agree']) && $_POST['agree']=='yes'){
header('Location: http://www.myurlhere.com');
}
/* Agree button wasn't checked */
else{
$chkboxwarn = 1;
}
}
?>
In the HTML body I put the following:
<form method="post">
<input type="checkbox" name="agree" value="yes" /> I understand and agree to the Terms above.<br/><br/>
<input type="submit" name="continue" value="Continue"/>
</form>
<?php
If($chkboxwarn == 1){
echo '<br/><span style="color:red;">To continue you must accept the terms by selecting the box then the button.</span>';
}
?>

Input does not pass validation test for strlen

I am making a login system and I have a form with some validation.
However my form seems to be failing to pass the validation even though the data input should pass easily.
See:
http://marmiteontoast.co.uk/fyp/login-register/index.php
When you input a username, it should be over 3 characters. But even if you enter one really long you get the error message: The username is less than 3 characters.
EDIT: There was an issue in my copying from formatting that caused a missing }. I've corrected this. It wasn't the issue.
This is the if statement for the username pass. So it seems like it is not getting past the first test:
if (isset($_POST['username'])){
$username = mysql_real_escape_string(trim($_POST['username']));
$_SESSION['status']['register']['username'] = $username;
if(strlen($username) > 3){
if(strlen($username) < 31){
if(user_exists($username) === true){
$_SESSION['status']['register']['error'][] = 'That username is already taken. Sorry, please try again with a different username.';
}else{
// passed
}
} else {
$_SESSION['status']['register']['error'][] = 'The username is greater than 30 characters.';
}
} else {
$_SESSION['status']['register']['error'][] = 'The username is less than 3 characters.';
}
} else {
$_SESSION['status']['register']['error'][] = 'The username is not entered.';
}
And this is the HTML for the username:
<form method="post" action="register.php">
<div class="username">
<label class="control-label" for="inputUser">Username</label>
<input type="text" id="inputUser" name="username" placeholder="Username" value="<?php echo $usern_value; ?>" />
</div>
You can see the site here: http://marmiteontoast.co.uk/fyp/login-register/index.php
Session
The index page does use sessions.
It starts with this:
<?php
session_start();
?>
And kills the session at the end of the file:
<?php
unset($_SESSION['status']);
?>
But in the file it starts new sessions which store the inputs. This is so if you make a mistake, it still holds your info so you can adjust it rather than having the fill in the form again. Here is an example of where it grabs the username and saves it, then outputs it.
<?php
if(isset($_SESSION['status']['register']['username'])){
$usern_value = $_SESSION['status']['register']['username'];
} else {
$usern_value = "";
}
?>
value="<?php echo $usern_value; ?>" />
This is the user-exists function:
function user_exists($username){
$sql = "SELECT `id` FROM `users` WHERE `username` = '".$username."'";
$query = mysql_query($sql);
$result = mysql_num_rows($query);
if($result == 1){
// username does already exist
return true;
}else{
// username doesn't exist in the database
return false;
}
}
Ah, I can see the problem from your website link. When the error pops up ("The username is less than 3 characters."), try refreshing your browser. I expected to receive a browser warning that says the data would be resubmitted to the server — because you are in a post form — but I did not.
So, what does this mean? It means that immediately after validation failure, you are redirecting back to the same screen, and — unless you are using a session to preserve this information — your $_POST data will be lost. Commonly in the case of validation failure with this sort of form, you must prevent that redirect and render inside the post operation, which keeps the user's input available to you. The redirect should only occur if the form input was successful (i.e. it saves to the data and/or sends an email).
Edit: I should have seen the $_SESSION in the original post. OK, so the strategy is to write things to the session, redirect regardless of validation outcome, and to save error messages to the session. I wonder whether you are not resetting the session errors array when you're posting the form? Immediately after your first if, try adding this:
if (isset($_POST['username'])){
$_SESSION['status']['register']['error'] = array(); // New line
Unless you have something to make the session forget your errors, they will be stored until you delete your browser's cookie.
You have missed a closing brace } on this line:
if(user_exists($username) === true){
} else{// **missed the closing brace before the else**
// passed
}
Why is your logic so complex?
if (strlen($username) < 3) {
// too short
} elseif (strlen($username) > 31) {
// too long
} elseif (true === user_exists($username)) {
// already registered
} else {
// passed
}

Implement Security to this application?

At the moment I am attempting to create an application that passes on data to delete a row in my database. This row will be known by the ID passed on by the html file to js.
Currently I have a Html file, Javascript and PHP file which all work together to get this data passed in.
What im looking to do is secure it so no-one unauthorised can just send data to the javascript document in-order to delete the row.
HTML -- > JS --> PHP
JS:
function deleteListing(id) {
var answer = confirm("Are you sure you want to delete this listing?")
if (answer) {
$.post("assets/scripts/deleteListing.php", {
id: id
},
function (result) {
var response = jQuery.parseJSON(result);
if (response.available === true) {
location.reload();
} else if (response.available === false) {
// alert("FAILURE DELETING USER");
} else if (response.root === true) {
// alert("Cannot Delete Root User..");
}
});
} else {
return;
}
}
PHP:
<?
require("../../../assets/config/config.php");
$id_retrieve = $_POST['id'];
$data = new stdClass();
$sth= $dbh-> prepare("SELECT * FROM listings WHERE id='".$id_retrieve."'");
$sth -> execute();
$row = $sth -> fetch();
$data->available = true;
$dbh->exec("DELETE FROM listings WHERE id = '".$id_retrieve."'");
echo json_encode($data);
?>
Before anyone says the statement is not created using the prepared statement, I am aware of this and will fix it asap. Apart from that, is there anyway I can secure the Javascript file from unauthorised access? or could I limit it somehow?
Thanks!
There are a couple of solutions.
As #Tobias said above: Use sessions to handle the authentication. That will protect you some.
However, that alone doesn't stop Cross-Session attacks.
Take a look at this page: http://phpsec.org/projects/guide/2.html
It suggests putting a token value on the form and saving it in the session. That way, when the form is submitted you can compare the incoming token against the one in your session and verify that the form did, indeed, come from your site.
<?php
session_start();
if (isset($_POST['message']))
{
if (isset($_SESSION['token']) && $_POST['token'] == $_SESSION['token'])
{
$message = htmlentities($_POST['message']);
$fp = fopen('./messages.txt', 'a');
fwrite($fp, "$message<br />");
fclose($fp);
}
}
$token = md5(uniqid(rand(), true));
$_SESSION['token'] = $token;
?>
<form method="POST">
<input type="hidden" name="token" value="<?php echo $token; ?>" />
<input type="text" name="message"><br />
<input type="submit">
</form>
<?php
readfile('./messages.txt');
?>

Categories