#!/usr/bin/perl
# NOTE: the above line must be changed to show the path to the
# Perl interpreter on your system! Leave the #! as is, but
# the path may have to be changed if yours is different.
#########################################################################
# Votesie 1.1.1 01/04/2004 #
# A simple voting/polling script. Lets visitors to a website vote on #
# a question, and view the total results. Admin can configure new polls,#
# including the color scheme and look of the Poll and Results pages. #
# #
# Copyright 1999, Kristina L. Pfaff-Harris, http://tesol.net/scripts/ #
# All rights reserved. #
# #
#########################################################################
##### License for Votesie 1.1.1
#####
##### This program may be used free of charge under the following
##### conditions:
#####
##### 1. All instructions and Copyright lines must remain unchanged.
#####
##### 2. All pages generated by the program must contain one of the
##### following pieces of HTML code:
#####
##### Powered by Votesie:
#####
##### http://www.tesol.net/scripts
##### OR:
#####
#####
#####
##### You may not remove the information described above from the script
##### without express written permission from the author.
#####
##### 3. You may not sell or distribute this program. You may charge
##### a reasonable fee for installing it for a client as long as
##### you make it clear that you are not the author, and you are
##### not selling the program to them: only charging for installing
##### it.
#####
##### 4. You agree that this program is offered without warranty of
##### any kind, including warranty of fitness for a particular
##### purpose. You further agree that the author and all sites
##### associated in any way with this program are not liable for
##### any damage or loss incurred as a result of using this program.
#####
##### 5. You may modify the program for your own use but you may not
##### distribute modified copies under any circumstances without
##### express written permission from the author.
#####
##### 6. Use of this program requires agreement to all the terms and
##### conditions of this license. If you do not agree to one or
##### more of these terms, you may not use the program.
#####
########################################################################## #
# Using the program: #
# This program requires the files "votesie.cgi", and text files #
# votesie_votes.txt and votesie_voters.txt for storing the poll results.#
# #
# In this program (the file you're looking at now), I #
# have put **CHANGE** wherever the program needs to be modified. If #
# your editor can search for text, you can easily find what to change #
# and how to change it. You must follow the instructions for how to #
# change things. This is a program, and as such, can get quite fussy #
# about very small syntax errors. #
# #
# Permissions: The votesie.cgi file must be "chmod 755". In #
# addition, your "votesie_votes" should be writeable by the web server. #
# This usually means making it chmod 766. If you don't know how to do #
# this, ask your system administrator. #
# #
# Where these files go depends on how your web server is set up. #
# Sometimes, all cgi files MUST be in the "official" cgi-bin #
# directory. Other times, the files can be anywhere as long as #
# they end in ".cgi". Again, check with your system administrator #
# to see where you need to put this. #
# #
#########################################################################
# #
# I hope this program proves useful to you! Please contact me #
# (http://tesol.net/scriptmail.html) for any bugs or feedback. #
# #
#########################################################################
print "Content-type: text/html\n\n";
%data = &get_data();
#########################################################################
# #
# BEGIN SECTION WHERE YOU NEED TO CHANGE THINGS #
# #
# In this next section, there are various things that you need to #
# change in order to get the program to work the way you'd like it to. #
# Don't worry: each variable has an explanation of what it does and #
# what you'll need to do in order to change it. Be careful of things #
# like " and ; and be sure to read the instructions. If you do this, #
# then you should be fine! #
# #
#########################################################################
# First of all, let's determine if we want to enable some debugging
# information. This can be very useful when you are first setting up
# the program, as it can tell you whether or not the program can find
# your "votesie_votes" and whether it can add entries to it. If you're
# done installing Votesie, and it seems to be working, **CHANGE** this to:
# $debugging = "0";
# Otherwise, you should leave it set to "1", so that you can see any errors
# that are happening while you're setting it up.
$debugging = "1";
# Next, you need to decide whether you want to try and keep
# people from "stuffing the ballot box." This is based on the IP
# address of the user that is voting, and so, for many reasons,
# is not foolproof. Since many Internet Service Providers use
# "dynamically assigned" IP addresses, then two different users
# could conceivably hit your site with the same address, in which
# case, the second user could not vote. By the same token, the same
# user could have a different address the next time they get on
# the Internet, and so could vote again. On the other hand, this
# will keep a single user from just reloading the votes results
# page over and over to add votes to their favorite answer. If
# you want the program to NOT count votes from the same IP
# address, **CHANGE** $dup_check = "off"; to $dup_check = "on";
# For those of you who know about proxying, the program does
# take into account the "HTTP_X_FORWARDED_FOR" header, so that
# people behind a firewall will not be unfairly penalized by the
# IP check.
$dup_check = "on";
# The next few "$javascript_whatever" options are in case you would like
# the results of the poll displayed in a little JavaScript popup window.
# If you would like the poll results to be displayed in a little popup
# window, set $javascript_popup = "yes"; Otherwise, just leave it set
# to "no".
$javascript_popup = "yes";
# Assuming that you have set $javascript_popup = "yes"; above, and would
# like the nice popup window, the next two items let you determine the
# width and height of the results window. I think that 400 wide by
# 230 high is more or less good for most purposes, but if you would like
# it smaller or larger, then change the number 400 and/or 230 to whatever
# number you feel is appropriate.
# $javascript_popupwidth is the width of the popup window:
$javascript_popupwidth = "400";
# $javascript_popupheight is the height of the popup window:
$javascript_popupheight = "230";
# Okay, now I have tried to set this up so that if you use the JavaScript
# popup window, it will still work if people don't have JavaScript. However,
# if your visitors have problems with the JavaScript, then you can still
# set $javascript_popup to no, and still have the results open in a new
# window. If you set $results_in_new_window = "yes"; then the results
# will open in another browser window. If you set it to "no", then the
# results will open in the same window as the poll. You probably won't
# need to change this.
$results_in_new_window = "yes";
# $votesie_votes is the system path to the file that contains the
# current poll + votes. This is NOT a URL, and must NOT begin with
# "http://". It should begin with "/". **CHANGE** this to the system
# path to your votesie_votes file. (The file must be chmod 766)
# Sometimes, the setting I have below will work fine for you. (Try it
# and see.) Otherwise, it should be something like:
# Unix:
# $votesie_votes = "/home/users/your/www/directory/votesie_votes.txt";
# Windows:
# $votesie_votes = "c:/Inetpub/wwwroot/your_directory/votesie_votes.txt";
#
# Note that on some operating systems, what I have below might work if
# the "votesie_votes" file in the same directory as this program.
# IMPORTANT: If your file does not end with ".txt" then you
# will need to make the filename below match what you actually have
# on your server, and vice versa. It does not matter what these files
# are called, as long as what is on the server EXACTLY matches
# what is listed in the script.
$votesie_votes = "./votesie_votes.txt";
# $voters should be, like $votesie_votes above, the full path to
# the "votesie_voters.txt" file. This file will keep track of users'
# IP addresses for each issue in case you care to turn duplicate
# checking on. **CHANGE** this to the path to votesie_voters on
# your server. NOTE: If your file does not end with ".txt" then you
# will need to make the filename below match what you actually have
# on your server, and vice versa. It does not matter what these files
# are called, as long as what is on the server EXACTLY matches
# what is listed in the script.
$voters = "./votesie_voters.txt";
# $path_to_poll_files is the system path to the directory where you
# want the program to create your poll files. As with $votesie_votes
# above, this should begin with "/" (on a Unix-based system) and should
# probably begin with "c:" or "d:" or similar on an NT-based system.
# It must not end with "/" or "\\". If
# you use the same path conventions as with votesie_votes above, you
# should be fine. **CHANGE** this to something appropriate for your
# site.
$path_to_poll_files = "/path/to/your/directory/for/polls";
# $votesie_url is what you would type in a browser to view files
# in the directory above (path_to_poll_files). This should begin
# with "http://" and should NOT end with a "/" and should NOT end
# with ".html". **CHANGE** this to something appropriate for your site.
$votesie_url = "http://your_domain.edu/directory/for/polls";
# $cgi_url is the full http URL to the votesie.cgi program
# (this program) on your web server. It should begin with
# http:// and end with "votesie.cgi". Note: On NT-based systems,
# you may have to rename votesie.cgi to votesie.pl. If this is the
# case, then the below should end with "votesie.pl" or whatever the
# filename of this program is. **CHANGE** this...well, you get the idea.
$cgi_url = "http://your_domain.edu/votesie.cgi";
# $admin_password is the password you will use to add new polls,
# archive old ones, and otherwise administer the system.
# **CHANGE** this to an appropriate password that would not
# be easily guessed. For example:
# $admin_password = "BX9mlkj7";
# $admin_password = "H0oHa4";
# etc...
$admin_password = "password";
# Here, we will define our HTML header. You can monkey about with the
# HTML code here so that it looks like that of your page. WARNING:
# any " (quotes) or @ ("at" signs) must have a \ (backslash) in front
# of them. Please be very careful if you modify the HTML code here --
# just one free " and the script will never run. You can put anything
# you like in between the and lines. This is only really used on the admin screens.
# You may **CHANGE** this to something that will fit in with the look
# of the rest of your site. Please see the FAQ at http://tesol.net/scripts/FAQ
# for more detailed information about what to do with $header and so forth.
$header = "
Votesie v1.1.1
Votesie v1.1.1
"; #<-- This quote and semicolon are necessary! Don't backslash them!
# Now define our HTML footer. As before, you may change the html
# code, but be careful of " and @ signs. Please leave the copyright
# notice and the address of Scripts for Educators so that other
# people can find and use this program. **CHANGE** this if you
# wish, bearing in mind the caveats from $header above.
$footer = "
"; #<-- This quote and semicolon are necessary! Don't backslash them!
# Okay this is the last thing that needs to be changed. If, for some reason,
# someone pulls up "votesie.cgi" all by itself, we'll give them a list of
# polls currently on the system. However, we won't have the colors
# available since each poll is created with custom colors, so we'll need
# to know how to display a poll if it's just by itself. Also, if you don't
# want to have to check a color box when creating a poll, it will just create
# polls with the colors that you fill in below. These colors need to be
# HTML "hex" colors WITHOUT the "#", or strange things will happen.
# You might just leave this the way it is, if you don't mind how it looks.
# $even_color is the background color for the even-numbered rows in the
# list of polls available. (E.g. 2, 4, 6, 8 ...)
$even_color = "FFFFFF";
# $odd_color is the background color for the odd-numbered rows in the
# list of polls available. (E.g. 1, 3, 5, 7 ...)
$odd_color = "EEEEFF";
# $default_header_color is the background color for the Poll question
$default_header_color = "0000FF";
# $default_font_color is the color of the text for the Poll question
$default_font_color = "FFFFFF";
# $default_poll_area_color is the background color of the main section of
# the poll where the options appear.
$default_poll_area_color = "FFFFFF";
# $default_poll_font_color is the color of the text in the main poll area.
$default_poll_font_color = "000000";
# $default_results_color is the background color of the main results area.
$default_results_color = "FFFFFF";
# $default_results_font_color is the color of the text in the main results area.
$default_results_font_color = "000000";
# $default_results_bar_color is the color of the bars on the results area
$default_results_bar_color = "0000FF";
# $results_bar_style is whether or not you'd like solid or lined bars. Try
# it both ways to see which you prefer. To use solid bars, set
# $results_bar_style = "solid";
# To use lined bars, set
# $results_bar_style = "lined";
$results_bar_style = "solid";
# $default_border_color is the color of the border around the poll
$default_border_color = "000000";
#########################################################################
# #
# END SECTION WHERE YOU NEED TO CHANGE THINGS #
# #
# You should not need to change anything beyond this point, unless #
# you know quite a bit about Perl and are making specific changes #
# to the code. #
# #
#########################################################################
# Let's do some error checking...
# First, this is just so people can't delete stuff on my server with
# the demo. :-)
if($ENV{'SERVER_NAME'} =~ /tesol.net/i ||
$ENV{'SERVER_NAME'} =~ /linguistic-funland.com/i ||
$ENV{'HTTP_HOST'} =~ /linguistic-funland.com/i ||
$ENV{'HTTP_HOST'} =~ /tesol.net/i){
$header .= "
Note: Deleting is disabled in this demo. You can go
through and delete stuff, and it will tell you that it has
successfully deleted the files, but it won't actually do it.
";
}
&check_version;
&debug("Make sure to set \$debugging = \"0\" when the program gets up and running so that you will not see these messages any more.
");
&debug("Perl version is $]");
# Actually, what you see as "number 1" in the list of polls
# is actually "number 0" as far as the script is concerned.
# Therefore, what you THINK is an odd or even number is wrong.
# Things are numbered 0, 1, 2, 3 instead of 1, 2, 3, 4, so this
# will always be a bit off. However, this is really difficult to
# explain sometimes, so we'll just let people tell us what they
# want for odd and even colors above, and we'll switch it here
# so that it works the way they expect.
$even1 = $odd_color; $odd1 = $even_color;
$even_color = $even1; $odd_color = $odd1;
if($ENV{'SERVER_SOFTWARE'} ne ""){
&debug("Your web server is $ENV{'SERVER_SOFTWARE'}.");
}
if($^O ne ""){
&debug("Your operating system is $^O");
if($^O =~ /win/i){
&debug("You appear to be running a Windows-based web server. My
condolences.");
}
}
&config_error();
# If you remove this link, without replacing it with a similar
# HTML comment (as above in the License section) you are in violation
# of the license for this program. So don't take it out unless
# you're in compliance with the license as noted above. :-)
# And honestly, since you didn't have to pay for this, is the link
# really too much to ask? :) If so, there are about a bazillion
# other free scripts out there: just use one of them instead.
# Thanks. :-)
$footer = "
Votesie! v1.1.1 is copyright 1999 Kristina
Pfaff-Harris and can be found at
http://www.tesol.net/scripts/
$footer";
# If no colors were entered, use the default.
if($data{'headercolor'} eq ""){$data{'headercolor'} = "#$default_header_color";}
if($data{'headerfontcolor'} eq ""){$data{'headerfontcolor'} = "#$default_header_font_color";}
if($data{'resultcolor'} eq ""){$data{'resultcolor'} = "#$default_results_color";}
if($data{'resultfontcolor'} eq ""){$data{'resultfontcolor'} = "#$default_results_font_color";}
if($data{'headercolor'} eq ""){$data{'headercolor'} = "#$default_header_color";}
if($data{'headerfontcolor'} eq ""){$data{'headerfontcolor'} = "#$default_font_color";}
if($data{'pollcolor'} eq ""){$data{'pollcolor'} = "#$default_poll_area_color";}
if($data{'pollfontcolor'} eq ""){$data{'pollfontcolor'} = "#$default_poll_font_color";}
if($data{'barcolor'} eq ""){$data{'barcolor'} = "#$default_results_bar_color";}
if($data{'bordercolor'} eq ""){$data{'bordercolor'} = "#$default_border_color";}
if($results_bar_style eq "solid"){
$results_bar_style = " style=\"background-color: $data{'barcolor'}\"";
}
else {
$results_bar_style = "";
}
if($ENV{'QUERY_STRING'} eq "$admin_password"){
$password = $admin_password;
$header = "$header
Admin Main Menu
";
$footer = "
Admin Main Menu
$footer";
&admin_login_screen;
}
elsif($ENV{'QUERY_STRING'} eq "$admin_password" || $data{'password'} eq "$admin_password"){
$password = $admin_password;
$header = "$header
Admin Main Menu
";
$footer = "
Admin Main Menu
$footer";
if($data{'NewPoll'}){ &newpoll; }
elsif($data{'FA'} eq "Del"){ &delete_poll; }
elsif($data{'FA'} eq "DelPollFiles"){ &delete_poll_html_files; }
else{ &admin_login_screen; }
}
elsif($data{'FA'} eq "ShowPoll"){
&show_poll;
}
else {
# The subroutine "write_to_votesie_votes" adds the entry to the votesie_votes.
&write_to_votesie_votes unless $data{'Vote'} eq "";
&show_results unless $data{'ShowResults'} ne "Yes";
$poll_links = &show_poll_links();
print "$header Welcome to the Voting Booth!
The following $number_of_polls polls are available:
Please choose one or go back and
try again.";
&debug("Debugging information follows: ");
foreach $key (keys(%ENV)){
&debug("$key $ENV{$key}");
}
print "
$footer";
exit();
}
sub write_to_votesie_votes {
# First, if dup checking is on, check and see if someone at this
# address has voted already..
if($dup_check =~ /on/i){
$stuffer = &check_dup_voters($data{'Question'});
}
# Okay, now, we're going to open up our question/answer database
# and record the response.
# First, open the file and find the question...
undef $/;
open(FILE, "+<$votesie_votes") ||
&debug("Could not open (votes database) $votesie_votes for writing $!");
if($^O =~ /win/i){
binmode(FILE);
}
else {
flock(FILE, 2) || &debug("Oops, could not lock $votesie_votes $!");
}
$contents = ;
@contents = split(/\n/, $contents);
seek(FILE, 0, 0);
if($stuffer != 1){
# If not, then we want to look through each line to find the question that
# is being voted on so we can add the new result.
foreach $content (@contents){
$content =~ s/\n//g;
if($content =~ /^\Q$data{'Question'}\E/){
($question,@answers) = split(/\|/, $content);
$line_to_print .= "$question|";
foreach $answer (@answers){
($resp,$numresp) = split(/%%/, $answer);
$numresp =~ s/\s//g;
$resp =~ s/\s+$//;
if($resp =~ /\Q$data{'Vote'}\E/){
$numresp = $numresp + 1;
}
$line_to_print .= "$resp %% $numresp|" if $resp ne "";
}
print FILE "$line_to_print\n";
$line_to_print = "";
}
else {
print FILE "$content\n";
}
}
close(FILE);
} # end if ...
$/ = "\n";
}
sub show_results {
if($stuffer == 1){
$stuffermsg = "Looks like you may have already voted. Vote not counted.";
}
open(FILE, "$votesie_votes") ||
&debug("Ack! I can't read the votesie_votes file! $!");
@contents = ;
GETCON: foreach $con (@contents){
if($con =~ /^\Q$data{'Question'}\E/){
$line = $con; last GETCON;
}
}
close(FILE);
$line =~ s/\n//;
($question,@answers) = split(/\|/, $line);
print "$stuffermsg
|
Results:$question
| ";
pop(@answers) if $answers[$#answers] eq "";
foreach $answer (@answers){
($resp,$numresp) = split(/%%/, $answer);
$numresp =~ s/\s//g;
$totalvotes = $totalvotes + $numresp;
}
foreach $answer (@answers){
($resp,$numresp) = split(/%%/, $answer);
$numresp =~ s/\s//g;
if($totalvotes > 0){
$percent = int((($numresp / $totalvotes) * 100) + 0.5);
}
else {
$percent = 0;
}
$totalpercent = $totalpercent + $percent;
if($totalpercent > 100){
$howmuchover = $totalpercent - 100;
$percent = $percent - $howmuchover;
$totalpercent = 100;
}
if($answer eq $answers[$#answers] && $totalpercent < 100){
$howmuchover = 100 - $totalpercent;
$percent = $percent + $howmuchover;
$totalpercent = 100;
}
print "
| $resp
| ";
for($i = 1; $i <= $percent; $i++){
print "|" unless $ENV{'HTTP_USER_AGENT'} =~ /lynx/i;
}
print " |
$numresp / $percent % | ";
}
print "
$totalvotes votes total: $totalpercent %
Powered by
Votesie!
|
| |
Back...";
exit();
}
sub debug {
if($debugging =~ /yes/i || $debugging == 1){
print "DEBUGGING INFO: $_[0]
\n";
}
}
sub get_data {
local($string);
# get data
if ($ENV{'REQUEST_METHOD'} eq 'GET') {
$string = $ENV{'QUERY_STRING'};
}
else { read(STDIN, $string, $ENV{'CONTENT_LENGTH'}); }
# split data into name=value pairs
@data = split(/&/, $string);
# split into name=value pairs in associative array
foreach (@data) {
split(/=/, $_);
$_[0] =~ s/\+/ /g; # plus to space
$_[0] =~ s/%00//g; # We don' need no steenking nulls :)
$_[0] =~ s/%0a/newline/g;
$_[0] =~ s/%(..)/pack("c", hex($1))/ge; # hex to alphanumeric
if(defined($data{$_[0]})){
$data{$_[0]} .= "\0";
$data{$_[0]} .= "$_[1]";
}
else {
$data{"$_[0]"} = $_[1];
}
}
# translate special characters
foreach (keys %data) {
$data{"$_"} =~ s/\+/ /g; # plus to space
$data{"$_"} =~ s/%00//g; # We don' need no steenking nulls :)
$data{"$_"} =~ s/%0a/newline/g;
$data{"$_"} =~ s/%(..)/pack("c", hex($1))/ge; # hex to alphanumeric
}
%data; # return associative array of name=value
}
sub admin_login_screen {
my $poll_links = &show_poll_links("admin");
print "$header
Welcome admin!
";
print <