0

I am new to PHP/MySQL and the whole website designing. I am building a website where pre-defined users can vote. I have a database with a list of users. I am trying to avoid duplicate votes. I read that you could block IP address or use cookies, but I am trying to use another method.

In my database called 'users' I have three columns - Username, Password and flag. Flag has a default value of 0. Once, the user votes, I set the flag for that particular user to 1. Now, if the user tries to vote again, I want to check the value of flag in my database. If it's 0 I'd send him to "Thank You for voting" page and update another database I created called results which keeps track of the number of votes each candidate has received. If not, I take him to another page which says, "You have already voted." Everything is working fine so far, except I don't know how to read the value of flag in my database and use an if condition of it.

Here's what I have so far:

<?php

$host="localhost"; // Host name 
$username="dbxxxxx"; // Mysql username 
$password="password"; // Mysql password 
$db_name="dbxxxxx_users"; // Database name 
$tbl_name="users"; // Table name 


// Connect to server and select databse.
mysql_connect("$host", "$username", "$password")or die("cannot connect"); 
mysql_select_db("$db_name")or die("cannot select DB");

$user = $_COOKIE["details"];  //cookie details has the username the user used to log in

$SQL = "SELECT flag FROM users WHERE Username='$user'";
$flag = mysql_query( $SQL );   //no clue what's happening here. Just trying random stuff
$db_field = mysql_fetch_assoc($flag);  


if($db_field==0)     //checking the value of flag in the database
{       
    mysql_query("UPDATE result SET Votes=Votes+1 //if flag in database = 0 
    WHERE Name='Candidate1'");  //updates result for candidate1 if the user voted for 1

    $user = $_COOKIE["details"];  //reading the cookie again. can be omitted.

    mysql_query("UPDATE users SET flag=1   //changing flag to 1 so user cannot vote again
    WHERE Username='$user'");

    header("location: http://www.lithuaniavote.com/thankyou.html");
 }

else    //flag != 1 or user has already voted
{
    header("location: http://www.lithuaniavote.com/alreadyvoted.html");
}

?>

PS: This code changes the flag from 0 to 1 in the database. However, there's something wrong with the if condition. I am able to vote even if the flag is 1, which is an indication that I have already voted or in other words, It never takes me to the Already Voted page.

  • 1
    I'm going to guess that the problem is the syntax error in your SQL updating the flag, but your code has much worse problems than that. You're constructing SQL queries using unescaped user input. – Cairnarvon Apr 14 '13 at 01:16
  • Debug your code: [How to get useful error messages in PHP?](http://stackoverflow.com/q/845021/1409082) – Jocelyn Apr 14 '13 at 01:20
  • 1
    You're also mixing up `$db_field` and `$fdb_field`. – icktoofay Apr 14 '13 at 01:20
  • Check the variable you used in the if statement – kabuto178 Apr 14 '13 at 01:26
  • 3
    ___Never___ use the `mysql_*` functions. Use prepared statements instead (MySQLi or PDO with `PDO::ATTR_EMULATE_PREPARES` set to `false`). –  Apr 14 '13 at 01:28
  • @Zoidberg: It shows me an error if I change mysql to mysqli. – Dikssha S Chhawla Apr 14 '13 at 16:55
  • @kabuto178: Yes, I noticed that and changed it in my code, but that doesn't change anything really. – Dikssha S Chhawla Apr 14 '13 at 16:56
  • @icktoofay: I changed both to db_field, but it still doesn't do what I need it to do. – Dikssha S Chhawla Apr 14 '13 at 16:58
  • @Cairnarvon: I checked my database and flag is being updated in the database after the user votes once. However, the only problem here is that even though flag is being updated in the database, it still won't stop me from voting. Could you please point to the problems that you found in my code. Thanks. – Dikssha S Chhawla Apr 14 '13 at 16:59

2 Answers2

0

Original code:

$SQL = "SELECT flag FROM users WHERE Username=$user";
$flag = mysql_query( $SQL );   //no clue what's happening here. Just trying random stuff
$db_field = mysql_fetch_assoc($flag);  
if($db_field==0)     //checking the value of flag in the database

Try this:

$SQL = "SELECT flag FROM users WHERE Username = '$user'"; // $user should be in 'quotes'
$flag = mysql_query( $SQL );  // This is the actual query to the database
$db_field = mysql_result($flag, 0);  // This is the result of the query.
if($db_field===0)  // Use 3 equals signs instead of 2 in this case (which means "exactly equal to")
jerdiggity
  • 3,655
  • 1
  • 29
  • 41
  • That doesn't help much. If I replace the code with what you have here... it takes me to Already Voted page every time, even if the user is voting for the first time. Let me ask you this, how do you read a value from the database and put it into another variable? If you were to read a value from the database and store it in a variable in PHP how would you do that? – Dikssha S Chhawla Apr 14 '13 at 16:53
  • Thanks a lot though. I appreciate your feedback. :) – Dikssha S Chhawla Apr 14 '13 at 17:01
0

I think you should try a much cleaner (and future-proof) approach. Let me re-construct the solution to your problem with PDO:

namespace Voting {
    $pdo = new \PDO("mysql:host={$host};dbname={$db_name};charset=utf8", $username, $password);

    if ($query1 = $pdo->prepare("SELECT `flag` FROM `users` WHERE `Username` = ?;", [\PDO::ATTR_CURSOR => \PDO::CURSOR_FWDONLY])) {
        if ($query1->execute([$_COOKIE["details"]])) {
            $result = $query1->fetch(\PDO::FETCH_ASSOC);

            if (intval($result["flag"]) === 0) {
                if ($query2 = $pdo->prepare("UPDATE `users` SET `flag` = '1' WHERE `Username` = ?")) {
                    $query2->execute([$_COOKIE["details"]]);
                    $pdo = null;
                    header("Location: http://www.lithuaniavote.com/thankyou.html");
                }
            } else {
                $pdo = null;
                header("Location: http://www.lithuaniavote.com/alreadyvoted.html");
            }
        }
    }
}

WARNING: Take into account I'm not checking for $_COOKIE safety. You must do some form of sanitization to prevent injections and other vulnerabilities.

Julio María Meca Hansen
  • 1,303
  • 1
  • 17
  • 37
  • Oh, almost forgot to mention it... this code should work as-is under PHP 5.4.x. If you need to make it run in PHP 5.3.x, substitute the bracket notation (`[]`) for arrays and replace them with `array()`. In case it's PHP 5.2.x remove the namespace and the `\\` symbols for all PDO operations (it only works with PHP 5.3.x+). Hope that helps ;) – Julio María Meca Hansen Apr 14 '13 at 17:30
  • Thank You so much for your reply, Julio. I am using PHP version 5.3.15 and it shows me an error on this line: if($query1 = $pdo->prepare("SELECT `flag` FROM `users` WHERE `Username` = ?;", [\PDO::ATTR_CURSOR => \PDO::CURSOR_FWDONLY])) Here's the error: Parse error: syntax error, unexpected '[' in /nfs/c03/h04/mnt/166547/domains/lithuaniavote.com/html/vote1.php on line 8. Hope you can help further. – Dikssha S Chhawla Apr 15 '13 at 04:18
  • Sure, I'm accustomed to write PHP 5.4 compliant code, so you just need to replace `[\PDO::ATTR_CURSOR => \PDO::CURSOR_FWDONLY]` with `array(\PDO::ATTR_CURSOR => \PDO::CURSOR_FWDONLY)`. That should get you going :) – Julio María Meca Hansen Apr 15 '13 at 08:10
  • Same goes for the parameter passed into the `execute()` method. Substitute any bracket structure with its corresponding `array()` equivalent, so instead of `[$_COOKIE["details"]]` it's `array($_COOKIE["details"])` – Julio María Meca Hansen Apr 15 '13 at 08:11
  • @Julia Meca Hansen: I did exactly what you said. There are no errors in the code now. However, I want to point out that with this code it always takes the user to 'YOU HAVE ALREADY VOTED' page irrespective of the value of the flag. I have set flag to 0 in my database, and even then it would take me to Already Voted page. Any ideas? – Dikssha S Chhawla Apr 15 '13 at 22:58
  • insert `print intval($result["flag"]);` before the flag check. What value does it give to you? It should be 0, thus entering the loop. The `intval()` function should guarantee that its output value is treated like an integer – Julio María Meca Hansen Apr 16 '13 at 08:44