Log in

View Full Version : No Revoting or hide once voted.



Rockonmetal
07-09-2007, 10:47 PM
Ok so I got the W3 Schools Ajax Poll System thing. It works great accept. Someone could sit there all day voting "yes" or "no" and render it usless.

How it works.
Person votes then they see there results. It uses js, php, and good old fashion forms and text. Quite simple.
I was thinking that after the person votes they could no longer vote again. When they refresh the page they see their results.
Heres all the code:
PHP Page which holds the form:

<div id="poll">
<form>
Yes:
<input type="radio" name="vote"
value="0" onclick="getVote(this.value)">
<br>No:
<input type="radio" name="vote"
value="1" onclick="getVote(this.value)">
</form>
</div>
External Js Page which holds the Javascript:

var xmlHttp

function getVote(int)
{
xmlHttp=GetXmlHttpObject()
if (xmlHttp==null)
{
alert ("Browser does not support HTTP Request")
return
}
var url="poll_vote.php"
url=url+"?vote="+int
url=url+"&sid="+Math.random()
xmlHttp.onreadystatechange=stateChanged
xmlHttp.open("GET",url,true)
xmlHttp.send(null)
}

function stateChanged()
{
if (xmlHttp.readyState==4 || xmlHttp.readyState=="complete")
{
document.getElementById("poll").
innerHTML=xmlHttp.responseText;
}
}

function GetXmlHttpObject()
{
var objXMLHttp=null
if (window.XMLHttpRequest)
{
objXMLHttp=new XMLHttpRequest()
}
else if (window.ActiveXObject)
{
objXMLHttp=new ActiveXObject("Microsoft.XMLHTTP")
}
return objXMLHttp
}
The other PHP Page/Code which does all the pretty processing:

<?php
$vote = $_REQUEST['vote'];//get content of textfile
$filename = "poll_result.txt";
$content = file($filename);//put content in array
$array = explode("||", $content[0]);
$yes = $array[0];
$no = $array[1];if ($vote == 0)
{
$yes = $yes + 1;
}
if ($vote == 1)
{
$no = $no + 1;
}//insert votes to txt file
$insertvote = $yes."||".$no;
$fp = fopen($filename,"w");
fputs($fp,$insertvote);
fclose($fp);
?><table cellpadding="0" cellspacing="0" border="0">
<tr>
<td>Yes:</td>
<td>
<img src="poll.gif"
width='<?php echo(100*round($yes/($no+$yes),2)); ?>'
height='20'>
<?php echo(100*round($yes/($no+$yes),2)); ?>%
</td>
</tr>
<tr>
<td>No:</td>
<td>
<img src="poll.gif"
width='<?php echo(100*round($no/($no+$yes),2)); ?>'
height='20'>
<?php echo(100*round($no/($no+$yes),2)); ?>%
</td>
</tr>
</table>

Is there anyway that I could make it so that the person cant vote again to rig the results?

djr33
07-09-2007, 11:03 PM
There is no way to block a specific person. You must have a way of deciding if they have voted twice. There are three possible ways:
1. Store a 'voted' cookie on their system, or use a session, which is similar. Problems: a cookie can be deleted; a session resets when they leave the page.
2. Do it based on IP address. Better, but the IP changes for dialup users and other rotating connections; people can also just use a second computer; occasionally, people will have the same IP at different times so people couldn't vote, and those on a network, such as a school, share an IP, so that means only one student from each school could vote, such as those living in the dorms.
3. Create a user system, where they must be logged in to vote. Well, this is problematic in two senses: 1. It would be hard to make, and probably more than you want to deal with; 2. You'd have the same problems as IP, checking whether they sign up for a second account.
Perhaps another solution would be to use email validation, where they must check their email and confirm a code, but that's more work than anyone voting would want, and people could still, if they wanted enough, sign up for extra emails.

So, I'd say use IP.

Create this, checkvoted.php:

<?php
function checkvoted() {
if (strpos(file_get_contents('iplist.txt'),$_SERVER['REMOTE_ADDR'].'|')) { return TRUE; }
else { return FALSE; }
}
?>

Now, you can use the following code:
include('checkvoted.php');
if (checkvoted()) { //don't allow voting
else { //voting ok

So, just include that on your pages. On the PHP script, place that on the top, and have it do nothing if they have already voted. You could use:
if (!checkvoted()) {, and then place a close bracket at the end of the script.
That would make it secure enough.
For the poll display page, I'd say disable the form, and replace it with "you have already voted". Simple enough.

Now, to create the IP list:
//....
}//insert votes to txt file
$insertvote = $yes."||".$no;
$fp = fopen($filename,"w");
fputs($fp,$insertvote);
fclose($fp);
//add this
$ips = @file_get_contents('iplist.txt');
$ipfile = fopen('iplist.txt','w+');
fwrite($ipfile,$ips.$_SERVER['REMOTE_ADDR'].'|');
fclose($ipfile);
//add above
?>

Rockonmetal
07-10-2007, 01:28 AM
Thanks man your advice really helped. Although you probably did a lot of hard work to get the code the first paragraphs pretty much convinced me to not put a voting limit on it. I'll just take off a percentage or extend the voting poll if the results seem unbalanced.

djr33
07-10-2007, 01:55 AM
I didn't say not to do it, but just warned you about the problems with the methods.
IP isn't that bad, and it's what most sites use. The main thing that is wrong with it is that people can come back from a different computer and vote again. But there is a limit to the number of computers people can access, so they can't just vote infinitely.

None of the methods are flawless, but it makes sense having something, so that they can't just vote over and over. Perhaps a session variable would be enough, at least to discourage it.

function checkvote() {
if (isset($_SESSION['checkvoted'])) {return TRUE;}
else {return FALSE;}
}

Then, instead of writing the file, just use:
$_SESSION['checkvoted'] = TRUE;

Also, to use sessions, you'll need to add:
session_start();
to the top of each page, to keep them 'logged in' for the duration of the time on the site.


Or, perhaps a cookie--
$_COOKIE['checkvoted']

Set with:
setcookie('checkvoted',TRUE,60*60*24*365);
//expires in one year (or when they delete it)


Note that a cookie (and session, depending on how you use it) might overlap with another poll if you have two on your site, so you might want to give them a unique name, like checkvote_poll3, etc.

The only downside to either method is that there are ways around it (another computer; resetting the cache), but it won't stop anyone from voting the first time, and it would discourage voting twice.

It's up to you whether you want to use it, though, since it is a tradeoff.