#!/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";
#Show the Admin MANUAL ADD facility
print "\n\n
Add voting elements manually
\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;
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 "$votecount | $percent% | $elementname | ";
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 "$totalcount total votes so far ... |
";
print "
\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 "
| $tempcount | $votecount | $percent% | $elementname | ";
if ($USE_BAR) {
$pixel_width = ($percent/100) * $MAX_BAR_LENGTH;
$pixel_width = sprintf("%9.0f",$pixel_width);
print " | ";
}
print "
\n";
}
print "
\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 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 "\n";
print "\n";
print "\n";
if ($REJECT == 1) {
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;
}
}