Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

I'm trying to add a rating system to my image gallery. I know how to make the web form and do the calculations to see how many stars out of five its earned. The problem is, all the images are being loaded from the same hash. I want it to be setup where you can vote on any images you want, but you can NOT vote on the same image twice.

The method? IP blocking, I don't see any other way to do it. But I can't setup one big .txt will IPs that already casted a vote on an image because that would block them from voting on other images as well.

Any suggestions on how to go about doing this?

Replies are listed 'Best First'.
Re: blocking IPs
by BrowserUk (Patriarch) on Jan 27, 2004 at 06:17 UTC

    As has been discussed here many times before, blocking on IP will not work. Every AOL, dial-up and many NAT users will be allocated a different IP each time they connect.

    Alternatively, where many users inside a LAN get to the internet through a common firewall, NAT or proxy, one IP will translate to many users. Without using some sort of cookie system, you will have considerable trouble determining which users have voted for what.

    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "Think for yourself!" - Abigail
    Timing (and a little luck) are everything!

      Even so, I'd rather be able to block and IP for an hour rather than having them be able to vote for the same image at 1 star 20 times in a row.
Re: blocking IPs
by crabbdean (Pilgrim) on Jan 27, 2004 at 06:40 UTC
    You'd have to get the person to sign up and use a login, to which you add a unique identifier and assign that identifier to the photo vote. eg. their email address is a good one.

    Obviously the problem here is you can't stop someone using two different email addresses or user accounts to vote more than once.

    Good Luck

Re: blocking IPs
by l3nz (Friar) on Jan 27, 2004 at 08:08 UTC
    Even if you consider IP blocking the way to go, beware of using flat files for your database. I don't know how big your site gets, but please notice that reparsing a single big file thousand and thousand times is a costly operation. Also, writing the same file by different processes at once might result in broken data under heavy load or transient opening errors. It would be much better if you had a database.

    If you don't want to use a database, I'd say go for a number of files, not just a single big one. You could use a number of files like ipblock_001.txt, ipblock_002.txt and so on, where the number is the least significant byte in the IP address. This way, IP address entries should be evenly distribuited among multiple files and you'll have less concurrency on the same file and much shorter access times. You should also prepare a job to 'purge' files of stale IP entries, unless you want to rewrite each file from scratch on every write access.

    A format for each file could be:
    ip-address picture-code timestamp-vote
    I'll assume you have the votes also in another file, as the content of this files will be rotated on an hourly basis. When a vote is cast, you read this file and determine whether you have a vote for this picture in the last hour; if you do, you print an error message; if you don't, you add an entry.

    Hope this helps

Re: blocking IPs
by BUU (Prior) on Jan 27, 2004 at 07:00 UTC
    With the above caveats about problems with ip blocking, what you want to do is just use a real database and store a row with the ip and the vote image and check against that on new votes. You could use either Mysql (or another 'real' database) or maybe dbfile, or possibly even just use Storable and store/retrieve a hash.
Re: blocking IPs
by b10m (Vicar) on Jan 27, 2004 at 13:58 UTC

    As soon as you cast the magic words "IP blocking" the default replies are always "think about the people behind a NAT firewall" and "there is no way you can use this". (I should write a bot for that someday ;)

    I, however, think that's unfair judgment for this specific case. I doubt that you run an image gallery with the load of /. or google. In your case I wouldn't be bothered by the fact that two people *might* not be able to vote, because someone else in the LAN already did so. Besides that, do you really care that much if you miss one legit rating, if you can block certain script kiddies?

    You can work out a login procedure, quite like Perlmonks, or Freshmeat for that matter. That way you can allow one vote per image, per user (as stated above), but I quite frankly get quite tired of all the websites you have to register for. You want to search through some message board? Register first! You want to read a certain post? Register first! You want to view an image? Register first!

    Yet another way could be the use of cookies. This is very easilly worked around, but hey, it can prevent the truely ignorant script kiddy-wannabees from rating an image a thousand times.

    Sessions could be another option. Same as with cookies. Easy to work around, but it'll stop the totally clueless.

    But, as prophesied before, if some script kiddy really wants to screw up your ratings, chances are big [s]he'll succeed.

    I think the easiest way for you, is to set up a simple database in which you store the IP of the voter, the image [s]he voted for, and the timestamp. Then disallow the IP to vote again for say a day or even a week. That way, you do allow others from the same IP to cast their vote (albeit with a delay) and you prevent the scriptkiddies from writing a simple bot to vote numerous times a minute. Then when someone wants to vote, you first check if their IP is already in your ban-database (for the specific image) and you check the timestamp (how long ago did we receive a vote for this already?). Based on the outcome of these tests, you either allow the vote, or politely report that the voter already voted for this image and that only one vote is allowed, possibly followed by your email address in case of questions.

    Just my €0,02

      I doubt the more than a million AOL customers can be considered to be on a single LAN. Sure, they have "lots and lots" of proxies, but up to a few years ago, they hid behind a dozen proxies. Perhaps they now have a few hundred of them. That still means they have a high user/IP ratio. And AOL isn't the only ISP with a lot more customers than proxies and/or NAT boxes.

      But you shouldn't only think big. Think small as well. Think families. Lots of families either share a computer, or are hidden behind the same proxy or NAT box. Blocking on IP means that little brother can vote, but when he shows the site to his sister, the sister can't.

      It's user hostile, and the tell mark sign of a bad programmer. A good programmer would never start from a broken design.


        It's choosing between two (or more) evils. Either you allow everyone to vote as often as possible (with possible abuse), or you restrict it in someway, and have some negative side effects, ranging from forcing people to register, to blocking potential legit votes (and the fact that you can work around it if you really want to).

        I take it, the OP has experienced people abusing the voting script, otherwise the whole blocking question probably never would come up.

        I, personally, find forcing users to register far more user unfriendly (hostile) than the blocking of some legit votes. It all depends on the amount of visits, I presume. If you only get a handful of visitors a day, blocking based on IP probably won't hurt. If you get a lot of visitors, it might work counter productive, I agree. And yes, small sites might get big, but a lot of them will stay small forever.

        In this specific case, the OP seems to have the voting procedures all done, and adding the procedures for users to log in (because I presume you think that is a better way, but I have no clue of knowing that for sure, since you don't specify a better alternative) probably takes a lot more time than implementing a simple IP-blocking test. And I personally would not do that, because of my already explained annoyance with registration on (simple) websites.

        I fully agree that IP blocking isn't nice (and personally, I would just allow everyone to vote as often as possible and would manually look through the logs to see if I could detect certain abusive votes, or even write a script to do the work for me and report every Monday, first thing in the morning :), but disregarding IP blocking as useful straight when you see the words isn't helping much either. It all depends on specific cases. Most sites won't get away with it, but small sites could use it quite well, IMHO.