<?php
// ActionPoll V1.1.1
// Author: robert ladstaetter <hide@address.com>
// This software is licensed under GPL, see the www.fsf.org
// for details or read gpl.txt distributed with this package.
// It would be nice however to inform me if you use the script
// and find it useful.
// IMPORTANT: change config.php to fit paths etc. with your configuration!
include("./config.php");
//
//include($CONFIG_POLLDB);
// ------------------------- begin of configuration -----------------------
// IMPORTANT: if you use the dbPoll you don't need to include following file:
include($CONFIG_TEXTCONFIG);
// ----------------------------------------------------------------------
// ------------------------- end of configuration -----------------------
// ----------------------------------------------------------------------
// class Actionpoll combines behaviour common to all polls
// Implementation notice: all methods with "_" are internal methods
class ActionPoll {
var $polldata;
var $pollSummaryText;
var $pollTitle;
var $pollDenyMessage;
var $pollInternalTitle;
var $pollStartValue;
var $pollMaxValue;
var $totalVotes;
var $performAction;
var $pollConfig;
var $caller;
var $performIPBan;
var $pollTimeGap;
// ---------------------------------------------------------------------
// function getDebugHTML
//
// $config ... a PollData() object
//
// constructor; sets necessary values
function ActionPoll ($config) {
global $CONFIG_TEXTCONFIG; //weired PHP
$this->polldata = $config->polldata;
$this->pollSummaryText = $config->pollSummaryText;
$this->pollTitle = $config->pollTitle;
$this->pollDenyMessage = $config->pollDenyMessage;
$this->pollInternalTitle = $config->pollInternalTitle;
$this->totalVotes = $this->calcTotalVotes_();
$this->performAction = $config->performAction;
$this->pollStartValue = $config->pollStartValue;
$this->pollMaxValue = $config->pollMaxValue;
$this->pollTimeGap = $config->pollTimeGap;
$this->pollConfig = $CONFIG_TEXTCONFIG;
$this->caller = gethostbyaddr(getenv("REMOTE_ADDR"));
$this->performIPBan = $config->performIPBan;
}
// ---------------------------------------------------------------------
// function getDebugHTML
//
// debugging function, prints out variables in HTML code
function getDebugHTML() {
return sprintf("<table>".
"<tr><td>polldata</td><td>%s</td></tr>" .
"<tr><td>pollSummaryText</td><td>%s</td></tr>" .
"<tr><td>pollTitle</td><td>%s</td></tr>" .
"<tr><td>pollDenyMessage</td><td>%s</td></tr>" .
"<tr><td>pollInternalTitle</td><td>%s</td></tr>" .
"<tr><td>pollStartValue</td><td>%s</td></tr>" .
"<tr><td>pollMaxValue</td><td>%s</td></tr>" .
"<tr><td>totalVotes</td><td>%s</td></tr>" .
"<tr><td>performAction</td><td>%s</td></tr>" .
"<tr><td>pollConfig</td><td>%s</td></tr>" .
"<tr><td>caller</td><td>%s</td></tr>" .
"<tr><td>performIPBan</td><td>%s</td></tr>" .
"<tr><td>pollTimeGap</td><td>%s</td></tr></table>",
$this->polldata,
$this->pollSummaryText,
$this->pollTitle,
$this->pollDenyMessage,
$this->pollInternalTitle,
$this->pollStartValue,
$this->pollMaxValue,
$this->totalVotes,
$this->performAction,
$this->pollConfig,
$this->caller,
$this->performIPBan,
$this->pollTimeGap);
}
// ---------------------------------------------------------------------
// function process($vote)
//
// $vote ... integer which indicates the number of the chosen option in
// the poll
//
// heart of actionpoll, here it is decided what to do
function process($vote) {
if (!($vote < 0 || $vote >= count($this->polldata) )) {
if(!($this->increaseVoteIfAllowed_($vote))) {
printf("<center>" . $this->pollDenyMessage . "</center>");
}
$this->totalVotes = $this->calcTotalVotes_(); // we have a new vote now
if ($this->isMaxReached_($vote) && $this->performAction) {
print($this->getMaxReachedMessage_());
$this->maxReachedAction_($vote);
$this->resetPoll_();
} else {
print($this->getShowHTMLMessage());
}
$this->writePoll_($vote);
} else {
print("<p>Wrong Value of Parameter!</p>");
}
}
// ---------------------------------------------------------------------
// function increaseVoteIfAllowed_($vote)
//
// $vote ... integer which indicates the number of the chosen option in
// the poll
//
// checks whether or not the voter has voted before and
// increases counter if not. if voted before, it returns false, else true
function increaseVoteIfAllowed_($vote) {
if (!($this->votedBefore_($vote))) {
$this->polldata[$vote]["counter"]++;
array_push($this->polldata[$vote]["ips"],$this->caller);
array_push($this->polldata[$vote]["timestamp"],time());
return true;
} else {
return false;
}
}
// ---------------------------------------------------------------------
// function getLastVoteTime($ips,$timestamp,$maxtime,$caller)
//
// $ips ...
// $timestamp ...
// $maxtime ...
// $caller ...
//
// checks whether or not voter has voted before and
// increases counter if not. if voted before, it simply does nothing.
// gives back timestamp of last vote of this host
// -1 if there was no vote before
function getLastVoteTime($ips,$timestamp,$maxtime,$caller) {
for ($i=0;$i<count($ips);$i++) {
if ($ips[$i] == $caller) {
if ($maxtime < $timestamp[$i]) {
$maxtime = $timestamp[$i];
}
}
}
return $maxtime;
}
// ---------------------------------------------------------------------
// function votedBefore_($vote)
//
// $vote ... integer which indicates the number of the chosen option in
// the poll
//
// returns true if there was a vote before
// false if the caller is allowed to vote (very logic :( )
function votedBefore_($vote) {
$lastVotedTime = -1;
if ($this->performIPBan) {
for ($i=0; $i<count($this->polldata);$i++) {
$lastVotedTime = $this->getLastVoteTime(
$this->polldata[$i]["ips"],
$this->polldata[$i]["timestamp"],
$lastVotedTime,
$this->caller);
}
if ($lastVotedTime != -1) {
$timeGap = time() - $lastVotedTime;
//printf("<b>debug: time: %s, timegap: %s, lastvisittime: %s</b>",
// time(),$timeGap, $lastVotedTime);
if ($timeGap < $this->pollTimeGap) {
return true;
} else {
return false;
}
}
} else {
return false; // do not check for allowed votes
}
}
// ---------------------------------------------------------------------
// function calcTotalVotes_()
//
// calculates the sum of votes for every option
function calcTotalVotes_() {
$tmpCountVotes = 0;
for ($i=0;$i<count($this->polldata); $i++) {
$tmpCountVotes += $this->polldata[$i]["counter"];
}
return $tmpCountVotes;
}
// ---------------------------------------------------------------------
// function resetPoll_()
//
// sets internal poll state to the default values
function resetPoll_() {
for ($i=0; $i<count($this->polldata); $i++) {
$this->polldata[$i]["counter"] = $this->pollStartValue;
$this->polldata[$i]["ips"] = array("");
$this->polldata[$i]["timestamp"] = array("");
}
}
// ---------------------------------------------------------------------
// function maxReachedAction_()
//
// override this function in subclass - this function gets called if
// a certain number of votes is reached for one option
function maxReachedAction_() {
print("<h1>ActionPoll::maxReachedAction_: IMPLEMENT ME!!!!!!!!!!!</h1>");
}
// ---------------------------------------------------------------------
// function maxReachedAction_()
//
// $vote ... integer which indicates the number of the chosen option in
// the poll
//
// returns true if the number of polls is greater than the allowed
// number which is specified in pollMaxValue
function isMaxReached_($vote) {
return $this->polldata[$vote]["counter"] >= $this->pollMaxValue;
}
// ---------------------------------------------------------------------
// function generateConfigFile_()
//
// returns a string which describes the actual state of the poll
// in PHP Code.
function generateConfigFile_() {
$cfgData = "<?php\n// This is a generated file by actionpoll V1.2.0\n".
"class PollData { \n var \$polldata = array (\n";
for ($i = 0; $i < count($this->polldata); $i++) {
$cfgData .= sprintf("\t\tarray(\n\t\t\t\"item\" => \"%s\",\n".
"\t\t\t\"counter\" => %s,\n" .
"\t\t\t\"ips\" => array(\"%s\"),\n".
"\t\t\t\"timestamp\" => array(\"%s\")\n\t\t),\n",
$this->polldata[$i]["item"],
$this->polldata[$i]["counter"],
implode("\",\"",$this->polldata[$i]["ips"]),
implode("\",\"",$this->polldata[$i]["timestamp"]));
}
$cfgData = substr($cfgData,0,-2);
$cfgData = $cfgData . ");\n";
$cfgData = sprintf("%s var \$pollSummaryText = \"%s\";\n".
" var \$pollTitle = \"%s\";\n" .
" var \$pollDenyMessage = \"%s\";\n" .
" var \$pollInternalTitle = \"%s\";\n" .
" var \$pollStartValue = %d;\n" .
" var \$pollMaxValue = %d;\n".
" var \$pollTimeGap = %d;\n".
" var \$performAction = %s;\n".
" var \$performIPBan = %s;\n}\n?>\n",
$cfgData,
$this->pollSummaryText,
$this->pollTitle,
$this->pollDenyMessage,
$this->pollInternalTitle,
$this->pollStartValue,
$this->pollMaxValue,
$this->pollTimeGap,
$this->performAction,
$this->performIPBan);
return $cfgData;
}
// ---------------------------------------------------------------------
// function writePoll_($vote)
//
// $vote ... integer which indicates the number of the chosen option in
// the poll
//
// writes state of poll to harddisc (synchronized)
function writePoll_($vote) {
$cfgFile = fopen($this->pollConfig,"w");
flock($cfgFile,2); // aquire exclusive writer lock
fwrite($cfgFile,$this->generateConfigFile_());
flock($cfgFile,3); // release lock
fclose($cfgFile);
}
// ---------------------------------------------------------------------
// In PHP there exists no possibility to force the user to implement
// certain methods in the subclass, thats why the following
// stubs are here.
// ---------------------------------------------------------------------
function getVoteHTMLMessage() {
return "<h1>ActionPoll::getVoteHTMLMessage()</h1><p>This function gets called when.</p>\n";
}
function getShowHTMLMessage() {
return "<h1>ActionPoll::getVoteHTMLMessage()</h1>" .
"<p>This function should be implemented to return a HTML formatted form (see for example HTMLActionpoll).</p>\n";
}
function getMaxReachedMessage_() {
return "<h1>ActionPoll::getMaxReachedMessage()</h1>" .
"<p>Returns a string which should be displayed when an action takes place.</p>\n";
}
function maxReachedAction_() {
print("<h1>ActionPoll::getmaxReachedAction_()</h1>" .
"<p>Fill this function with the PHP commands which are called when a action takes place.</p>\n");
}
}
// -----------------------------------------------------------------------
// Following class implements an example poll.
// -----------------------------------------------------------------------
// class HTMLActionPoll for dealing with HTML output
class HTMLActionPoll extends ActionPoll {
var $messageMaxReached;
var $pollVoteButtonDescription;
var $pollImage;
var $pollImageHeight;
var $pollImageScale;
function HTMLActionPoll($polldata) {
global $CONFIG_PIXEL;
global $CONFIG_IMAGEHEIGHT;
global $CONFIG_IMAGESCALE;
$this->ActionPoll($polldata);
$this->messageMaxReached = "Message which should be displayed at max!";
$this->pollVoteButtonDescription = "vote!";
$this->pollImage = $CONFIG_PIXEL;
$this->pollImageHeight = $CONFIG_IMAGEHEIGHT;
$this->pollImageScale = $CONFIG_IMAGESCALE;
}
// HTML Input Form which calls again script
function getVoteHTMLMessage() {
global $PHP_SELF; // unhide PHP_SELF
$voteHTMLMessage = sprintf("<form action=\"%s\">\n",$PHP_SELF);
$voteHTMLMessage .= sprintf("<table class=\"pollTable\" align=\"center\">\n");
$voteHTMLMessage .= sprintf("<tr><td colspan=\"4\" class=\"pollTitle\">%s</td></tr>\n",
$this->pollTitle);
for ($i=0;$i<count($this->polldata); $i++) {
$percent = ($this->totalVotes != 0)?
(100 / $this->totalVotes * $this->polldata[$i]["counter"]):
0;
$voteHTMLMessage .= sprintf(" <tr> \n".
" <td class=\"pollItem\">%s</td>\n".
" <td class=\"pollOption\"><input type=radio name=\"%s\"".
" value=\"%d\"></td>\n" .
" </tr>\n",
$this->polldata[$i]["item"],
$this->pollInternalTitle,
$i);
}
$voteHTMLMessage .= sprintf(" <tr>\n" .
" <td class=\"pollSummary\" colspan=\"4\"><input type=\"submit\"".
"value=\"%s\"></td>" .
" </tr>\n</table>\n</form>\n",
$this->pollVoteButtonDescription);
return $voteHTMLMessage;
}
function getShowHTMLMessage() {
$showPollStr = "<table class=\"pollTable\" align=center>\n";
$showPollStr .= sprintf("<tr><td colspan=\"4\" class=\"pollTitle\">%s</td></tr>\n",
$this->pollTitle);
for ($i=0;$i<count($this->polldata); $i++) {
$percent = ($this->totalVotes != 0)?
(100 / $this->totalVotes * $this->polldata[$i]["counter"]):
0;
$showPollStr .= sprintf(" <tr> \n".
" <td class=\"pollItem\">%s</td>\n".
" <td class=\"pollImage\"><img src=\"%s\" width=%d height=%d></td>\n".
" <td class=\"pollPercent\">%d %s</td>\n".
" <td class=\"pollVotes\">%d</td>\n".
" </tr>\n",
$this->polldata[$i]["item"],
$this->pollImage,
round($percent*$this->pollImageScale),
$this->pollImageHeight,
round($percent),
"Prozent",
$this->polldata[$i]["counter"]);
}
$showPollStr .= sprintf(" <tr>\n".
" <td class=\"pollSummary\" colspan=\"4\">%s %s</td>\n" .
" </tr>\n",
$this->pollSummaryText,
$this->totalVotes);
$showPollStr .= "</table>\n";
return $showPollStr;
}
function getMaxReachedMessage_() {
$mesgMaxReached = sprintf("<table class=\"maxReachedTable\" align=center>\n".
"<tr>\n".
" <td class=\"maxReachedMessage\">%s</td>\n" .
"</tr>\n</table>\n",
$this->messageMaxReached);
return $mesgMaxReached;
}
function maxReachedAction_($vote) {
// insert here whatever you want to do when maxpoll is
// reached, for example send an email or pop up a window
// or something else
}
}
class DBHTMLActionPoll extends HTMLActionPoll {
var $dbPoll;
function DBHTMLActionPoll($dbPoll) {
$this->dbPoll = $dbPoll;
$this->HTMLActionPoll($dbPoll);
}
// we have to overwrite the writePoll_ Method, since now
// there is a convenient way to update our counter in the
// database and to add the ip information via sql.
function writePoll_($vote) {
$this->dbPoll->riseCounter($vote);
$this->dbPoll->writeIP($vote,$this->caller);
}
}
// -----------------------------------------------------------------------
// -----------------------------------------------------------------------
// --------------------- end of class definitions ------------------------
// -----------------------------------------------------------------------
?>