#!/usr/bin/perl ############################################################################################ # AnyVote $version = 1.31; # # Written by Jonathan Cogley # Copyright 1998. THYCOTIC WEBDESIGN # http://www.thycotic.com # E-Mail : info@thycotic.com # ############################################################################################ ############################################################################################ # # PLEASE NOTE : ALL CONFIGURATION INFORMATION IS NOW CONTAINED IN CONFIG.CGI # ############################################################################################ ############################################################################################ # This script may not be sold or distributed in any other form # without the permission of Thycotic WebDesign. # # Please note that the script is supplied as is under the Shareware agreement. You are # not permitted to customise the actual code without permission by Thycotic WebDesign. # If you wish to customise Anyvote further then you will have to contact us to purchase a # commercial license. # ############################################################################################ # Changes History # ################### # # 1.3 -> 1.3.1 Added ability to allow voting items to start with 0 votes # You can now configure how many votes you want Suggested items and # Admin added items to start with ... # Added a bar graph option to the output of the results making the top ten # and all votes options easy to interpret # Thanks to everyone for their fantastic suggestions! :) # # 1.2.1 -> 1.3 Separated configuration options into a new file config.cgi to make future # upgrades simpler for all the users out there! :) # (Anyvote.cgi now contains just pure code.) # Addition of a referral check to improve security with additional logging # 1.2 -> 1.2.1 Added a MAXLENGTH field for limiting amount of suggestion text # 1.1 -> 1.2 Tightened security of votes! Introduced a log file to optionally capture the ip # addresses of the voters after abuse of the voting system on the gothic music site. # The voteip file now stops last 10 people from revoting by default (can be configured) # Added option for customising the target tag for links and also prevented HTML # and (potentially) SSI calls from being entered as suggestions!!! (possible security hole!) # Those two suggestions were from Hendrik Jan de Bruyn (http://www.introweb.nl/~hjdb) # Many thanks! - and happy Anyvoting! # 1.0 -> 1.1 Added the ability to produce a rejected suggestion list. This allows visitors # to see which suggestions have been rejected. It was a shame to have to just # delete some of the hilarious suggestions you can get! :) # ############################################################################################ ############################################################################################ ############################################################################################ ### Nothing below this line may be changed without the permission of Thycotic WebDesign #### ############################################################################################ ############################################################################################ require "config.cgi"; print "Content-type: text/html\n\n"; print $BODYTAG; print "
"; &load_votefile; &parse_form; $inputstring = $ENV{'QUERY_STRING'}; $htmltag = chr(85).chr(110).chr(114).chr(101).chr(103).chr(105).chr(115).chr(116).chr(101).chr(114).chr(101); $htmltag = $htmltag.chr(100).chr(32).chr(118).chr(101).chr(114).chr(115).chr(105).chr(111).chr(110); if (-e "anyvote.key"){ open (KEY,"; close (KEY); chomp($key); $string = "Anyvote"; $length = length $string; $tempcode = crypt ($string, $length); if ($key eq crypt ($string, $length)) { $htmltag = substr($htmltag, 3, (length $htmltag) -3); $htmltag = chr(82).$htmltag; } } if ($inputstring eq "$ADMIN" || $Form{'admin'}) { &check_referral; &do_admin; } elsif ($Form{'voting'}) { #&check_referral; &do_voting; } elsif ($Form{'suggesting'}) { #&check_referral; &do_suggestion; } elsif ($Form{'fullvotelist'}) { &print_allvotes; print "$RETURNTEXT

"; &tagline; } elsif ($Form{'showwaiting'}) { &load_waiting; &print_waiting; print "$RETURNTEXT

"; &tagline; } elsif ($Form{'showreject'}) { &load_reject; &print_reject; print "$RETURNTEXT

"; &tagline; } else { &print_topten; &print_vote_form; } # Check Referral ################################################################ sub check_referral { if ( $ENV{'HTTP_REFERER'} !~ /$SCRIPTURL/i ) { $votelogmsg = "Call from another page!! $ENV{'HTTP_REFERER'}"; &write_vote_log; end; } } # Do admin ################################################################ sub do_admin { print "\n"; print "

Voting Administration

\n"; &load_waiting; if ($Form{'add'}) { open (VOTEFILE, ">>$VOTEDATA"); flock (VOTEFILE,2); print VOTEFILE "$SUGGEST_STARTVOTE|$Form{element}\n"; close (VOTEFILE); &remove_from_waiting; print "$Form{element} has been added to the available voting elements!

"; &load_waiting; } if ($Form{'manualadd'}) { open (VOTEFILE, ">>$VOTEDATA"); flock (VOTEFILE,2); print VOTEFILE "$MANUALADD_STARTVOTE|$Form{element}\n"; close (VOTEFILE); print "$Form{element} has been manually added to the available voting elements!

"; &load_waiting; } if ($Form{'reject'}) { &remove_from_waiting; open (REJECT, ">>$REJFILE"); flock (REJECT,2); print REJECT "$Form{origelement}\n"; close (REJECT); print "$Form{origelement} has been added to the rejection list!

"; &load_waiting; } if ($Form{'delete'}) { &remove_from_waiting; print "$Form{origelement} has been deleted from the suggestions list!

"; &load_waiting; } if ($Form{'deletevote'}) { &load_votefile; &remove_from_main_vote; print "$Form{element} has been deleted from the MAIN VOTE list!

"; } if ($Form{'sortvote'}) { print "MAIN VOTE file vote.dat has been sorted alphabetically!

"; &load_votefile; &sort_vote_file; } &show_waiting; &load_votefile; &admin_vote_form; &tagline; } # show admin waiting list ################################################################ sub show_waiting { if (@waiting[0] eq "") { print "There are no suggestions waiting to be added.

\n"; } else { foreach $line (@waiting) { chop($line); print "
\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; if ($REJECT == 1) { print "\n"; } print "
\n"; print "
\n"; } } print "
\n"; #Show the Admin MANUAL ADD facility print "\n\n

Add voting elements manually
\n"; print "
\n"; print "\n"; print "\n"; print "\n"; print "
\n\n"; } # Load the waiting file ################################################################ sub load_waiting { open (WAITING, "$WAITING"); flock (WAITING,2); @waiting = ; close (WAITING); } # Load the reject file ################################################################ sub load_reject { open (REJECT, "$REJFILE"); flock (REJECT,2); @rejentries = ; close (REJECT); } # Print the reject file ################################################################ sub print_reject { if (@rejentries[0] eq "") { print "There are no rejected suggestions to show.

\n"; } else { @rejentries = sort @rejentries; print "The following suggestions have been rejected :"; print "
"; foreach $line (@rejentries) { print "$line
"; } print "


"; } } # remove element from waiting list ################################################################ sub remove_from_waiting { open (WAITING, ">$WAITING"); flock (WAITING,2); foreach $line (@waiting) { chop($line); if ($line eq $Form{'origelement'}) {#dont copy over to new file } else { print WAITING "$line\n"; } } close (WAITING); } # remove element from MAIN VOTE LIST ################################################################ sub remove_from_main_vote { open (VOTEFILE, ">$VOTEDATA"); #load vote file into an array flock (VOTEFILE,2); foreach $line (@listings) { ($votecount,$elementname) = split(/\|/,$line); chop($elementname); if ($elementname eq $Form{'element'}) {#dont copy over to new file } else { print VOTEFILE "$votecount|$elementname\n"; } } close (VOTEFILE); } # Do/Process a suggestion ################################################################ sub do_suggestion { print "
"; if ($Form{'suggestion'} eq "name") { print "Please enter the band you would like to suggest!

"; print "$RETURNTEXT"; &tagline; exit; } if ($LOGIP) { &check_ip; #check the voters ip address } #check to see if in queue already &load_waiting; $suggestion = "$Form{'suggestion'}"; $suggestion =~ tr/A-Z/a-z/; foreach $line (@waiting) { chop($line); $line =~ tr/A-Z/a-z/; if ($line eq $suggestion) { print "Your suggestion is already in the suggestion queue and will be added to the voting list shortly
"; print "$RETURNTEXT

"; &load_waiting; &print_waiting; &tagline; exit; } } #check to see if in voting file already &load_votefile; $suggestion = "$Form{'suggestion'}"; $suggestion =~ tr/A-Z/a-z/; foreach $line (@listings) { #read the element names from array ($votecount,$elementname) = split(/\|/,$line); @elements = (@elements,$elementname); } foreach $line (@elements) { chop($line); $line =~ tr/A-Z/a-z/; if ($line eq $suggestion) { print "Your suggestion is already in the voting list - just vote for it!
"; print "$RETURNTEXT

"; &tagline; exit; } } #Take out any potential nasty HTML or etc ... $_ = "$Form{'suggestion'}"; tr///d; #that should do the trick ... open (WAITING, ">>$WAITING"); #open file for adding suggestion flock (WAITING,2); print WAITING "$_\n"; close (WAITING); if ($LOGIP) { &write_new_ip; #write new voters ip address } print "Thanks for suggesting $Form{'suggestion'}
"; print "This suggestion will be reviewed and included in our voting list shortly!"; print "

$RETURNTEXT

"; &load_waiting; &print_waiting; &tagline; } sub tagline { print "AnyVote $version"; print " by Thycotic WebDesign
$htmltag
"; } # Do the voting bit ################################################################ sub do_voting { print "
"; if ($Form{'element'} eq "default") { print "Please select a band to vote for!

"; print "$RETURNTEXT

"; &tagline; exit; } if ($LOGIP) { &check_ip; #check the voters ip address } open (VOTEFILE, ">$VOTEDATA"); #open file for adding vote flock (VOTEFILE,2); foreach $line (@listings) { chop($line); ($votecount,$elementname,) = split(/\|/,$line); if ($Form{'element'} eq $elementname) { $votecount++; } print VOTEFILE "$votecount|$elementname\n"; } close (VOTEFILE); if ($LOGIP) { &write_new_ip; #write new voters ip address } &load_votefile; &print_topten; print "

Thanks for voting for $Form{'element'}!
"; print "The new figures are shown above ...
"; print "
$RETURNTEXT

"; &tagline; } # Load the vote data file ################################################################ sub load_votefile { open (VOTEFILE, "$VOTEDATA"); #load vote file into an array flock (VOTEFILE,2); @listings = ; close (VOTEFILE); } # Print the waiting file ################################################################ sub print_waiting { if (@waiting[0] eq "") { print "There are no suggestions waiting to be added.

\n"; } else { @waiting = sort @waiting; print "The following items are currently in the suggestion queue:"; print "
"; foreach $line (@waiting) { print "$line
"; } print "


"; } } # Check the voters ip address ################################################################ sub check_ip { # Load previous voters ip from ip file open (ADDRESSFILE, "$VOTEIP"); #load vote file into an array flock (ADDRESSFILE,2); @oldips = ; close (ADDRESSFILE); foreach $oldip (@oldips) { #check against all ips in the $VOTEIP file chomp($oldip); if ($oldip eq $ENV{REMOTE_ADDR}) { print "You cant vote again! - you have only just voted.

"; print "$RETURNTEXT

"; &tagline; exit; } $ipcount++; } } # Write to the vote log ################################################################ sub write_vote_log { open (IPLOG, ">>$VOTELOG"); flock (IPLOG,2); $temp_element = $Form{'element'}; chomp($temp_element); print IPLOG "$ENV{REMOTE_ADDR} $ENV{'REMOTE_HOST'} $votelogmsg\n"; close (IPLOG); } # Write new voters ip address ################################################################ sub write_new_ip { if ($USELOGGING == 1) { if ($Form{'voting'}) { $votelogmsg = $temp_element; &write_vote_log; } else { $votelogmsg = "Suggested: $temp_element"; &write_vote_log; } } if ($ipcount > $IPBLOCKNUM) { open (ADDRESSFILE, ">$VOTEIP"); for ($n = $ipcount - ($IPBLOCKNUM - 1); $n < $ipcount; $n++ ) { flock (ADDRESSFILE,2); print ADDRESSFILE "$oldips[$n]\n"; } print ADDRESSFILE "$ENV{REMOTE_ADDR}\n"; close (ADDRESSFILE); } else { open (ADDRESSFILE, ">>$VOTEIP"); flock (ADDRESSFILE,2); print ADDRESSFILE "$ENV{REMOTE_ADDR}\n"; close (ADDRESSFILE); } } # Parse form input ################################################################ sub parse_form { read (STDIN, $buffer, $ENV{'CONTENT_LENGTH'}); @cgiPairs = split(/&/,$buffer); foreach $cgiPair (@cgiPairs) { ($name, $value) = split(/=/,$cgiPair); $name =~ s/\+/ /g; $value =~ s/\+/ /g; $name =~ s/%(..)/pack("c",hex($1))/ge; $value =~ s/%(..)/pack("c",hex($1))/ge; $Form{$name} .= "\0" if (defined($Form{$name})); $Form{$name} .= "$value"; } undef $name; undef $value; } #Print the TOP TEN votes so far ################################################################ sub print_topten { foreach $line (@listings) { ($votecount,$elementname) = split(/\|/,$line); $totalcount = $totalcount + $votecount; } #do a sort based on whether the total votes is 0 or not... if ($totalcount ==0) { @listings = sort @listings; } else { @listings = sort by_number @listings; } $count = 0; $totalcount = 0; foreach $line (@listings) { ($votecount,$elementname) = split(/\|/,$line); $totalcount = $totalcount + $votecount; if ($count < 10) { @toptenlistings = (@toptenlistings, $line); } $count++; } $count = 1; print ""; foreach $line (@toptenlistings) { ($votecount,$elementname,) = split(/\|/,$line); if ($totalcount != 0) { $percent = ($votecount / $totalcount) * 100; $percent = sprintf("%9.1f",$percent); } else { $percent = 0; } print ""; if ($USEIMAGES) { print ""; } print ""; if ($USE_BAR) { $pixel_width = ($percent/100) * $MAX_BAR_LENGTH; $pixel_width = sprintf("%9.0f",$pixel_width); print ""; } print "\n"; $count++; } print ""; if ($USEIMAGES) { print ""; } print ""; print "
$votecount$percent%$elementname
$totalcount total votes so far ...
\n\n"; } #Print all the votes so far ################################################################ sub print_allvotes { $bandcount = 0; foreach $line (@listings) { ($votecount,$elementname) = split(/\|/,$line); $totalcount = $totalcount + $votecount; $bandcount++; } #do a sort based on whether the total votes is 0 or not... if ($totalcount ==0) { @listings = sort @listings; } else { @listings = sort by_number @listings; } print "\n"; foreach $line (@listings) { ($votecount,$elementname,) = split(/\|/,$line); if ($totalcount != 0) { $percent = ($votecount / $totalcount) * 100; $percent = sprintf("%9.1f",$percent); } else { $percent = 0; } $tempcount++; print ""; if ($USE_BAR) { $pixel_width = ($percent/100) * $MAX_BAR_LENGTH; $pixel_width = sprintf("%9.0f",$pixel_width); print ""; } print "\n"; } print "
$tempcount   $votecount$percent%$elementname
\n\n"; print "
$totalcount total votes so far ...

"; print "$bandcount bands listed!


"; } #Show mini vote form for admin purposes ################################################################ sub admin_vote_form { foreach $line (@listings) { #read the element names from array ($votecount,$elementname) = split(/\|/,$line); @elements = (@elements,$elementname); } @elements = sort @elements; #sort the array print "
"; print "Elements currently available to vote on:\n"; print "
\n"; print "\n"; print "\n"; if ($REMOVEFROMMAIN) { print "\n"; } print "
\n"; print "
\n"; print "
\n"; } #Print the vote form ################################################################ sub print_vote_form { foreach $line (@listings) { #read the element names from array ($votecount,$elementname) = split(/\|/,$line); @elements = (@elements,$elementname); } @elements = sort @elements; #sort the array print "
"; print "
\n"; print ""; print "\n"; print "\n"; print "
\n"; print "
\n"; print "Is your fave not listed?
"; print ""; print "\n"; print "
(Please spell correctly)"; print "
\n"; print "
\n"; print ""; print "\n"; print "
\n"; print "
\n"; print ""; print "\n"; print "
\n"; if ($REJECT == 1) { print "
\n"; print ""; print "\n"; print "
\n"; } print "
"; &tagline; } #Sort the vote file ################################################################ sub sort_vote_file { foreach $line (@listings) { #read the element names from array chop($line); ($votecount,$elementname) = split(/\|/,$line); $newline = "$elementname|$votecount\n"; @newelements = (@newelements,$newline); } @newelements = sort @newelements; #sort the array open (VOTEFILE, ">$VOTEDATA"); #load vote file into an array flock (VOTEFILE,2); foreach $newline (@newelements) { chop($newline); ($elementname,$votecount) = split(/\|/,$newline); print VOTEFILE "$votecount|$elementname\n"; } close (VOTEFILE); } # Sort routine ################################################################ sub by_number { if ($a > $b) { -1; } elsif ($a == $b) { 0; } elsif ($a < $b) { 1; } }