2

I'm running a site that uses qdbs 1.10 to offer a PHP based quote database with votes. Voting is implemented via GET, causing bots to vote on quotes by accident. To avoid this, I'd like to convert the GET requests to POSTs.

I'm a complete newbie at PHP, and web development in general. Is it possible to perform this chance with minimal knowledge? Are there any patterns to follow, or have you got some hints on how to do it?

(I'm changing robots.txt as a temporary solution, but this does not solve the underlying issue.)

Edit: This appears to be the relevant section of code. I did not write this myself of course, and I can only follow it by guessing what might be happening - I never learned one word of PHP.

index.php

if ($_GET['do'] || $_POST['do']) {
    switch ($_GET['do']) {
        case 'rate':
             $sql = "SELECT ip FROM ".$_qdbs[tpfx]."votes WHERE id='".mysql_real_escape_string($_GET['q'])."' AND ip='$ip'"; 
             $a = $db->_sql($sql);
             $row = $db->fetch_row($a);
             if ($row['ip'] != $ip) {
                 if ($_GET['r'] == 'good') {
                     $sql = "UPDATE ".$_qdbs[tpfx]."quotes SET rating=rating+1 WHERE id='".mysql_real_escape_string($_GET['q'])."'";
                     $a = $db->_sql($sql);
                     $sql = "INSERT INTO ".$_qdbs[tpfx]."votes (id,ip) VALUES ('".mysql_real_escape_string($_GET['q'])."', '".mysql_real_escape_string($ip)."')";
                     $a = $db->_sql($sql);
                 }
                 elseif ($_GET['r'] == 'bad') {
                     $sql = "UPDATE ".$_qdbs[tpfx]."quotes SET rating=rating-1 WHERE id='".mysql_real_escape_string($_GET['q'])."'";
                     $a = $db->_sql($sql);
                     $sql = "INSERT INTO ".$_qdbs[tpfx]."votes (id,ip) VALUES ('".mysql_real_escape_string($_GET['q'])."', '".mysql_real_escape_string($ip)."')";
                     $a = $db->_sql($sql);
                 }
             }
             header("Location: ".$ref);
             break;
    }
...

quote_rate.tpl

[<a href="?do=rate&q=<?php echo $q_id;?>&r=good" title="Rate as good"><b>+</b></a>|<a href="?do=rate&q=<?php echo $q_id;?>&r=bad" title="Rate as bad"><b>-</b></a>]

Edit: The idea to replace GET with POST came this related question.

Using AJAX to vote is something I'd like to do anyway, so of course an AJAX based solution would be great, too.

Community
  • 1
  • 1
mafu
  • 31,798
  • 42
  • 154
  • 247

2 Answers2

2

I'm assuming you are talking about crawlers and not spam-bots. You won't stop a spam-bot from 'clicking' your buttons by switching to POST. However, it sounds like your links, that use GET query strings, are being 'clicked'.

GET/POST isn't the problem. A link is a link. You can't stop a crawler from clicking them. And forms are forms, you can't stop vote-riggers or spam-bots from hammering your forms.

To solve the link problem, you will need to replace your links with forms. Forms are not typically sent by most crawlers, and certainly not by responsible ones if you tell them not to crawl those pages in robots.txt. You can even continue to use GET. You just need to use a form.

<form action="?do=rate&q=<?php echo $q_id;?>&r=good">
    <input type="submit" name="up" value="up" />
</form>
<form action="?do=rate&q=<?php echo $q_id;?>&r=bad">
    <input type="submit" name="down" value="down" />
</form>
DampeS8N
  • 3,621
  • 17
  • 20
  • Plenty of stuff will hit your form. Put a form on a page for a day, and I'd expect it to get "filled out" a dozen times. Even if you just have submit buttons, it will get hit all the time from bots testing for an e-mail relay. – Brad Jan 10 '11 at 15:54
  • @Brad: I addressed that in my answer as well already. However, in his case, google crawlers are clicking his links. – DampeS8N Jan 10 '11 at 15:57
  • Could you add an example of how code using forms look would like? – mafu Jan 10 '11 at 16:05
1

I think the best solution for you (hopefully others feel the same) is to change the HTML code that links to each +- sign by an AJAX function that will do the voting, for example:

instead of having this code:

[<a href="?do=rate&q=<?php echo $q_id;?>&r=good" title="Rate as good"><b>+</b></a>|<a href="?do=rate&q=<?php echo $q_id;?>&r=bad" title="Rate as bad"><b>-</b></a>]

You will have something like this:

[<a href="javascript:rateQuote('good',<?php echo $q_id;?>)" title="Rate as good"><b>+</b></a>|<a href="javascript:rateQuote('bad',<?php echo $q_id;?>)" title="Rate as bad"><b>-</b></a>]  

The JS function should look something similar to this:

function rateQuote(vote,id) {
if (window.XMLHttpRequest)
  {// code for IE7+, Firefox, Chrome, Opera, Safari
  xmlhttp=new XMLHttpRequest();
  }
else
  {// code for IE6, IE5
  xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
  }
xmlhttp.onreadystatechange=function()
  {
  if (xmlhttp.readyState==4 && xmlhttp.status==200)
    {
               //if you want to include a 'success' message, this is the place
    }
  }
xmlhttp.open("GET","index.php?do=rate&q="+id+"r="+vote,true);
xmlhttp.send();
}

As far as I know, generally, crawlers don't run javascript functions. But I am not 100% sure.

Or Weinberger
  • 7,332
  • 23
  • 71
  • 116
  • This doesn't account for those without JS. – DampeS8N Jan 10 '11 at 15:07
  • I also believe js based links prevent bots from following them, usually. I never learned js but I think I can follow your code sample, and I'll try to add it to the site. – mafu Jan 10 '11 at 15:10
  • You might find that adding that js between the tags, will actually vote for the quote, but won't remove the [+\-] signs after a person voted. In that case, you might want to add this line after the comment I made in the code for a success message: window.location.reload(); – Or Weinberger Jan 10 '11 at 15:13
  • *Some* crawlers *do* run Javascript. AJAX is not the answer to this problem. You're making the same requests this way as you would with a simple link. – Brad Jan 10 '11 at 15:53
  • I think there's an `&` missing in front of the `r=` in the code example. – mafu Jan 10 '11 at 15:55
  • @Brad: I don't really know, but I think changing robots.txt and using AJAX removes most of the problem - of course there may still be some ill-behaved bots, but that would probably lead too far in this case. – mafu Jan 10 '11 at 15:58
  • @Or W: I mean that only users with JS turned on will be able to engage in voting. Other solutions can solve as much of the problem without hurting users that have turned off JavaScript. – DampeS8N Jan 10 '11 at 16:02
  • @Brad - Some crawlers submit forms as well, google crawler will submit forms. I know I am replicating the same action through a JS function, that was my intension as it will reduce to nearly zero the amount of crawlers who vote for quotes. @DampeS8N - according to this link, it's not that common for people to turn off JS http://www.w3schools.com/browsers/browsers_stats.asp – Or Weinberger Jan 10 '11 at 16:12
  • @mafutrct - you're right, my mistake, there is a & missing there. Other than that, is it working? – Or Weinberger Jan 10 '11 at 16:13
  • It appears to be working, it's live. I don't know yet if it prevents the crawler issue but I guess it does. – mafu Jan 10 '11 at 16:29
  • I decided to go with this answer for two reasons: 1) I'll have to use js in the end anyway because of planned functionality 2) Other similar sites use the same approach – mafu Jan 10 '11 at 23:02