diff --git a/inc/config.php b/inc/config.php index 484183ba..d47ab59f 100644 --- a/inc/config.php +++ b/inc/config.php @@ -903,6 +903,9 @@ // PM snippet (for ?/inbox) length in characters $config['mod']['snippet_length'] = 75; + // Edit raw HTML in posts by default + $config['mod']['raw_html_default'] = false; + // Probably best not to change these: if (!defined('JANITOR')) { define('JANITOR', 0, true); @@ -1049,6 +1052,9 @@ // Edit the current configuration (via web interface) $config['mod']['edit_config'] = ADMIN; + // Execute un-filtered SQL queries on the database (?/debug/sql) + $config['mod']['debug_sql'] = DISABLED; + /* * ==================== * Events (PHP 5.3.0+) diff --git a/inc/display.php b/inc/display.php index 011a953c..9be772e4 100644 --- a/inc/display.php +++ b/inc/display.php @@ -297,7 +297,7 @@ class Post { // Edit post if (hasPermission($config['mod']['editpost'], $board['uri'], $this->mod)) - $built .= ' ' . $config['mod']['link_editpost'] . ''; + $built .= ' ' . $config['mod']['link_editpost'] . ''; if (!empty($built)) $built = '' . $built . ''; @@ -418,7 +418,7 @@ class Thread { // Edit post if (hasPermission($config['mod']['editpost'], $board['uri'], $this->mod)) - $built .= ' ' . $config['mod']['link_editpost'] . ''; + $built .= ' ' . $config['mod']['link_editpost'] . ''; if (!empty($built)) $built = '' . $built . ''; diff --git a/inc/mod/pages.php b/inc/mod/pages.php index 643786b4..f6ac3fc4 100644 --- a/inc/mod/pages.php +++ b/inc/mod/pages.php @@ -986,7 +986,7 @@ function mod_ban_post($board, $delete, $post, $token = false) { mod_page(_('New ban'), 'mod/ban_form.html', $args); } -function mod_edit_post($board, $postID) { +function mod_edit_post($board, $edit_raw_html, $postID) { global $config, $mod; if (!openBoard($board)) @@ -994,8 +994,11 @@ function mod_edit_post($board, $postID) { if (!hasPermission($config['mod']['editpost'], $board)) error($config['error']['noaccess']); + + if ($edit_raw_html && !hasPermission($config['mod']['rawhtml'], $board)) + error($config['error']['noaccess']); - $security_token = make_secure_link_token($board . '/edit/' . $postID); + $security_token = make_secure_link_token($board . '/edit' . ($edit_raw_html ? '_raw' : '') . '/' . $postID); $query = prepare(sprintf('SELECT * FROM `posts_%s` WHERE `id` = :id', $board)); $query->bindValue(':id', $postID); @@ -1005,7 +1008,10 @@ function mod_edit_post($board, $postID) { error($config['error']['404']); if (isset($_POST['name'], $_POST['email'], $_POST['subject'], $_POST['body'])) { - $query = prepare(sprintf('UPDATE `posts_%s` SET `name` = :name, `email` = :email, `subject` = :subject, `body_nomarkup` = :body WHERE `id` = :id', $board)); + if ($edit_raw_html) + $query = prepare(sprintf('UPDATE `posts_%s` SET `name` = :name, `email` = :email, `subject` = :subject, `body` = :body WHERE `id` = :id', $board)); + else + $query = prepare(sprintf('UPDATE `posts_%s` SET `name` = :name, `email` = :email, `subject` = :subject, `body_nomarkup` = :body WHERE `id` = :id', $board)); $query->bindValue(':id', $postID); $query->bindValue('name', $_POST['name']); $query->bindValue(':email', $_POST['email']); @@ -1013,15 +1019,19 @@ function mod_edit_post($board, $postID) { $query->bindValue(':body', $_POST['body']); $query->execute() or error(db_error($query)); - rebuildPost($postID); + if (!$edit_raw_html) + rebuildPost($postID); + buildIndex(); header('Location: ?/' . sprintf($config['board_path'], $board) . $config['dir']['res'] . sprintf($config['file_page'], $post['thread'] ? $post['thread'] : $postID) . '#' . $postID, true, $config['redirect_http']); } else { - if ($config['minify_html']) + if ($config['minify_html']) { $post['body_nomarkup'] = str_replace("\n", ' ', $post['body_nomarkup']); + $post['body'] = str_replace("\n", ' ', $post['body']); + } - mod_page(_('Edit post'), 'mod/edit_post_form.html', array('token' => $security_token, 'post' => $post)); + mod_page(_('Edit post'), 'mod/edit_post_form.html', array('token' => $security_token, 'board' => $board, 'raw' => $edit_raw_html, 'post' => $post)); } } @@ -1723,40 +1733,6 @@ function mod_config() { mod_page(_('Config editor'), 'mod/config-editor.html', array('conf' => $conf)); } -function mod_debug_antispam() { - global $pdo, $config; - - $args = array(); - - if (isset($_POST['board'], $_POST['thread'])) { - $where = '`board` = ' . $pdo->quote($_POST['board']); - if ($_POST['thread'] != '') - $where .= ' AND `thread` = ' . $pdo->quote($_POST['thread']); - - if (isset($_POST['purge'])) { - $query = prepare('UPDATE `antispam` SET `expires` = UNIX_TIMESTAMP() + :expires WHERE' . $where); - $query->bindValue(':expires', $config['spam']['hidden_inputs_expire']); - $query->execute() or error(db_error()); - } - - $args['board'] = $_POST['board']; - $args['thread'] = $_POST['thread']; - } else { - $where = ''; - } - - $query = query('SELECT COUNT(*) FROM `antispam`' . ($where ? " WHERE $where" : '')) or error(db_error()); - $args['total'] = number_format($query->fetchColumn(0)); - - $query = query('SELECT COUNT(*) FROM `antispam` WHERE `expires` IS NOT NULL' . ($where ? " AND $where" : '')) or error(db_error()); - $args['expiring'] = number_format($query->fetchColumn(0)); - - $query = query('SELECT * FROM `antispam` ' . ($where ? "WHERE $where" : '') . ' ORDER BY `passed` DESC LIMIT 40') or error(db_error()); - $args['top'] = $query->fetchAll(PDO::FETCH_ASSOC); - - mod_page(_('Debug: Anti-spam'), 'mod/debug/antispam.html', $args); -} - function mod_themes_list() { global $config; @@ -1884,3 +1860,89 @@ function mod_theme_rebuild($theme_name) { 'theme_name' => $theme_name, )); } + +function mod_debug_antispam() { + global $pdo, $config; + + $args = array(); + + if (isset($_POST['board'], $_POST['thread'])) { + $where = '`board` = ' . $pdo->quote($_POST['board']); + if ($_POST['thread'] != '') + $where .= ' AND `thread` = ' . $pdo->quote($_POST['thread']); + + if (isset($_POST['purge'])) { + $query = prepare('UPDATE `antispam` SET `expires` = UNIX_TIMESTAMP() + :expires WHERE' . $where); + $query->bindValue(':expires', $config['spam']['hidden_inputs_expire']); + $query->execute() or error(db_error()); + } + + $args['board'] = $_POST['board']; + $args['thread'] = $_POST['thread']; + } else { + $where = ''; + } + + $query = query('SELECT COUNT(*) FROM `antispam`' . ($where ? " WHERE $where" : '')) or error(db_error()); + $args['total'] = number_format($query->fetchColumn(0)); + + $query = query('SELECT COUNT(*) FROM `antispam` WHERE `expires` IS NOT NULL' . ($where ? " AND $where" : '')) or error(db_error()); + $args['expiring'] = number_format($query->fetchColumn(0)); + + $query = query('SELECT * FROM `antispam` ' . ($where ? "WHERE $where" : '') . ' ORDER BY `passed` DESC LIMIT 40') or error(db_error()); + $args['top'] = $query->fetchAll(PDO::FETCH_ASSOC); + + $query = query('SELECT * FROM `antispam` ' . ($where ? "WHERE $where" : '') . ' ORDER BY `created` DESC LIMIT 20') or error(db_error()); + $args['recent'] = $query->fetchAll(PDO::FETCH_ASSOC); + + mod_page(_('Debug: Anti-spam'), 'mod/debug/antispam.html', $args); +} + +function mod_debug_recent_posts() { + global $pdo, $config; + + $limit = 500; + + $boards = listBoards(); + + // Manually build an SQL query + $query = 'SELECT * FROM ('; + foreach ($boards as $board) { + $query .= sprintf('SELECT *, %s AS `board` FROM `posts_%s` UNION ALL ', $pdo->quote($board['uri']), $board['uri']); + } + // Remove the last "UNION ALL" seperator and complete the query + $query = preg_replace('/UNION ALL $/', ') AS `all_posts` ORDER BY `time` DESC LIMIT ' . $limit, $query); + $query = query($query) or error(db_error()); + $posts = $query->fetchAll(PDO::FETCH_ASSOC); + + foreach ($posts as &$post) { + $post['snippet'] = pm_snippet($post['body']); + } + + mod_page(_('Debug: Recent posts'), 'mod/debug/recent_posts.html', array('posts' => $posts)); +} + +function mod_debug_sql() { + global $config; + + if (!hasPermission($config['mod']['debug_sql'])) + error($config['error']['noaccess']); + + $args['security_token'] = make_secure_link_token('debug/sql'); + + if (isset($_POST['query'])) { + $args['query'] = $_POST['query']; + if ($query = query($_POST['query'])) { + $args['result'] = $query->fetchAll(PDO::FETCH_ASSOC); + if (!empty($args['result'])) + $args['keys'] = array_keys($args['result'][0]); + else + $args['result'] = 'empty'; + } else { + $args['error'] = db_error(); + } + } + + mod_page(_('Debug: SQL'), 'mod/debug/sql.html', $args); +} + diff --git a/mod.php b/mod.php index 4b0594ae..cb12b565 100644 --- a/mod.php +++ b/mod.php @@ -61,7 +61,7 @@ $pages = array( '/ban' => 'secure_POST ban', // new ban '/([\w+.]+)/ban(&delete)?/(\d+)' => 'secure_POST ban_post', // ban poster '/([\w+.]+)/move/(\d+)' => 'secure_POST move', // move thread - '/([\w+.]+)/edit/(\d+)' => 'secure_POST edit_post', // edit post + '/([\w+.])/edit(_raw)?/(\d+)' => 'secure_POST edit_post', // edit post '/([\w+.]+)/delete/(\d+)' => 'secure delete', // delete post '/([\w+.]+)/deletefile/(\d+)' => 'secure deletefile', // delete file from post '/([\w+.]+)/deletebyip/(\d+)(/global)?' => 'secure deletebyip', // delete all posts by IP address @@ -78,6 +78,8 @@ $pages = array( // these pages aren't listed in the dashboard without $config['debug'] '/debug/antispam' => 'debug_antispam', + '/debug/recent' => 'debug_recent_posts', + '/debug/sql' => 'secure_POST debug_sql', // This should always be at the end: '/([\w+.]+)/' => 'view_board', diff --git a/templates/mod/debug/antispam.html b/templates/mod/debug/antispam.html index a846bc17..95aa61a6 100644 --- a/templates/mod/debug/antispam.html +++ b/templates/mod/debug/antispam.html @@ -1,3 +1,44 @@ +

+ Most recent: +

+ + + + + + + + + + {% for hash in recent %} + + + + + + + + + {% endfor %} +
BoardThreadHash (SHA1)CreatedExpiresPassed
{{ config.board_abbreviation|sprintf(hash.board) }} + {% if hash.thread %} + {{ hash.thread }} + {% else %} + - + {% endif %} + {{ hash.hash }} + + {{ hash.created|ago }} ago + + {% if hash.expires %} + + {{ hash.expires|until }} + + {% else %} + - + {% endif %} + {{ hash.passed }}
+

Most used (in active):

@@ -38,6 +79,7 @@ {% endfor %} +

Total: {{ total }} ({{ expiring }} set to expire)

diff --git a/templates/mod/debug/recent_posts.html b/templates/mod/debug/recent_posts.html new file mode 100644 index 00000000..740ed21e --- /dev/null +++ b/templates/mod/debug/recent_posts.html @@ -0,0 +1,89 @@ + + + + + + + + + + + + + {% for post in posts %} + + + + + + + + + + + + {% endfor %} +
TimeBoardIDThreadIPNameSubjectFileBody (snippet)
+ {{ post.time | ago }} ago + + {{ config.board_abbreviation|sprintf(post.board) }} + + {% if post.thread %} + {% set thread = post.thread %} + {% else %} + {% set thread = post.id %} + {% endif %} + + {{ post.id }} + + + + {% if post.thread %} + {{ post.thread }} + {% else %} + (OP) + {% endif %} + + + {% if mod|hasPermission(config.mod.show_ip, post.board) %} + + {{ post.ip }} + + {% else %} + hidden + {% endif %} + + + {% if post.email|length > 0 %} + {# start email #} + + {% endif %} + {% if capcode %} + {{ capcode.cap }} + {% endif %} + + + {% if post.subject %} + {{ post.subject }} + {% else %} + – + {% endif %} + + {% if post.file %} + {{ post.file }} ({{ post.filesize | filesize }}) + {% else %} + – + {% endif %} + + {{ post.snippet }} +
+ diff --git a/templates/mod/debug/sql.html b/templates/mod/debug/sql.html new file mode 100644 index 00000000..755995f9 --- /dev/null +++ b/templates/mod/debug/sql.html @@ -0,0 +1,26 @@ +
+ + + +
+ +{% if result == 'empty' %} +

Query successful (no result).

+{% elseif result %} + + + {% for key in keys %} + + {% endfor %} + + {% for row in result %} + + {% for col in row %} + + {% endfor %} + + {% endfor %} +
{{ key | e }}
{{ col | e }}
+{% elseif error %} +

{{ error | e }}

+{% endif %} diff --git a/templates/mod/edit_post_form.html b/templates/mod/edit_post_form.html index 22fa40cb..146e725b 100644 --- a/templates/mod/edit_post_form.html +++ b/templates/mod/edit_post_form.html @@ -32,8 +32,16 @@ {% trans %}Comment{% endtrans %} - + +

+ {% if raw %} + {% trans %}Currently editing raw HTML.{% endtrans %} + {% trans %}Edit markup instead?{% endtrans %} + {% else %} + {% trans %}Edit raw HTML instead?{% endtrans %} + {% endif %} +