Voting Tool
authorPhilipp Dunkel <Philipp Dunkel@d4452222-2f33-11de-9270-010000000000>
Thu, 21 May 2009 11:20:15 +0000 (11:20 +0000)
committerPhilipp Dunkel <Philipp Dunkel@d4452222-2f33-11de-9270-010000000000>
Thu, 21 May 2009 11:20:15 +0000 (11:20 +0000)
git-svn-id: http://svn.cacert.cl/Software/Voting/vote@34 d4452222-2f33-11de-9270-010000000000

database.php [new file with mode: 0644]
denied.php [new file with mode: 0644]
index.php [new file with mode: 0644]
motion.php [new file with mode: 0644]
motions.php [new file with mode: 0644]
proxy.php [new file with mode: 0644]
styles.css [new file with mode: 0644]
vote.php [new file with mode: 0644]

diff --git a/database.php b/database.php
new file mode 100644 (file)
index 0000000..be20eb0
--- /dev/null
@@ -0,0 +1,82 @@
+<?php
+       $board = "cacert-board@lists.cacert.org";
+       class DB {
+               function __construct() {
+                       $this->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 = <<<BODY
+Dear Board,
+
+The motion with the identifier $tag has been $state.
+
+Motion:
+    $title
+    $content
+
+Votes:
+       Quorum: $quorum
+       Majority: $majority%
+       
+       Ayes: $ayes
+       Nayes: $nayes
+       Abstentions: $abstains
+       
+       Percentage: $percent%
+       
+Kind regards,
+the voting system.
+
+BODY;
+                                       mail($board,"Re: ".$decision['tag']." - ".$decision['title'],$body);
+                               }
+                       }
+               }
+       }
+?>
\ No newline at end of file
diff --git a/denied.php b/denied.php
new file mode 100644 (file)
index 0000000..9bb72d6
--- /dev/null
@@ -0,0 +1,12 @@
+<html>
+       <head>
+               <title>CAcert Board Decisions</title>
+               <meta http-equiv="Content-Type" content="text/html; charset='UTF-8'" />
+               <link rel="stylesheet" type="text/css" href="styles.css" />
+       </head>
+       <body>
+               <b>You are not authorized to act here!</b><br/>
+               <i>If you think this is in error, please contact the administrator</i>
+               <i>If you don't know who that is, it is definitely not an error ;)</i>
+       </body>
+</html>
\ No newline at end of file
diff --git a/index.php b/index.php
new file mode 100644 (file)
index 0000000..3363496
--- /dev/null
+++ b/index.php
@@ -0,0 +1,5 @@
+<?php
+       header("HTTP/1.0 301 Redirect");
+       header("Location: motions.php");
+       exit();
+?>
\ No newline at end of file
diff --git a/motion.php b/motion.php
new file mode 100644 (file)
index 0000000..515e25c
--- /dev/null
@@ -0,0 +1,211 @@
+<?php
+       if ($_SERVER['HTTPS'] != 'on') {
+               header("HTTP/1.0 302 Redirect");
+               header("Location: https://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']);
+               exit();
+       }
+       $user = $_SERVER['REMOTE_USER'];
+       require_once("database.php");
+       $db = new DB();
+       $stmt = $db->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('/&/',"&amp;",$string);
+               $string = preg_replace('/</',"&lt;",$string);
+               $string = preg_replace('/>/',"&gt;",$string);
+               echo $string;
+       }
+?>
+<html>
+       <head>
+               <title>CAcert Board Decisions</title>
+               <meta http-equiv="Content-Type" content="text/html; charset='UTF-8'" />
+               <link rel="stylesheet" type="text/css" href="styles.css" />
+       </head>
+       <body>
+               <?php
+               if ($_REQUEST['action'] == "store") {
+                       if (is_numeric($_REQUEST['motion'])) {
+                               $stmt = $db->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()) {
+                                       ?>
+                                       <b>The motion has been proposed!</b><br/>
+                                       <a href="motions.php">Back to motions</a><br/>
+                                       <br/>
+                                       <br/>
+                                       <?php
+                                       $decision = $db->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 = <<<BODY
+Dear Board,
+
+$name has modified motion $tag to the following:
+
+$title
+$content
+
+To pass a minimum of $quorum votes and a $majority% acceptance will be required.
+Voting will close $due.
+
+To vote please choose:
+
+Aye: $voteurl&vote=1
+Naye: $voteurl&vote=-1
+Abstain: $voteurl&vote=0
+
+Please be aware, that if you have voted already your votr is still registered and valid.
+If this modification has an impact on how you wish to vote, you are responsible for voting
+again.
+
+Kind regards,
+the voting system
+BODY;
+                                       mail($board,"Re: $tag - $title",$body);
+                               } else {
+                                       ?>
+                                       <b>The motion has NOT been proposed!</b><br/>
+                                       <a href="motions.php">Back to motions</a><br/>
+                                       <i><?php echo join("<br/>\n",$stmt->errorInfo()); ?></i><br/>
+                                       <br/>
+                                       <br/>
+                                       <?php
+                               }
+                       } else {
+                               $stmt = $db->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();
+                                       ?>
+                                       <b>The motion has been proposed!</b><br/>
+                                       <a href="motions.php">Back to motions</a><br/>
+                                       <br/>
+                                       <br/>
+                                       <?php
+                                       $decision = $db->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 = <<<BODY
+Dear Board,
+
+$name has made the following motion:
+
+$title
+$content
+
+To pass a minimum of $quorum votes and a $majority% acceptance will be required.
+Voting will close $due.
+
+To vote please choose:
+
+Aye: $voteurl&vote=1
+Naye: $voteurl&vote=-1
+Abstain: $voteurl&vote=0
+
+Kind regards,
+the voting system
+BODY;
+                                       mail($board,"$tag - $title",$body);
+                               } else {
+                                       ?>
+                                       <b>The motion has NOT been proposed!</b><br/>
+                                       <a href="motions.php">Back to motions</a><br/>
+                                       <i><?php echo join("<br/>\n",$stmt->errorInfo()); ?></i><br/>
+                                       <br/>
+                                       <br/>
+                                       <?php
+                               }
+                       }
+                       
+               }
+               if (is_numeric($_REQUEST['motion'])) {
+                       $stmt = $db->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'];
+               }
+               ?>
+               <form <?php if (is_numeric($_REQUEST['motion'])) { echo(" action=\"?\""); } ?> method="POST">
+                       <input type="hidden" name="action" value="store" />
+                       <?php
+                               if (is_numeric($_REQUEST['motion'])) {
+                                       ?><input type="hidden" name="motion" value="<?php echo($_REQUEST["motion"]); ?>" /><?php
+                               }
+                       ?>
+               <table>
+                       <tr><td>ID:</td><td><?php htmlesc($motion['tag']); ?></td></tr>
+                       <tr><td>Proponent:</td><td><?php htmlesc($motion['proposer']); ?><input type="hidden" name="proponent" value="<?php htmlesc($user['id']); ?>"></td></tr>
+                       <tr><td>Proposed:</td><td><?php htmlesc($motion['proposed']); ?> UTC</td></tr>
+                       <tr><td>Title:</td><td><input name="title" value="<?php htmlesc($motion['title'])?>"></td></tr>
+                       <tr><td>Text:</td><td><textarea name="content"><?php htmlesc($motion['content'])?></textarea></td></tr>
+                       <tr><td>Quorum:</td><td><select name="quorum">
+                               <option value="<?php echo(ceil($stats["voters"])); ?>" <?php if($motion['quorum'] == $stats["voters"]) { echo(" selected=\"selected\""); } ?>>100% Votes (<?php echo($stats["voters"]); ?>)</option>
+                               <option value="<?php echo(ceil($stats["voters"] / 2)); ?>" <?php if($motion['quorum'] == ceil($stats["voters"] / 2)) { echo(" selected=\"selected\""); } ?>>50% Votes (<?php echo(ceil($stats["voters"] / 2)); ?>)</option>
+                               <option value="2" <?php if($motion['quorum'] == 2) { echo(" selected=\"selected\""); } ?>>2 Votes</option>
+                               <option value="1" <?php if($motion['quorum'] == 1) { echo(" selected=\"selected\""); } ?>>1 Vote</option>
+                       </select></td></tr>
+                       <tr><td>Majority:</td><td><select name="majority">
+                               <option value="50" <?php if($motion['majority'] == 50) { echo(" selected=\"selected\""); } ?>>50%</option>
+                               <option value="67" <?php if($motion['majority'] == 67) { echo(" selected=\"selected\""); } ?>>67%</option>
+                               <option value="75" <?php if($motion['majority'] == 75) { echo(" selected=\"selected\""); } ?>>75%</option>
+                               <option value="100" <?php if($motion['majority'] == 100) { echo(" selected=\"selected\""); } ?>>100%</option>
+                       </td></tr>
+                       <tr><td rowspan="2">Due:</td><td><?php echo($motion['due'])?> UTC</td></tr>
+                       <tr><td><select name="due">
+                               <option value="+3 days">In 3 Days</option>
+                               <option value="+7 days">In 1 Week</option>
+                               <option value="+14 days">In 2 Weeks</option>
+                       </select></td></tr>
+                       <tr><td>&nbsp;</td><td><input type="submit" value="Propose" /></td></tr>
+               </table>
+               </form>
+               <br/>
+               <a href="motions.php">Back to motions</a>               
+       </body>
+</html>
diff --git a/motions.php b/motions.php
new file mode 100644 (file)
index 0000000..27d1632
--- /dev/null
@@ -0,0 +1,83 @@
+<?php
+       require_once("database.php");
+       $db = new DB();
+       $db->closeVotes();
+       $page = is_numeric($_REQUEST['page'])?$_REQUEST['page']:1;
+?>
+<html>
+       <head>
+               <title>CAcert Board Decisions</title>
+               <meta http-equiv="Content-Type" content="text/html; charset='UTF-8'" />
+               <link rel="stylesheet" type="text/css" href="styles.css" />
+       </head>
+       <body>
+               <table class="list">
+                       <tr>
+                               <th>Status</th>
+                               <th>Motion</th>
+                               <th>Actions</th>
+                       </tr>
+                       <?php
+                               $stmt = $db->getStatement("list decisions");
+                               $stmt->execute(array($page));
+                               $items = 0;
+                               while ($row = $stmt->fetch()) {
+                                       $items++;
+                                       ?><tr>
+                                               <td class="<?php switch($row['status']) { case 0: echo "pending"; break; case 1: echo "approved"; break; case -1: echo "declined"; break; }?>">
+                                               <?php 
+                                                       switch($row['status']) { 
+                                                               case 0: echo "Pending<br/><i>".$row['due']." UTC</i>"; break; 
+                                                               case 1: echo "Approved<br/><i>".$row['modified']." UTC</i>"; break; 
+                                                               case -1: echo "Declined<br/><i>".$row['modified']." UTC</i>"; break; 
+                                                       }
+                                               ?>
+                                               </td>
+                                               <td>
+                                               <i><?php echo $row['tag'] ?></i><br/>
+                                               <b><?php echo $row['title']; ?></b><br/>
+                                               <pre><?php echo $row['content']; ?></pre>
+                                               <br/>
+                                               <i>Due: <?php echo($row['due']); ?> UTC</i><br/>
+                                               <i>Proposed: <?php echo($row['proposer']); ?> (<?php echo($row['proposed']); ?> UTC)</i><br/>
+                                               <i>Required Votes: <?php echo($row['quorum']); ?></i><br/>
+                                               <i>Majority: <?php echo($row['majority']); ?>%</i><br/>
+                                               <i>Aye|Naye|Abstain: <?php echo($row['ayes']); ?>|<?php echo($row['nayes']); ?>|<?php echo($row['abstains']); ?></i><br/>
+                                               </td><?php
+                                       ?><td class="actions">
+                                               <?php
+                                                       if ($row['status'] == 0) {
+                                                               ?>
+                                                               <ul>
+                                                                       <li><a href="vote.php?motion=<?php echo($row['id']); ?>&amp;vote=1">Aye</a></li>
+                                                                       <li><a href="vote.php?motion=<?php echo($row['id']); ?>&amp;vote=0">Abstain</a></li>
+                                                                       <li><a href="vote.php?motion=<?php echo($row['id']); ?>&amp;vote=-1">Naye</a></li>
+                                                                       <li><a href="proxy.php?motion=<?php echo($row['id']); ?>">Proxy Vote</a></li>
+                                                                       <li><a href="motion.php?motion=<?php echo($row['id']); ?>">Modify</a></li>
+                                                               </ul>
+                                                               <?php
+                                                       } else {
+                                                               ?>
+                                                               &nbsp;
+                                                               <?php
+                                                       }
+                                               ?>
+                                       </td>
+                                       </tr><?php
+                               }
+                       ?>
+                       <tr>
+                               <td colspan="2" class="navigation">
+                                       <?php if ($page>1) { ?><a href="?page=<?php echo($page-1); ?>">&lt;</a><?php } else { ?>&nbsp;<?php } ?>
+                                               &nbsp;
+                                       <?php if ($items>9) { ?><a href="?page=<?php echo($page+1); ?>">&gt;</a><?php } else { ?>&nbsp;<?php } ?>
+                               </td>
+                               <td class="actions">
+                                       <ul>
+                                               <li><a href="motion.php">New Motion</a></li>
+                                       </ul>
+                               </td>
+                       </tr>
+               </table>
+       </body>
+</html>
diff --git a/proxy.php b/proxy.php
new file mode 100644 (file)
index 0000000..77bcc89
--- /dev/null
+++ b/proxy.php
@@ -0,0 +1,157 @@
+<?php
+       if ($_SERVER['HTTPS'] != 'on') {
+               header("HTTP/1.0 302 Redirect");
+               header("Location: https://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']);
+               exit();
+       }
+       $user = $_SERVER['REMOTE_USER'];
+       require_once("database.php");
+       $db = new DB();
+       $stmt = $db->getStatement("get voter");
+       $stmt->execute(array($user));
+       if (!($user = $stmt->fetch())) {
+               header("HTTP/1.0 302 Redirect");
+               header("Location: denied.php");
+               exit();
+       }
+?>
+<html>
+       <head>
+               <title>CAcert Board Decisions</title>
+               <meta http-equiv="Content-Type" content="text/html; charset='UTF-8'" />
+               <link rel="stylesheet" type="text/css" href="styles.css" />
+       </head>
+       <body>
+<?php
+       if (!is_numeric($_REQUEST['motion'])) {
+?>
+               <b>This is not a valid motion!</b><br/>
+               <a href="motions.php">Back to motions</a><br/>
+<?php
+       } else {
+               $stmt = $db->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()) {
+                                               ?>
+                                                       <b>The vote has been registered.</b><br/>
+                                                       <a href="motions.php">Back to motions</a>
+                                               <?php
+                                               $stmt = $db->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 = <<<BODY
+Dear Board,
+
+$name has just registered a proxy vote of $vote for $voter on motion $tag.
+
+The justification for this was:
+$justification
+
+Motion:
+$title
+$content
+
+Kind regards,
+the vote system
+
+BODY;
+                                               mail($board,"Re: $tag - $title",$body);
+                                       } else {
+                                               ?>
+                                               <b>The vote has NOT been registered.</b><br/>
+                                               <a href="motions.php">Back to motions</a>
+                                               <i><?php echo join("<br/>\n",$stmt->errorInfo()); ?></i>
+                                               <?php
+                                       }
+                               } else {
+                                       ?>
+                                       <b>The vote has NOT been registered.</b><br/>
+                                       <a href="motions.php">Back to motions</a>
+                                       <i><?php echo join("<br/>\n",$stmt->errorInfo()); ?></i>
+                                       <?php
+                               }
+                       } else {
+                       $stmt = $db->getStatement("get voters");
+                       if ($stmt->execute() && ($voters = $stmt->fetchAll())) {
+?>
+                       <form method="POST" action="?motion=<?php echo($_REQUEST['motion']); ?>">
+                       <table>
+                               <tr>
+                                       <th>Voter</th><th>Vote</th>
+                               </tr>
+                               <tr>
+                                       <td><select name="voter"><?php
+                                       foreach ($voters as $voter) {
+?>
+                                               <option value="<?php echo($voter['id']); ?>"<?php if ($voter['id'] == $_POST['voter']) { echo(" selected=\"selected\""); } ?>><?php echo($voter['name']); ?></option>
+<?php
+                                       }
+                                       ?></select></td>
+                                       <td><select name="vote">
+                                               <option value="1"<?php if (1 == $_POST['voter']) { echo(" selected=\"selected\""); } ?>>Aye</option>
+                                               <option value="0"<?php if (0 == $_POST['voter']) { echo(" selected=\"selected\""); } ?>>Abstain</option>
+                                               <option value="-1"<?php if (-1 == $_POST['voter']) { echo(" selected=\"selected\""); } ?>>Naye</option>
+                                       </select></td>
+                               </tr>
+                               <tr>
+                                       <th colspan="2">Justification:</th>
+                               </tr>
+                               <tr>
+                                       <td colspan="2"><textarea name="justification"><?php echo($_POST['justification']); ?></textarea></td>
+                               </tr>
+                               <tr>
+                                       <td colspan="2"><input type="submit" value="Proxy Vote" /></td>
+                               </tr>
+                       </table>
+                       </form>
+<?php
+                       } else {
+?>
+                               <b>Could not retrieve voters!</b><br/>
+                               <a href="motions.php">Back to motions</a><br/>
+                               <i><?php echo join("<br/>\n",$stmt->errorInfo()); ?></i>
+<?php
+                       }
+               }
+?>
+                       
+<?php
+               } else {
+?>
+                       <b>This is not a valid motion!</b><br/>
+                       <a href="motions.php">Back to motions</a><br/>
+                       <i><?php echo join("<br/>\n",$stmt->errorInfo()); ?></i>
+<?php  
+               }
+       }
+?>
+       </body>
+</html>
diff --git a/styles.css b/styles.css
new file mode 100644 (file)
index 0000000..0610148
--- /dev/null
@@ -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 (file)
index 0000000..b357cf1
--- /dev/null
+++ b/vote.php
@@ -0,0 +1,107 @@
+<?php
+       if ($_SERVER['HTTPS'] != 'on') {
+               header("HTTP/1.0 302 Redirect");
+               header("Location: https://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']);
+               exit();
+       }
+       $user = $_SERVER['REMOTE_USER'];
+       require_once("database.php");
+       $db = new DB();
+       $stmt = $db->getStatement("get voter");
+       $stmt->execute(array($user));
+       if (!($user = $stmt->fetch())) {
+               header("HTTP/1.0 302 Redirect");
+               header("Location: denied.php");
+               exit();
+       }
+?>
+<html>
+       <head>
+               <title>CAcert Board Decisions</title>
+               <meta http-equiv="Content-Type" content="text/html; charset='UTF-8'" />
+               <link rel="stylesheet" type="text/css" href="styles.css" />
+       </head>
+       <body>
+               <?php
+                       if (is_numeric($_REQUEST['motion']) && is_numeric($_REQUEST['vote'])) {
+                               $stmt = $db->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()) {
+                                                               ?>
+                                                                       <b>Your vote has been registered.</b><br/>
+                                                                       <a href="motions.php">Back to motions</a>
+                                                               <?php
+                                                               $name = $user['name'];
+                                                               $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 = <<<BODY
+Dear Board,
+
+$name has just voted $vote on motion $tag.
+
+Motion:
+    $title
+    $content
+
+Kind regards,
+the vote system
+
+BODY;
+                                                               mail($board,"Re: $tag - $title",$body);
+                                                       } else {
+                                                               ?>
+                                                               <b>Your vote has NOT been registered.</b><br/>
+                                                               <a href="motions.php">Back to motions</a>
+                                                               <i><?php echo join("<br/>\n",$stmt->errorInfo()); ?></i>
+                                                               <?php
+                                                       }
+                                               } else {
+                                                       ?>
+                                                       <b>Your vote has NOT been registered.</b><br/>
+                                                       <a href="motions.php">Back to motions</a>
+                                                       <i><?php echo join("<br/>\n",$stmt->errorInfo()); ?></i>
+                                                       <?php
+                                               }
+                                       } else {
+                                               ?>
+                                               <b>Your vote has NOT been registered.</b><br/>
+                                               <b>Voting is alread closed!</b><br/>
+                                               <a href="motions.php">Back to motions</a>
+                                               <?php
+                                       }
+                               } else {
+                                       ?>
+                                       <b>Your vote has NOT been registered.</b><br/>
+                                       <b>Could not find the motion to be voted!</b><br/>
+                                       <a href="motions.php">Back to motions</a>
+                                       <?php
+                               }
+                       } else {
+                               ?>
+                               <b>This call is not a valid vote!</b><br/>
+                               <a href="motions.php">Back to motions</a>
+                               <?php
+                       }
+               ?>
+       </body>
+</html>
\ No newline at end of file