commit 99ee0407525ab98e56479f183af573c3a3451a69 Author: Philipp Dunkel Date: Thu May 21 11:20:15 2009 +0000 Voting Tool git-svn-id: http://svn.cacert.cl/Software/Voting/vote@34 d4452222-2f33-11de-9270-010000000000 diff --git a/database.php b/database.php new file mode 100644 index 0000000..be20eb0 --- /dev/null +++ b/database.php @@ -0,0 +1,82 @@ +dbh = new PDO("sqlite:".dirname(__FILE__)."/database.sqlite"); + $this->statement = array(); + $this->statement['list decisions'] = $this->dbh->prepare("SELECT decisions.id, decisions.tag, voters.name AS proposer, decisions.proposed, decisions.title, decisions.content, decisions.quorum, decisions.majority, decisions.status, decisions.due, decisions.modified, (SELECT COUNT(*) FROM votes WHERE decision=decisions.id AND vote=1) AS ayes, (SELECT COUNT(*) FROM votes WHERE decision=decisions.id AND vote=-1) AS nayes, (SELECT COUNT(*) FROM votes WHERE decision=decisions.id AND vote=0) AS abstains FROM decisions, voters WHERE decisions.proponent=voters.id ORDER BY proposed DESC LIMIT 10 OFFSET 10 * (:page - 1);"); + $this->statement['closed decisions'] = $this->dbh->prepare("SELECT decisions.id, decisions.tag, voters.name AS proposer, decisions.proposed, decisions.title, decisions.content, decisions.quorum, decisions.majority, decisions.status, decisions.due, decisions.modified, (SELECT COUNT(*) FROM votes WHERE decision=decisions.id AND vote=1) AS ayes, (SELECT COUNT(*) FROM votes WHERE decision=decisions.id AND vote=-1) AS nayes, (SELECT COUNT(*) FROM votes WHERE decision=decisions.id AND vote=0) AS abstains FROM decisions, voters WHERE decisions.proponent=voters.id AND decisions.status=0 AND datetime('now','utc') > datetime(due);"); + $this->statement['get decision'] = $this->dbh->prepare("SELECT decisions.id, decisions.tag, decisions.proponent, voters.name AS proposer, decisions.proposed, decisions.title, decisions.content, decisions.quorum, decisions.majority, decisions.status, decisions.due, decisions.modified, (SELECT COUNT(*) FROM votes WHERE decision=decisions.id AND vote=1) AS ayes, (SELECT COUNT(*) FROM votes WHERE decision=decisions.id AND vote=-1) AS nayes, (SELECT COUNT(*) FROM votes WHERE decision=decisions.id AND vote=0) AS abstains FROM decisions, voters WHERE decisions.proponent=voters.id AND decisions.id=:decision;"); + $this->statement['get new decision'] = $this->dbh->prepare("SELECT decisions.id, decisions.tag, decisions.proponent, voters.name AS proposer, decisions.proposed, decisions.title, decisions.content, decisions.quorum, decisions.majority, decisions.status, decisions.due, decisions.modified, (SELECT COUNT(*) FROM votes WHERE decision=decisions.id AND vote=1) AS ayes, (SELECT COUNT(*) FROM votes WHERE decision=decisions.id AND vote=-1) AS nayes, (SELECT COUNT(*) FROM votes WHERE decision=decisions.id AND vote=0) AS abstains FROM decisions, voters WHERE decisions.proponent=voters.id AND decisions.id=last_insert_rowid();"); + $this->statement['get voter'] = $this->dbh->prepare("SELECT voters.id, voters.name FROM voters, emails WHERE voters.id=emails.voter AND emails.address=? AND voters.enabled=1"); + $this->statement['get voter by id'] = $this->dbh->prepare("SELECT voters.id, voters.name FROM voters WHERE id=:id;"); + $this->statement['get voters'] = $this->dbh->prepare("SELECT voters.id, voters.name FROM voters WHERE voters.enabled=1 ORDER BY name ASC;"); + $this->statement['del vote'] = $this->dbh->prepare("DELETE FROM votes WHERE decision=:decision AND voter=:voter;"); + $this->statement['do vote'] = $this->dbh->prepare("INSERT INTO votes (decision, voter, vote, voted, notes) VALUES (:decision, :voter, :vote, datetime('now','utc'), :notes);"); + $this->statement['stats'] = $this->dbh->prepare("SELECT (SELECT COUNT(*) FROM voters WHERE enabled=1) AS voters;"); + $this->statement['create decision'] = $this->dbh->prepare("INSERT INTO decisions (proposed, proponent, title, content, quorum, majority, status, due, modified) VALUES (datetime('now','utc'), :proponent, :title, :content, :quorum, :majority, 0, datetime('now','utc', :due), datetime('now','utc'));"); + $this->statement['post create'] = $this->dbh->prepare(" UPDATE decisions SET tag='m' || strftime('%Y%m%d','now') || '.' || id WHERE id=last_insert_rowid();"); + $this->statement['update decision'] = $this->dbh->prepare("UPDATE decisions SET proposed=datetime('now','utc'), proponent=:proponent, title=:title, content=:content, quorum=:quorum, majority=:majority, status=0, due=datetime('now','utc',:due), modified=datetime('now','utc') WHERE id=:id;"); + $this->statement['close decision'] = $this->dbh->prepare("UPDATE decisions SET status=:status, modified=datetime('now','utc') WHERE id=:decision"); + } + function getStatement($name) { + return $this->statement[$name]; + } + function closeVotes() { + $stmt = $this->getStatement("closed decisions"); + $upd = $this->getStatement("close decision"); + if ($stmt->execute()) { + while ($decision = $stmt->fetch()) { + $votes = $decision['ayes'] + $decision['nayes'] + $decision['abstains']; + if ($votes < $decision['quorum']) { + $decision['status'] = -1; + } else { + $votes = $decision['ayes'] + $decision['nayes']; + if (($decision['ayes'] / $votes) >= ($decision['majority'] / 100)) { + $decision['status'] = 1; + } else { + $decision['status'] = -1; + } + } + $upd->bindParam(":decision",$decision['id']); + $upd->bindParam(":status",$decision['status']); + $upd->execute(); + $state = $decision['status']==1?"accepted":"declined"; + $tag = $decision['tag']; + $title = $decision['title']; + $content = $decision['content']; + $quorum = $decision['quorum']; + $majority = $decision['majority']; + $ayes = $decision['ayes']; + $nayes = $decision['nayes']; + $abstains = $decision['abstains']; + $percent = $decision['ayes'] * 100 / $decision['ayes']+$decision['nayes']; + $body = << \ No newline at end of file diff --git a/denied.php b/denied.php new file mode 100644 index 0000000..9bb72d6 --- /dev/null +++ b/denied.php @@ -0,0 +1,12 @@ + + + CAcert Board Decisions + + + + + You are not authorized to act here!
+ If you think this is in error, please contact the administrator + If you don't know who that is, it is definitely not an error ;) + + \ No newline at end of file diff --git a/index.php b/index.php new file mode 100644 index 0000000..3363496 --- /dev/null +++ b/index.php @@ -0,0 +1,5 @@ + \ No newline at end of file diff --git a/motion.php b/motion.php new file mode 100644 index 0000000..515e25c --- /dev/null +++ b/motion.php @@ -0,0 +1,211 @@ +getStatement("get voter"); + $stmt->execute(array($user)); + if (!($user = $stmt->fetch())) { + header("HTTP/1.0 302 Redirect"); + header("Location: denied.php"); + exit(); + } + $db->getStatement("stats")->execute(); + $stats = $db->getStatement("stats")->fetch(); + function htmlesc($string) { + $string = preg_replace('/&/',"&",$string); + $string = preg_replace('//',">",$string); + echo $string; + } +?> + + + CAcert Board Decisions + + + + + getStatement("update decision"); + $stmt->bindParam(":id",$_POST['motion']); + $stmt->bindParam(":proponent",$_POST['proponent']); + $stmt->bindParam(":title",$_POST['title']); + $stmt->bindParam(":content",$_POST['content']); + $stmt->bindParam(":quorum",$_POST['quorum']); + $stmt->bindParam(":majority",$_POST['majority']); + $stmt->bindParam(":due",$_POST['due']); + if ($stmt->execute()) { + ?> + The motion has been proposed!
+ Back to motions
+
+
+ getStatement("get decision")->execute(array($_POST['motion']))?$db->getStatement("get decision")->fetch():array(); + $name = $user['name']; + $tag = $decision['tag']; + $title = $decision['title']; + $content =$decision['content']; + $due = $decision['due']." UTC"; + $quorum = $decision['quorum']; + $majority = $decision['majority']; + $voteurl = "https://".$_SERVER['HTTP_HOST'].":".$_SERVER['SERVER_PORT'].preg_replace('/motion\.php/','vote.php',$_SERVER['REQUEST_URI'])."?motion=".$decision['id']; + $body = << + The motion has NOT been proposed!
+ Back to motions
+ \n",$stmt->errorInfo()); ?>
+
+
+ getStatement("create decision"); + $stmt->bindParam(":proponent",$_POST['proponent']); + $stmt->bindParam(":title",$_POST['title']); + $stmt->bindParam(":content",$_POST['content']); + $stmt->bindParam(":quorum",$_POST['quorum']); + $stmt->bindParam(":majority",$_POST['majority']); + $stmt->bindParam(":due",$_POST['due']); + if ($stmt->execute()) { + $db->getStatement("post create")->execute(); + ?> + The motion has been proposed!
+ Back to motions
+
+
+ getStatement("get new decision")->execute()?$db->getStatement("get new decision")->fetch():array(); + $name = $user['name']; + $tag = $decision['tag']; + $title = $decision['title']; + $content =$decision['content']; + $due = $decision['due']." UTC"; + $quorum = $decision['quorum']; + $majority = $decision['majority']; + $voteurl = "https://".$_SERVER['HTTP_HOST'].":".$_SERVER['SERVER_PORT'].preg_replace('/motion\.php/','vote.php',$_SERVER['REQUEST_URI'])."?motion=".$decision['id']; + $body = << + The motion has NOT been proposed!
+ Back to motions
+ \n",$stmt->errorInfo()); ?>
+
+
+ getStatement("get decision"); + if ($stmt->execute(array($_REQUEST['motion']))) { + $motion = $stmt->fetch(); + } + if (!is_numeric($motion['id'])) { + $motion = array(); + foreach (array("title","content","quorum","majority") as $column) { + $motion[$column] = ""; + } + $motion["proponent"] = $user['id']; + $motion["proposer"] = $user['name']; + } + } else { + $motion = array(); + foreach (array("title","content","quorum","majority") as $column) { + $motion[$column] = ""; + } + $motion["proponent"] = $user['id']; + $motion["proposer"] = $user['name']; + } + ?> +
method="POST"> + + " /> + + + + + + + + + + + +
ID:
Proponent:
Proposed: UTC
Title:
Text:
Quorum:
Majority:
Due: UTC
 
+
+
+ Back to motions + + diff --git a/motions.php b/motions.php new file mode 100644 index 0000000..27d1632 --- /dev/null +++ b/motions.php @@ -0,0 +1,83 @@ +closeVotes(); + $page = is_numeric($_REQUEST['page'])?$_REQUEST['page']:1; +?> + + + CAcert Board Decisions + + + + + + + + + + + getStatement("list decisions"); + $stmt->execute(array($page)); + $items = 0; + while ($row = $stmt->fetch()) { + $items++; + ?> + + + + + + + +
StatusMotionActions
"> + ".$row['due']." UTC"; break; + case 1: echo "Approved
".$row['modified']." UTC"; break; + case -1: echo "Declined
".$row['modified']." UTC"; break; + } + ?> +
+
+
+
+
+ Due: UTC
+ Proposed: ( UTC)
+ Required Votes:
+ Majority: %
+ Aye|Naye|Abstain: ||
+
+ + + +   + +
+ +
+ + diff --git a/proxy.php b/proxy.php new file mode 100644 index 0000000..77bcc89 --- /dev/null +++ b/proxy.php @@ -0,0 +1,157 @@ +getStatement("get voter"); + $stmt->execute(array($user)); + if (!($user = $stmt->fetch())) { + header("HTTP/1.0 302 Redirect"); + header("Location: denied.php"); + exit(); + } +?> + + + CAcert Board Decisions + + + + + + This is not a valid motion!
+ Back to motions
+getStatement("get decision"); + $stmt->bindParam(":decision",$_REQUEST['motion']); + if ($stmt->execute() && ($decision=$stmt->fetch()) && ($decision['status'] == 0)) { + if (is_numeric($_POST['voter']) && is_numeric($_POST['vote']) && is_numeric($_REQUEST['motion']) && ($_POST['justification'] != "")) { + $stmt = $db->getStatement("del vote"); + $stmt->bindParam(":voter",$_REQUEST['voter']); + $stmt->bindParam(":decision",$_REQUEST['motion']); + if ($stmt->execute()) { + $stmt = $db->getStatement("do vote"); + $stmt->bindParam(":voter",$_REQUEST['voter']); + $stmt->bindParam(":decision",$_REQUEST['motion']); + $stmt->bindParam(":vote",$_REQUEST['vote']); + $notes = "Proxy-Vote by ".$user['name']."\n\n".$_REQUEST['justification']."\n\n".$_SERVER['SSL_CLIENT_CERT']; + $stmt->bindParam(":notes",$notes); + if ($stmt->execute()) { + ?> + The vote has been registered.
+ Back to motions + getStatement("get voter by id"); + $stmt->bindParam(":id",$_REQUEST['voter']); + if ($stmt->execute() && ($voter=$stmt->fetch())) { + $voter = $voter['name']; + } else { + $voter = "Voter: ".$_REQUEST['voter']; + } + $name = $user['name']; + $justification = $_REQUEST['justification']; + $vote = ''; + switch($_REQUEST['vote']) { + case 1 : $vote='Aye'; break; + case -1: $vote='Naye'; break; + default: $vote='Abstain'; break; + } + $tag = $decision['tag']; + $title = $decision['title']; + $content = $decision['content']; + $due = $decision['due']." UTC"; + $body = << + The vote has NOT been registered.
+ Back to motions + \n",$stmt->errorInfo()); ?> + + The vote has NOT been registered.
+ Back to motions + \n",$stmt->errorInfo()); ?> + getStatement("get voters"); + if ($stmt->execute() && ($voters = $stmt->fetchAll())) { +?> +
+ + + + + + + + + + + + + + + + + +
VoterVote
Justification:
+
+ + Could not retrieve voters!
+ Back to motions
+ \n",$stmt->errorInfo()); ?> + + + + This is not a valid motion!
+ Back to motions
+ \n",$stmt->errorInfo()); ?> + + + diff --git a/styles.css b/styles.css new file mode 100644 index 0000000..0610148 --- /dev/null +++ b/styles.css @@ -0,0 +1,28 @@ +html, body, th, td { + font-family: Verdana, Arial, Sans-Serif; + font-size:10px; +} +table, tr, td, th { + vertical-align:top; + border:1px solid black; + border-collapse: collapse; +} +td.navigation { + text-align:center; +} +td.approved { + color:green; +} +td.declined { + color:red; +} +td.pending { + color:blue; +} +textarea { + width:400px; + height:150px; +} +input { + width:400px; +} diff --git a/vote.php b/vote.php new file mode 100644 index 0000000..b357cf1 --- /dev/null +++ b/vote.php @@ -0,0 +1,107 @@ +getStatement("get voter"); + $stmt->execute(array($user)); + if (!($user = $stmt->fetch())) { + header("HTTP/1.0 302 Redirect"); + header("Location: denied.php"); + exit(); + } +?> + + + CAcert Board Decisions + + + + + getStatement("get decision"); + $stmt->bindParam(":decision",$_REQUEST['motion']); + if ($stmt->execute() && ($decision=$stmt->fetch())) { + if ($decision['status'] == 0) { + $stmt = $db->getStatement("del vote"); + $stmt->bindParam(":voter",$user['id']); + $stmt->bindParam(":decision",$_REQUEST['motion']); + if ($stmt->execute()) { + $stmt = $db->getStatement("do vote"); + $stmt->bindParam(":voter",$user['id']); + $stmt->bindParam(":decision",$_REQUEST['motion']); + $stmt->bindParam(":vote",$_REQUEST['vote']); + $notes="Direct Vote\n\n".$_SERVER['SSL_CLIENT_CERT']; + $stmt->bindParam(":notes",$notes); + if ($stmt->execute()) { + ?> + Your vote has been registered.
+ Back to motions + + Your vote has NOT been registered.
+ Back to motions + \n",$stmt->errorInfo()); ?> + + Your vote has NOT been registered.
+ Back to motions + \n",$stmt->errorInfo()); ?> + + Your vote has NOT been registered.
+ Voting is alread closed!
+ Back to motions + + Your vote has NOT been registered.
+ Could not find the motion to be voted!
+ Back to motions + + This call is not a valid vote!
+ Back to motions + + + \ No newline at end of file