| @@ -0,0 +1,13 @@ | |||
| FROM docker.io/bravecheng/php-nginx-sqlite:latest | |||
| USER nobody | |||
| RUN mkdir -p /var/www/html/inc/config | |||
| RUN chown nobody:nobody /var/www/html/inc/config | |||
| VOLUME /var/www/html/inc/config | |||
| USER root | |||
| WORKDIR /var/www | |||
| COPY cli cli | |||
| COPY web html | |||
| USER nobody | |||
| @@ -39,15 +39,17 @@ select | |||
| MIN(username) as `username`, | |||
| group_concat(proxy.voting_id) as `proxies`, | |||
| MIN(upstream_proxy.delegate_id) as `delegate`, | |||
| md5(coalesce(MIN(email), "")) as `gravatar_hash` | |||
| coalesce(MIN(email), "") as `gravatar_email` | |||
| from members | |||
| left join proxy on (members.voting_id=proxy.delegate_id) | |||
| left join proxy as upstream_proxy on (upstream_proxy.voting_id=members.voting_id) | |||
| where members.voting_id is not null | |||
| group by members.voting_id | |||
| UNION | |||
| select skymanager_id, voting_id, name, username, NULL as `proxies`, NULL as `delegate`, md5(coalesce(email, "")) as `gravatar_hash` | |||
| select skymanager_id, voting_id, name, username, NULL as `proxies`, NULL as `delegate`, coalesce(email, "") as `gravatar_email` | |||
| from members where members.voting_id is null'); | |||
| get_gravatar_assoc($voters); | |||
| ?> | |||
| <script type="text/javascript"> | |||
| var voters = <?= json_encode($voters); ?>; | |||
| @@ -28,7 +28,7 @@ if (!empty($_POST['ballot']) && !empty($_POST['candidate'])) { | |||
| if (empty($error)) { | |||
| $result = $db->query("INSERT INTO votes (candidate_id, position, member_id, vote_type, submitter_id) SELECT $candidate_selected, \"$ballot\", $voter_selected, 'IN PERSON', $voter_selected UNION SELECT $candidate_selected, \"$ballot\", voting_id, 'PROXY IN PERSON', delegate_id from proxy where delegate_id=$voter_selected"); | |||
| $candidate = $db->fetchRow('select skymanager_id, name, username, md5(coalesce(email, "")) as `gravatar_hash` from members where skymanager_id=' . $candidate_selected); | |||
| $candidate = $db->fetchRow('select skymanager_id, name, username, coalesce(email, "") as `gravatar_email` from members where skymanager_id=' . $candidate_selected); | |||
| if ($result) { | |||
| $proxy_votes = $db->fetchAssoc("SELECT member_id, submitter_id from votes where submitter_id=$voter_selected and position=\"$ballot\""); | |||
| @@ -57,8 +57,11 @@ $header->setAttribute('title', 'Michigan Flyers'); | |||
| $header->setAttribute('tagline', 'Election Poll Worker Tools'); | |||
| $header->output(); | |||
| $candidates = $db->fetchAssoc('select skymanager_id, name, username, md5(coalesce(email, "")) as `gravatar_hash` from members where voting_id is not null'); | |||
| $voters = $db->fetchAssoc('select MIN(skymanager_id) as `skymanager_id`, MIN(members.voting_id) as `voting_id`, MIN(name) as `name`, MIN(username) as `username`, group_concat(proxy.voting_id) as `proxies`, MIN(upstream_proxy.delegate_id) as `delegate`, md5(coalesce(MIN(email), "")) as `gravatar_hash` from members left join proxy on (members.voting_id=proxy.delegate_id) left join proxy as upstream_proxy on (upstream_proxy.voting_id=members.voting_id) where members.voting_id is not null group by members.voting_id UNION select skymanager_id, voting_id, name, username, NULL as `proxies`, NULL as `delegate`, md5(coalesce(email, "")) as `gravatar_hash` from members where members.voting_id is null'); | |||
| $candidates = $db->fetchAssoc('select skymanager_id, name, username, coalesce(email, "") as `gravatar_email` from members where voting_id is not null'); | |||
| $voters = $db->fetchAssoc('select MIN(skymanager_id) as `skymanager_id`, MIN(members.voting_id) as `voting_id`, MIN(name) as `name`, MIN(username) as `username`, group_concat(proxy.voting_id) as `proxies`, MIN(upstream_proxy.delegate_id) as `delegate`, coalesce(MIN(email), "") as `gravatar_email` from members left join proxy on (members.voting_id=proxy.delegate_id) left join proxy as upstream_proxy on (upstream_proxy.voting_id=members.voting_id) where members.voting_id is not null group by members.voting_id UNION select skymanager_id, voting_id, name, username, NULL as `proxies`, NULL as `delegate`, coalesce(email, "") as `gravatar_email` from members where members.voting_id is null'); | |||
| get_gravatar_assoc($candidates); | |||
| get_gravatar_assoc($voters); | |||
| ?> | |||
| <script type="text/javascript"> | |||
| var voters = <?= json_encode($voters); ?>; | |||
| @@ -134,7 +137,7 @@ var candidates = <?= json_encode($candidates); ?>; | |||
| <h4 class="section-heading">Candidate</h4> | |||
| <div id="vote-profile" class="candidate"> | |||
| <div class="profile-icon"> | |||
| <img src="https://www.gravatar.com/avatar/<?= $candidate['gravatar_hash']; ?>.png?d=mp&s=64" /> | |||
| <img src="https://www.gravatar.com/avatar/<?= md5($candidate['gravatar_email']); ?>.png?d=mp&s=64" /> | |||
| </div> | |||
| <div class="profile"> | |||
| <h2 class="profile-name"><?= $candidate['name']; ?></h2> | |||
| @@ -25,7 +25,7 @@ function loadPositions() { | |||
| function loadVoters() { | |||
| global $db; | |||
| return $db->fetchAssoc(' | |||
| $voters = $db->fetchAssoc(' | |||
| select | |||
| MIN(skymanager_id) as `skymanager_id`, | |||
| MIN(members.voting_id) as `voting_id`, | |||
| @@ -33,15 +33,18 @@ function loadVoters() { | |||
| MIN(username) as `username`, | |||
| group_concat(proxy.voting_id) as `proxies`, | |||
| MIN(upstream_proxy.delegate_id) as `delegate`, | |||
| md5(coalesce(MIN(email), "")) as `gravatar_hash` | |||
| coalesce(MIN(email), "") as `gravatar_email` | |||
| from members | |||
| left join proxy on (members.voting_id=proxy.delegate_id) | |||
| left join proxy as upstream_proxy on (upstream_proxy.voting_id=members.voting_id) | |||
| where members.voting_id is not null | |||
| group by members.voting_id | |||
| UNION | |||
| select skymanager_id, voting_id, name, username, NULL as `proxies`, NULL as `delegate`, md5(coalesce(email, "")) as `gravatar_hash` | |||
| select skymanager_id, voting_id, name, username, NULL as `proxies`, NULL as `delegate`, coalesce(email, "") as `gravatar_email` | |||
| from members where members.voting_id is null'); | |||
| get_gravatar_assoc($voters); | |||
| return $voters; | |||
| } | |||
| $result = null; | |||
| @@ -60,34 +63,42 @@ if (!empty($_POST['create'])) { | |||
| $error = "Created position " . htmlspecialchars($desc); | |||
| } | |||
| } else if (!empty($_POST['setActive']) || !empty($_POST['deactivate'])) { | |||
| $positions = loadPositions(); | |||
| $position = $_POST['ballot']; | |||
| if (!array_key_exists($position, $positions)) $error = "That position does not exist"; | |||
| if (!empty($_POST['deactivate'])) | |||
| $position=''; | |||
| if (empty($error)) { | |||
| $result = $db->query('UPDATE positions set active=(position="' . $db->sanitize($position) . '")'); | |||
| if ($result === false) | |||
| $error = "Failed to set active position"; | |||
| else if (empty($position)) | |||
| $error = "Deactivated voting form"; | |||
| else | |||
| $error = "Set " . htmlspecialchars($positions[$_POST['ballot']]['label']) . " as active."; | |||
| if (!array_key_exists('ballot', $_POST)) { | |||
| $error = "No position selected"; | |||
| } else { | |||
| $positions = loadPositions(); | |||
| $position = $_POST['ballot']; | |||
| if (!array_key_exists($position, $positions)) $error = "That position does not exist"; | |||
| if (!empty($_POST['deactivate'])) | |||
| $position=''; | |||
| if (empty($error)) { | |||
| $result = $db->query('UPDATE positions set active=(position="' . $db->sanitize($position) . '")'); | |||
| if ($result === false) | |||
| $error = "Failed to set active position"; | |||
| else if (empty($position)) | |||
| $error = "Deactivated voting form"; | |||
| else | |||
| $error = "Set " . htmlspecialchars($positions[$_POST['ballot']]['label']) . " as active."; | |||
| } | |||
| } | |||
| } else if (!empty($_POST['remove'])) { | |||
| $positions = loadPositions(); | |||
| if (!array_key_exists($_POST['ballot'], $positions)) $error = "That position does not exist"; | |||
| if (empty($error)) { | |||
| $result = $db->query('DELETE FROM positions WHERE position="' . $db->sanitize($_POST['ballot']) . '"'); | |||
| if ($result === false) | |||
| $error = "Failed to remove position"; | |||
| else | |||
| $error = "Removed " . htmlspecialchars($positions[$_POST['ballot']]['label']) . " and discarded cast ballots."; | |||
| if (!array_key_exists('ballot', $_POST)) { | |||
| $error = "No position selected"; | |||
| } else { | |||
| $positions = loadPositions(); | |||
| if (!array_key_exists($_POST['ballot'], $positions)) $error = "That position does not exist"; | |||
| if (empty($error)) { | |||
| $result = $db->query('DELETE FROM positions WHERE position="' . $db->sanitize($_POST['ballot']) . '"'); | |||
| if ($result === false) | |||
| $error = "Failed to remove position"; | |||
| else | |||
| $error = "Removed " . htmlspecialchars($positions[$_POST['ballot']]['label']) . " and discarded cast ballots."; | |||
| } | |||
| } | |||
| } else if (!empty($_POST['force'])) { | |||
| $voters = loadVoters(); | |||
| @@ -11,24 +11,41 @@ if (!empty($config)) { | |||
| require_once(BASE . '/inc/db.php'); | |||
| require_once(BASE . '/inc/user.php'); | |||
| $required = ['db-host', 'db-username', 'db-password', 'db-database', 'flyers-user', 'flyers-password']; | |||
| $fieldNames = ['db-type', 'db-host', 'db-username', 'db-password', 'db-database', 'flyers-user', 'flyers-password']; | |||
| function test_config($params) { | |||
| global $required, $db, $user; | |||
| global $fieldNames, $db, $user; | |||
| if (!empty($params) && count($params) != count($required)) | |||
| return "All fields are required"; | |||
| mysqli_report(MYSQLI_REPORT_OFF); | |||
| $mysql = mysqli_connect($params['db-host'], $params['db-username'], $params['db-password']); | |||
| if (!$mysql) | |||
| return "Unable to connect to the database."; | |||
| $config = [ | |||
| "type" => $params['db-type'] | |||
| ]; | |||
| mysqli_select_db($mysql, $params['db-database']); | |||
| if (mysqli_error($mysql)) | |||
| return "Unable to access database '" . htmlspecialchars($params['db-database']) . "': " . mysqli_error($mysql); | |||
| if (empty($params['flyers-user']) || empty($params['flyers-password'])) | |||
| return "All fields are required"; | |||
| mysqli_multi_query($mysql, " | |||
| switch ($params['db-type']) { | |||
| case "mysql": | |||
| if (!empty($params) && count($params) != count($fieldNames)) | |||
| return "All fields are required"; | |||
| $config += [ | |||
| 'host' => $params['db-host'], | |||
| 'user' => $params['db-username'], | |||
| 'pass' => $params['db-password'], | |||
| 'db' => $params['db-database'] | |||
| ]; | |||
| $db = MysqlDb::Connect($config->host, $config->user, $config->pass, $config->db); | |||
| break; | |||
| case "sqlite": | |||
| $db = SqliteDb::Connect(); | |||
| break; | |||
| default: | |||
| return "Invalid Database Type"; | |||
| } | |||
| $success = $db->exec_multi(" | |||
| CREATE TABLE IF NOT EXISTS `members` ( | |||
| `skymanager_id` integer NOT NULL PRIMARY KEY, | |||
| `name` varchar(128) NOT NULL, | |||
| @@ -53,43 +70,36 @@ CREATE TABLE IF NOT EXISTS `votes` ( | |||
| `candidate_id` integer NOT NULL, | |||
| `position` varchar(64) NOT NULL, | |||
| `member_id` integer NOT NULL, | |||
| `vote_type` enum('IN PERSON','ONLINE','PROXY IN PERSON','PROXY ONLINE','UNANIMOUS') NOT NULL DEFAULT 'ONLINE', | |||
| -- `vote_type` enum('IN PERSON','ONLINE','PROXY IN PERSON','PROXY ONLINE','UNANIMOUS') NOT NULL DEFAULT 'ONLINE', | |||
| `vote_type` varchar(24) NOT NULL DEFAULT 'ONLINE', | |||
| `submitted_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, | |||
| `submitter_id` integer NOT NULL, | |||
| PRIMARY KEY (`position`,`member_id`), | |||
| FOREIGN KEY (`position`) REFERENCES `positions` (`position`) ON DELETE CASCADE) | |||
| "); | |||
| if (!$success) | |||
| return "Failed to set up database schema: " . $db->getError(); | |||
| do { | |||
| if (mysqli_error($mysql)) | |||
| return "Unable to set up tables: " . mysqli_error($mysql); | |||
| } while (mysqli_next_result($mysql) || mysqli_error($mysql)); | |||
| $db = DBHandler::wrap($mysql); | |||
| $success = $user->login($params['flyers-user'], $params['flyers-password']); | |||
| if (!$success) | |||
| return "Login Failed"; | |||
| $db->query("UPDATE members SET `pollworker`=TRUE where skymanager_id=" . ((int) $user->getUserId())); | |||
| if ($db->getError()) | |||
| return "Failed to update user permissions"; | |||
| if ($err = $db->getError()) | |||
| return "Failed to update user permissions: $err"; | |||
| $conf = json_encode([ | |||
| 'host' => $params['db-host'], | |||
| 'user' => $params['db-username'], | |||
| 'pass' => $params['db-password'], | |||
| 'db' => $params['db-database'] | |||
| ], JSON_PRETTY_PRINT); | |||
| $conf = ""; | |||
| $conf = json_encode($config, JSON_PRETTY_PRINT); | |||
| if (file_put_contents(BASE . "/inc/config.json", $conf) === false) | |||
| if (file_put_contents(BASE . "/inc/config/config.json", $conf) === false) | |||
| return "Failed to write configuration."; | |||
| return false; | |||
| } | |||
| $params = []; | |||
| foreach ($required as $field) { | |||
| foreach ($fieldNames as $field) { | |||
| if (array_key_exists($field, $_POST) && !empty($_POST[$field])) | |||
| $params[$field] = $_POST[$field]; | |||
| } | |||
| @@ -110,6 +120,19 @@ if ($error === false) { | |||
| <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" /> | |||
| <link rel="stylesheet" type="text/css" href="https://fonts.googleapis.com/css2?family=Fira+Sans:wght@400;600;800&display=swap" /> | |||
| <link rel="stylesheet" type="text/css" href="/styles/style.css" /> | |||
| <style type="text/css"> | |||
| form input#db-sqlite:checked~.form-row label[for="db-sqlite"] .radio-button-label, | |||
| form input#db-mysql:checked~.form-row label[for="db-mysql"] .radio-button-label { | |||
| background-color: #000; | |||
| color: #fff; | |||
| border: 2px solid #fff; | |||
| box-shadow: 0px 0px 0px 2px #000; | |||
| } | |||
| form .form-row.conditional { display: none; } | |||
| form input#db-mysql:checked~.form-row.mysql { display: block; } | |||
| </style> | |||
| </head> | |||
| <body> | |||
| <div id="container"> | |||
| @@ -122,20 +145,36 @@ if ($error === false) { | |||
| <?php if(!empty($error)) echo "<span class=\"errormessage\">$error</span>"; ?> | |||
| <form action="configure.php" method="POST"> | |||
| <div class="form-section"> | |||
| <input type="radio" id="db-sqlite" name="db-type" value="sqlite" checked /> | |||
| <input type="radio" id="db-mysql" name="db-type" value="mysql" /> | |||
| <h3>Database Setup</h3> | |||
| <div class="form-row"> | |||
| <div class="selector"> | |||
| <label class="radio" for="db-sqlite"> | |||
| <span class="radio-button-label">SQLite</span> | |||
| </label> | |||
| <label class="radio" for="db-mysql"> | |||
| <span class="radio-button-label">MySQL</span> | |||
| </label> | |||
| </div> | |||
| </div> | |||
| <div class="form-row conditional mysql"> | |||
| <label for="db-host">Host</label> | |||
| <input type="text" id="db-host" name="db-host" value="localhost" /> | |||
| </div> | |||
| <div class="form-row"> | |||
| <div class="form-row conditional mysql"> | |||
| <label for="db-host">Host</label> | |||
| <input type="text" id="db-host" name="db-host" value="localhost" /> | |||
| </div> | |||
| <div class="form-row conditional mysql"> | |||
| <label for="db-database">Database Name</label> | |||
| <input type="text" id="db-database" name="db-database" /> | |||
| </div> | |||
| <div class="form-row"> | |||
| <div class="form-row conditional mysql"> | |||
| <label for="db-username">Username</label> | |||
| <input type="text" id="db-username" name="db-username" /> | |||
| </div> | |||
| <div class="form-row"> | |||
| <div class="form-row conditional mysql"> | |||
| <label for="db-password">Password</label> | |||
| <input type="password" id="db-password" name="db-password" /> | |||
| </div> | |||
| @@ -1,22 +1,20 @@ | |||
| <?php | |||
| class DBHandler{ | |||
| class MysqlDb { | |||
| private $mysql; | |||
| private function __construct() {} | |||
| public static function Connect($hostname, $username, $password, $database){ | |||
| $handler = new DBHandler(); | |||
| $handler = new MysqlDb(); | |||
| mysqli_report(MYSQLI_REPORT_OFF); | |||
| $handler->mysql = mysqli_connect($hostname, $username, $password); | |||
| if(!$handler->mysql) die("MySql error: " . mysql_error()); | |||
| if(!$handler->mysql) return false; | |||
| mysqli_select_db($handler->mysql, $database); | |||
| return $handler; | |||
| } | |||
| if (mysqli_error($handler->mysql)) | |||
| return false; | |||
| public static function Wrap($mysql) { | |||
| $handler = new DBHandler(); | |||
| $handler->mysql = $mysql; | |||
| return $handler; | |||
| } | |||
| @@ -32,6 +30,45 @@ class DBHandler{ | |||
| } | |||
| } | |||
| public function insert($table, $fields, $values_assoc, $ignore = false) { | |||
| $field_list = implode(",", $fields); | |||
| $values_arr = []; | |||
| foreach ($values_assoc as $value) { | |||
| $value_arr = []; | |||
| foreach ($value as $v) { | |||
| if ($this->verifyInteger($v)) | |||
| $value_arr[] = $v; | |||
| else if ($v === "NULL") | |||
| $value_arr[] = "NULL"; | |||
| else | |||
| $value_arr[] = "\"{$this->sanitize($v)}\""; | |||
| } | |||
| $values_arr[] = "(" . implode(',', $value_arr) . ")"; | |||
| } | |||
| $values_list = implode(',', $values_arr); | |||
| $ignore_str = ''; | |||
| if ($ignore) | |||
| $ignore_str = 'IGNORE'; | |||
| return $this->query("INSERT $ignore_str INTO $table ($field_list) VALUES $values_list"); | |||
| } | |||
| public function exec_multi($query){ | |||
| try { | |||
| $res = mysqli_multi_query($this->mysql, $query); | |||
| do { | |||
| if ($err = $this->getError()) | |||
| return false; | |||
| } while (mysqli_next_result($this->mysqli) || $this->getError()); | |||
| return true; | |||
| } catch (Throwable $err) { | |||
| return false; | |||
| } | |||
| } | |||
| public function fetchRow($query){ | |||
| $result = $this->query($query); | |||
| if($result === false || $result === true) die(mysqli_error($this->mysql));//return $result; | |||
| @@ -55,14 +92,133 @@ class DBHandler{ | |||
| return mysqli_error($this->mysql); | |||
| } | |||
| public function lastInsertId(){ | |||
| return mysqli_insert_id($this->mysql); | |||
| //public function lastInsertId(){ | |||
| // return mysqli_insert_id($this->mysql); | |||
| //} | |||
| //public function getAffectedRows() { | |||
| // return mysqli_affected_rows($this->mysql); | |||
| //} | |||
| public function verifyInteger($input, $minimum = 1){ | |||
| /* | |||
| * Pretty hacky solution. | |||
| * | |||
| * First checks if the integer cast of the input is equal to itself. | |||
| * This filters out decimals, alternate bases, and exponents. | |||
| * Then checks if the input is numeric, which filters out other strings that slip by the first check. | |||
| * This guarantees that it's in a numeric format, which combined with the first filter, should guarantee that it is an integer | |||
| */ | |||
| return (((int) $input == $input) && is_numeric($input) && (($minimum === false) || (int) $input >= $minimum)); | |||
| } | |||
| // Always returns a key of length 40. TODO: Add arbitrary length | |||
| public function randomKey(){ | |||
| //Cryptographically Secure Key | |||
| if(function_exists('openssl_random_pseudo_bytes')) return base64_encode(openssl_random_pseudo_bytes(30)); | |||
| //Fallback (Not cryptographically secure) | |||
| $str = ""; | |||
| for($i=0; $i<30; $i++){ | |||
| $str .= chr(mt_rand(0,255)); | |||
| } | |||
| return base64_encode($str); | |||
| } | |||
| } | |||
| class SqliteDb { | |||
| private $sqlite; | |||
| private function __construct() {} | |||
| public static function Connect(){ | |||
| $handler = new SqliteDb(); | |||
| $handler->sqlite = new Sqlite3(BASE . "/inc/config/sqlite3.db"); | |||
| $handler->sqlite->exec('PRAGMA foreign_keys = ON'); | |||
| return $handler; | |||
| } | |||
| public function sanitize($text){ | |||
| return SQLite3::escapeString($text); | |||
| } | |||
| public function query($query){ | |||
| try { | |||
| return $this->sqlite->query($query); | |||
| } catch (Throwable $err) { | |||
| return false; | |||
| } | |||
| } | |||
| public function insert($table, $fields, $values_assoc, $ignore = false) { | |||
| $field_list = implode(",", $fields); | |||
| $values_arr = []; | |||
| foreach ($values_assoc as $value) { | |||
| $value_arr = []; | |||
| foreach ($value as $v) { | |||
| if ($this->verifyInteger($v)) | |||
| $value_arr[] = $v; | |||
| else if ($v === "NULL") | |||
| $value_arr[] = "NULL"; | |||
| else | |||
| $value_arr[] = "\"{$this->sanitize($v)}\""; | |||
| } | |||
| $values_arr[] = "(" . implode(',', $value_arr) . ")"; | |||
| } | |||
| $values_list = implode(',', $values_arr); | |||
| $ignore_str = ''; | |||
| if ($ignore) | |||
| $ignore_str = 'OR IGNORE'; | |||
| return $this->query("INSERT $ignore_str INTO $table ($field_list) VALUES $values_list"); | |||
| } | |||
| public function exec_multi($query){ | |||
| try { | |||
| return $this->sqlite->exec($query); | |||
| } catch (Throwable $err) { | |||
| return false; | |||
| } | |||
| } | |||
| public function fetchRow($query){ | |||
| $result = $this->query($query); | |||
| if ($result === false || $result === true) | |||
| return $result; | |||
| return $result->fetchArray(); | |||
| } | |||
| public function fetchAssoc($query){ | |||
| $result = $this->query($query); | |||
| if($result === false || $result === true) die($this->getError());//return $result; | |||
| $data = array(); | |||
| while($row = $result->fetchArray()){ | |||
| $data[] = $row; | |||
| } | |||
| return $data; | |||
| } | |||
| public function getAffectedRows() { | |||
| return mysqli_affected_rows($this->mysql); | |||
| public function getError() { | |||
| return $this->sqlite->lastErrorCode() === 0 ? "" : $this->sqlite->lastErrorMsg(); | |||
| } | |||
| //public function lastInsertId(){ | |||
| // return mysqli_insert_id($this->mysql); | |||
| //} | |||
| //public function getAffectedRows() { | |||
| // return mysqli_affected_rows($this->mysql); | |||
| //} | |||
| public function verifyInteger($input, $minimum = 1){ | |||
| /* | |||
| * Pretty hacky solution. | |||
| @@ -3,7 +3,7 @@ | |||
| define('BASE', dirname(__DIR__)); | |||
| define('BASEURL', $_SERVER['SERVER_NAME']); | |||
| $config = json_decode(file_get_contents(BASE . "/inc/config.json")); | |||
| $config = json_decode(file_get_contents(BASE . "/inc/config/config.json")); | |||
| if (empty($config)) { | |||
| header('Location: /configure.php'); | |||
| die(); | |||
| @@ -15,9 +15,13 @@ session_start(); | |||
| // Database and Authentication | |||
| require_once(BASE . '/inc/db.php'); | |||
| $db = DBHandler::Connect($config->host, $config->user, $config->pass, $config->db); | |||
| if ($config->type == "mysql") | |||
| $db = MysqlDb::Connect($config->host, $config->user, $config->pass, $config->db); | |||
| else | |||
| $db = SqliteDb::Connect(); | |||
| require_once(BASE . '/inc/user.php'); | |||
| require_once(BASE . '/inc/misc.php'); | |||
| // Templates | |||
| require_once(BASE . '/templates/header.php'); | |||
| @@ -0,0 +1,8 @@ | |||
| <?php | |||
| function get_gravatar_assoc(&$results) { | |||
| foreach ($results as &$result) { | |||
| $result['gravatar_hash'] = md5($result['gravatar_email']); | |||
| unset($result['gravatar_email']); | |||
| } | |||
| } | |||
| @@ -59,7 +59,8 @@ class User{ | |||
| $this->loggedin = true; | |||
| // Create user automatically on login | |||
| $_ = $db->query('insert ignore into members (skymanager_id, name, username, email) VALUES (' . ((int) $this->uid) . ', "' . $db->sanitize($this->name) . '", "' . $db->sanitize($this->username) . '", ' . (empty($this->email) ? 'NULL' : '"' . $db->sanitize($this->email) . '"') . ')'); | |||
| //$_ = $db->query('insert into members (skymanager_id, name, username, email) VALUES (' . ((int) $this->uid) . ', "' . $db->sanitize($this->name) . '", "' . $db->sanitize($this->username) . '", ' . (empty($this->email) ? 'NULL' : '"' . $db->sanitize($this->email) . '"') . ') ON DUPLICATE KEY UPDATE skymanager_id=skymanager_id'); | |||
| $_ = $db->insert('members', ['skymanager_id', 'name', 'username', 'email'], [[((int) $this->uid), $this->name, $this->username, (empty($this->email) ? 'NULL' : $this->email)]], true); | |||
| // Get voter ID | |||
| $result = $db->fetchRow('select members.voting_id from members left join proxy on (members.voting_id=proxy.voting_id) where proxy.delegate_id is null and skymanager_id=' . ((int) $this->uid)); | |||
| @@ -19,10 +19,12 @@ $header->setAttribute('title', 'Michigan Flyers'); | |||
| $header->setAttribute('tagline', 'Online Ballot'); | |||
| $header->output(); | |||
| $candidates = $db->fetchAssoc('select skymanager_id, name, username, md5(coalesce(email, "")) as `gravatar_hash` from members where voting_id is not null'); | |||
| $candidates = $db->fetchAssoc('select skymanager_id, name, username, coalesce(email, "") as `gravatar_email` from members where voting_id is not null'); | |||
| $votes = $db->fetchAssoc("select position from votes where member_id={$user->voterId()}"); | |||
| $position = $db->fetchRow("select position as code, description as label from positions where active<>0 limit 1"); | |||
| get_gravatar_assoc($candidates); | |||
| foreach ($votes as &$vote) { | |||
| $vote = $vote['position']; | |||
| } | |||
| @@ -193,7 +193,7 @@ form div.selector label { | |||
| flex-grow: 1; | |||
| } | |||
| form label.radio input { | |||
| form label.radio input, form input[type=radio] { | |||
| display: none; | |||
| } | |||
| @@ -207,7 +207,7 @@ form label.radio .radio-button-label { | |||
| border-radius: 10px; | |||
| } | |||
| form label.radio input:checked+.radio-button-label { | |||
| form label.radio input:checked+.radio-button-label, form input:checked+label.radio .radio-button-label { | |||
| background-color: #000; | |||
| color: #fff; | |||
| border: 2px solid #fff; | |||
| @@ -24,7 +24,7 @@ if (!$error) { | |||
| try { | |||
| $result = $db->query("INSERT INTO votes (candidate_id, position, member_id, vote_type, submitter_id) SELECT $candidate_selected, \"$ballot\", {$user->voterId()}, 'ONLINE', {$user->voterId()} UNION SELECT $candidate_selected, \"$ballot\", voting_id, 'PROXY ONLINE', delegate_id from proxy where delegate_id={$user->voterId()}"); | |||
| } catch (Throwable $ignore) {} | |||
| $candidate = $db->fetchRow('select skymanager_id, name, username, md5(coalesce(email, "")) as `gravatar_hash` from members where skymanager_id=' . $candidate_selected); | |||
| $candidate = $db->fetchRow('select skymanager_id, name, username, coalesce(email, "") as `gravatar_email` from members where skymanager_id=' . $candidate_selected); | |||
| if ($result) { | |||
| $to = 'mf2022elec@gmail.com'; | |||
| $from = 'noreply@tyzoid.com'; | |||
| @@ -83,7 +83,7 @@ $header->output(); | |||
| <h4 class="section-heading">Candidate</h4> | |||
| <div id="vote-profile" class="candidate"> | |||
| <div class="profile-icon"> | |||
| <img src="https://www.gravatar.com/avatar/<?= $candidate['gravatar_hash']; ?>.png?d=mp&s=64" /> | |||
| <img src="https://www.gravatar.com/avatar/<?= md5($candidate['gravatar_email']); ?>.png?d=mp&s=64" /> | |||
| </div> | |||
| <div class="profile"> | |||
| <h2 class="profile-name"><?= $candidate['name']; ?></h2> | |||