diff options
| author | Michael Save <savetheinternet@tinyboard.org> | 2012-04-16 16:40:24 +1000 |
|---|---|---|
| committer | Michael Save <savetheinternet@tinyboard.org> | 2012-04-16 16:40:24 +1000 |
| commit | ad55a634bf3f9301489f5371942c73940361a24c (patch) | |
| tree | 3d6120b26158942bade96f8d96cbc4c668e21eed | |
| parent | fb3e8191328c12bc1ab5bce8a3aef58582ee1a64 (diff) | |
various improvements
| -rw-r--r-- | inc/mod/ban.php | 41 | ||||
| -rw-r--r-- | inc/mod/pages.php | 105 | ||||
| -rw-r--r-- | mod.php | 4 | ||||
| -rw-r--r-- | stylesheets/style.css | 15 | ||||
| -rw-r--r-- | templates/mod/ban_list.html | 74 | ||||
| -rw-r--r-- | templates/mod/new_pm.html | 4 | ||||
| -rw-r--r-- | templates/mod/pm.html | 41 |
7 files changed, 247 insertions, 37 deletions
diff --git a/inc/mod/ban.php b/inc/mod/ban.php index 8d86cbcd..e7110edf 100644 --- a/inc/mod/ban.php +++ b/inc/mod/ban.php @@ -16,44 +16,45 @@ function parse_time($str) { if (($time = @strtotime($str)) !== false) return $time; - if (!preg_match('/^((\d+)\s*ye?a?r?s?)?\s*+((\d+)\s*mon?t?h?s?)?\s*((\d+)\s*we?e?k?s?)?\s*((\d+)\s*da?y?s?)?((\d+)\s*ho?u?r?s?)?\s*((\d+)\s*mi?n?u?t?e?s?)?\s*+((\d+)\s*se?c?o?n?d?s?)?$/', $str, $matches)) + if (!preg_match('/^((\d+)\s?ye?a?r?s?)?\s?+((\d+)\s?mon?t?h?s?)?\s?+((\d+)\s?we?e?k?s?)?\s?+((\d+)\s?da?y?s?)?((\d+)\s?ho?u?r?s?)?\s?+((\d+)\s?mi?n?u?t?e?s?)?\s?+((\d+)\s?se?c?o?n?d?s?)?$/', $str, $matches)) return false; - $expire = time(); - if (isset($m[2])) { + $expire = 0; + + if (isset($matches[2])) { // Years - $expire += $m[2]*60*60*24*365; + $expire += $matches[2]*60*60*24*365; } - if (isset($m[4])) { + if (isset($matches[4])) { // Months - $expire += $m[4]*60*60*24*30; + $expire += $matches[4]*60*60*24*30; } - if (isset($m[6])) { + if (isset($matches[6])) { // Weeks - $expire += $m[6]*60*60*24*7; + $expire += $matches[6]*60*60*24*7; } - if (isset($m[8])) { + if (isset($matches[8])) { // Days - $expire += $m[8]*60*60*24; + $expire += $matches[8]*60*60*24; } - if (isset($m[10])) { + if (isset($matches[10])) { // Hours - $expire += $m[10]*60*60; + $expire += $matches[10]*60*60; } - if (isset($m[12])) { + if (isset($matches[12])) { // Minutes - $expire += $m[12]*60; + $expire += $matches[12]*60; } - if (isset($m[14])) { + if (isset($matches[14])) { // Seconds - $expire += $m[14]; + $expire += $matches[14]; } - return $expire; + return time() + $expire; } function ban($mask, $reason, $length, $board) { - global $mod; + global $mod, $pdo; // TODO: permissions @@ -78,6 +79,8 @@ function ban($mask, $reason, $length, $board) { $query->bindValue(':board', null, PDO::PARAM_NULL); $query->execute() or error(db_error($query)); + + modLog('Created a new ban (<small>#' . $pdo->lastInsertId() . '</small>) for <strong>' . utf8tohtml($mask) . '</strong> with ' . ($reason ? 'reason: <small>' . $reason . '</small>' : 'no reason')); } function unban($id) { @@ -86,5 +89,7 @@ function unban($id) { $query = prepare("DELETE FROM `bans` WHERE `id` = :id"); $query->bindValue(':id', $id); $query->execute() or error(db_error($query)); + + modLog("Removed ban #{$id}"); } diff --git a/inc/mod/pages.php b/inc/mod/pages.php index 7518b9fb..60f101ea 100644 --- a/inc/mod/pages.php +++ b/inc/mod/pages.php @@ -39,7 +39,7 @@ function mod_login() { $args['error'] = $config['error']['invalid']; } else { - modLog("Logged in."); + modLog('Logged in'); // Login successful // Set cookies @@ -101,6 +101,7 @@ function mod_view_board($boardName, $page_no = 1) { $page['btn'] = getPageButtons($page['pages'], true); $page['mod'] = true; $page['config'] = $config; + echo Element('index.html', $page); } @@ -128,6 +129,8 @@ function mod_ip_remove_note($ip, $id) { $query->bindValue(':id', $id); $query->execute() or error(db_error($query)); + modLog("Removed a note for <a href=\"?/IP/{$ip}\">{$ip}</a>"); + header('Location: ?/IP/' . $ip, true, $config['redirect_http']); } @@ -160,6 +163,8 @@ function mod_page_ip($ip) { $query->bindValue(':body', $_POST['note']); $query->execute() or error(db_error($query)); + modLog("Added a note for <a href=\"?/IP/{$ip}\">{$ip}</a>"); + header('Location: ?/IP/' . $ip, true, $config['redirect_http']); return; } @@ -177,8 +182,9 @@ function mod_page_ip($ip) { $query->bindValue(':limit', $config['mod']['ip_recentposts'], PDO::PARAM_INT); $query->execute() or error(db_error($query)); - while ($post = $query->fetch()) { + while ($post = $query->fetch(PDO::FETCH_ASSOC)) { if (!$post['thread']) { + // TODO: There is no reason why this should be such a fucking mess. $po = new Thread( $post['id'], $post['subject'], $post['email'], $post['name'], $post['trip'], $post['capcode'], $post['body'], $post['time'], $post['thumb'], $post['thumbwidth'], $post['thumbheight'], $post['file'], $post['filewidth'], @@ -230,13 +236,6 @@ function mod_ban() { return; } - $query = prepare("SELECT `bans`.*, `username` FROM `bans` LEFT JOIN `mods` ON `mod` = `mods`.`id` WHERE `ip` = :ip"); - $query->bindValue(':ip', $ip); - $query->execute() or error(db_error($query)); - $args['bans'] = $query->fetchAll(PDO::FETCH_ASSOC); - - $ip = $_POST['ip']; - require_once 'inc/mod/ban.php'; ban($_POST['ip'], $_POST['reason'], parse_time($_POST['length']), $_POST['board'] == '*' ? false : $_POST['board']); @@ -247,6 +246,51 @@ function mod_ban() { header('Location: ?/', true, $config['redirect_http']); } +function mod_bans() { + global $config; + + if (!hasPermission($config['mod']['view_banlist'])) + error($config['error']['noaccess']); + + if (isset($_POST['unban'])) { + if (!hasPermission($config['mod']['unban'])) + error($config['error']['noaccess']); + + $unban = array(); + foreach ($_POST as $name => $unused) { + if (preg_match('/^ban_(\d+)$/', $name, $match)) + $unban[] = $match[1]; + } + + query('DELETE FROM `bans` WHERE `id` = ' . implode(' OR `id` = ', $unban)) or error(db_error()); + + foreach ($unban as $id) { + modLog("Removed ban #{$id}"); + } + + header('Location: ?/bans', true, $config['redirect_http']); + } + + if ($config['mod']['view_banexpired']) { + $query = prepare("SELECT `bans`.*, `username` FROM `bans` LEFT JOIN `mods` ON `mod` = `mods`.`id` ORDER BY (`expires` IS NOT NULL AND `expires` < :time), `set` DESC"); + $query->bindValue(':time', time(), PDO::PARAM_INT); + $query->execute() or error(db_error($query)); + } else { + // Filter out expired bans + $query = prepare("SELECT `bans`.*, `username` FROM `bans` INNER JOIN `mods` ON `mod` = `mods`.`id` WHERE `expires` = 0 OR `expires` > :time ORDER BY `set` DESC"); + $query->bindValue(':time', time(), PDO::PARAM_INT); + $query->execute() or error(db_error($query)); + } + $bans = $query->fetchAll(PDO::FETCH_ASSOC); + + foreach ($bans as &$ban) { + if (filter_var($ban['ip'], FILTER_VALIDATE_IP) !== false) + $ban['real_ip'] = true; + } + + mod_page('Ban list', 'mod/ban_list.html', array('bans' => $bans)); +} + function mod_delete($board, $post) { global $config, $mod; @@ -290,9 +334,48 @@ function mod_user_promote($uid, $action) { $query->bindValue(':id', $uid); $query->execute() or error(db_error($query)); + modLog(($action == 'promote' ? 'Promoted' : 'Demoted') . " user #{$uid}"); + header('Location: ?/users', true, $config['redirect_http']); } +function mod_pm($id, $reply = false) { + global $mod, $config; + + $query = prepare("SELECT `mods`.`username`, `mods_to`.`username` AS `to_username`, `pms`.* FROM `pms` LEFT JOIN `mods` ON `mods`.`id` = `sender` LEFT JOIN `mods` AS `mods_to` ON `mods_to`.`id` = `to` WHERE `pms`.`id` = :id"); + $query->bindValue(':id', $id); + $query->execute() or error(db_error($query)); + + if ((!$pm = $query->fetch(PDO::FETCH_ASSOC)) || ($pm['to'] != $mod['id'] && !hasPermission($config['mod']['master_pm']))) + error($config['error']['404']); + + if (isset($_POST['delete'])) { + $query = prepare("DELETE FROM `pms` WHERE `id` = :id"); + $query->bindValue(':id', $id); + $query->execute() or error(db_error($query)); + + header('Location: ?/', true, $config['redirect_http']); + return; + } + + if ($pm['unread'] && $pm['to'] == $mod['id']) { + $query = prepare("UPDATE `pms` SET `unread` = 0 WHERE `id` = :id"); + $query->bindValue(':id', $id); + $query->execute() or error(db_error($query)); + + modLog('Read a PM'); + } + + if ($reply) { + if (!$pm['to_username']) + error($config['error']['404']); // deleted? + + mod_page("New PM for {$pm['to_username']}", 'mod/new_pm.html', array('username' => $pm['to_username'], 'id' => $pm['to'], 'message' => quote($pm['message']))); + } else { + mod_page("Private message – #$id", 'mod/pm.html', $pm); + } +} + function mod_new_pm($username) { global $config, $mod; @@ -323,6 +406,8 @@ function mod_new_pm($username) { $query->bindValue(':time', time()); $query->execute() or error(db_error($query)); + modLog('Sent a PM to ' . utf8tohtml($username)); + header('Location: ?/', true, $config['redirect_http']); } @@ -371,7 +456,7 @@ function mod_rebuild() { } $query = query(sprintf("SELECT `id` FROM `posts_%s` WHERE `thread` IS NULL", $board['uri'])) or error(db_error()); - while($post = $query->fetch()) { + while ($post = $query->fetch(PDO::FETCH_ASSOC)) { $log[] = '<strong>' . sprintf($config['board_abbreviation'], $board['uri']) . '</strong>: Rebuilding thread #' . $post['id']; buildThread($post['id']); } @@ -26,16 +26,18 @@ $pages = array( '!^/confirm/(.+)$!' => 'confirm', // confirm action (if javascript didn't work) '!^/log$!' => 'log', // modlog '!^/log/(\d+)$!' => 'log', // modlog - + '!^/users$!' => 'users', // manage users '!^/users/(\d+)/(promote|demote)$!' => 'user_promote', // prmote/demote user '!^/new_PM/([^/]+)$!' => 'new_pm', // create a new pm + '!^/PM/(\d+)(/reply)?$!' => 'pm', // read a pm '!^/rebuild$!' => 'rebuild', // rebuild static files '!^/ban$!' => 'ban', // new ban '!^/IP/([\w.:]+)$!' => 'ip', // view ip address '!^/IP/([\w.:]+)/remove_note/(\d+)$!' => 'ip_remove_note', // remove note from ip address + '!^/bans$!' => 'bans', // ban list '!^/(\w+)/delete/(\d+)$!' => 'delete', // delete post diff --git a/stylesheets/style.css b/stylesheets/style.css index d77f05b5..edebf0c1 100644 --- a/stylesheets/style.css +++ b/stylesheets/style.css @@ -68,15 +68,18 @@ form table input { } input[type="text"], input[type="password"], textarea { border: 1px solid #a9a9a9; - text-indent: 0px; + text-indent: 0; text-shadow: none; text-transform: none; word-spacing: normal; } form table tr td { text-align: left; - margin: 0px; - padding: 0px; + margin: 0; + padding: 0; +} +form table.mod tr td { + padding: 2px; } form table tr th { text-align: left; @@ -102,7 +105,7 @@ form table tr td div label { } p.fileinfo { display: block; - margin: 0px; + margin: 0; padding-right: 7em; } div.banner { @@ -326,7 +329,7 @@ div.pages form input { hr { border: none; border-top: 1px solid #B7C5D9; - height: 0px; + height: 0; clear: left; } div.boardlist { @@ -349,7 +352,7 @@ table.modlog { } table.modlog tr td { text-align: left; - margin: 0px; + margin: 0; padding: 4px 15px 0 0; } table.modlog tr th { diff --git a/templates/mod/ban_list.html b/templates/mod/ban_list.html new file mode 100644 index 00000000..00b8a0f4 --- /dev/null +++ b/templates/mod/ban_list.html @@ -0,0 +1,74 @@ +{% if bans|count == 0 %} + <p style="text-align:center" class="unimportant">(There are no active bans.)</p> +{% else %} + <form action="" method="post"> + <table class="mod"> + <tr> + <th>{% trans %}IP address{% endtrans %}</th> + <th>{% trans %}Reason{% endtrans %}</th> + <th>{% trans %}Board{% endtrans %}</th> + <th>{% trans %}Set{% endtrans %}</th> + <th>{% trans %}Expires{% endtrans %}</th> + <th>{% trans %}Staff{% endtrans %}</th> + </tr> + {% for ban in bans %} + <tr{% if ban.expires != 0 and ban.expires < time() %} style="text-decoration:line-through"{% endif %}> + <td style="white-space: nowrap"> + <input type="checkbox" name="ban_{{ ban.id }}"> + {% if ban.real_ip %} + <a href="?/IP/{{ ban.ip }}">{{ ban.ip }}</a> + {% else %} + {{ ban.ip|e }} + {% endif %} + </td> + <td> + {% if ban.reason %} + {{ ban.reason }} + {% else %} + - + {% endif %} + </td> + <td style="white-space: nowrap"> + {% if ban.board %} + {{ config.board_abbreviation|sprintf(ban.board) }} + {% else %} + <em>{% trans %}all boards{% endtrans %} + {% endif %} + </td> + <td style="white-space: nowrap"> + {{ ban.set|date(config.post_date) }} + </td> + <td style="white-space: nowrap"> + {% if ban.expires == 0 %} + <em>never</em> + {% else %} + {{ ban.expires|date(config.post_date) }} + {% if ban.expires > time() %} + <small>({{ ban.expires|until }})</small> + {% endif %} + {% endif %} + </td> + <td> + {% if ban.username %} + {% if mod|hasPermission(config.mod.view_banstaff) %} + <a href="?/new_PM/{{ ban.username|e }}">{{ ban.username|e }}</a> + {% else %} + {% if mod|hasPermission(config.mod.view_banquestionmark) %} + <em>?</em> + {% else %} + + {% endif %} + {% endif %} + {% else %} + <em>deleted?</em> + {% endif %} + </td> + </tr> + {% endfor %} + </table> + + <p style="text-align:center"> + <input type="submit" name="unban" value="Unban selected"> + </p> + </form> +{% endif %} diff --git a/templates/mod/new_pm.html b/templates/mod/new_pm.html index d694bc26..ece1325c 100644 --- a/templates/mod/new_pm.html +++ b/templates/mod/new_pm.html @@ -2,7 +2,7 @@ {% set username = 'me' %} {% endif %}#} -<form action="" method="post"> +<form action="?/new_PM/{{ username|e }}" method="post"> <table> <tr> <th>To</th> @@ -14,7 +14,7 @@ </tr> <tr> <th>Message</th> - <td><textarea name="message" rows="10" cols="40"></textarea></td> + <td><textarea name="message" rows="10" cols="40">{{ message }}</textarea></td> </tr> </table> diff --git a/templates/mod/pm.html b/templates/mod/pm.html new file mode 100644 index 00000000..511bcfef --- /dev/null +++ b/templates/mod/pm.html @@ -0,0 +1,41 @@ +<form action="" method="post"> + <table> + <tr> + <th>From</th> + {% if username %} + <td><a href="?/new_PM/{{ username|e }}">{{ username|e }}</a></td> + {% else %} + <td><em>deleted?</em></td> + {% endif %} + </tr> + {% if to != mod.id %} + <tr> + <th>To</th> + {% if to_username %} + <td><a href="?/new_PM/{{ to_username|e }}">{{ to_username|e }}</a></td> + {% else %} + <td><em>deleted?</em></td> + {% endif %} + </tr> + {% endif %} + <tr> + <th>Date</th> + <td>{{ time|date(config.post_date) }}</td> + </tr> + <tr> + <th>Message</th> + <td>{{ message }}</td> + </tr> + </table> + + <ul style="list-style:none;text-align:center;padding:0"> + <li style="padding:5px 0"> + <input type="submit" name="delete" value="Delete forever"> + </li> + <li style="padding:5px 0"> + <a href="?/PM/{{ id }}/reply"> + Reply with quote + </a> + </li> + </ul> +</form> |
