From 4c8e9203030af7fd4b785468ea785ae0f3ed279a Mon Sep 17 00:00:00 2001 From: unknown <8n-tech@users.noreply.github.com> Date: Mon, 20 Oct 2014 10:17:19 -0500 Subject: [PATCH] [#184] Resolved duplicate report issue. Added rudamentary Clean functionality. --- inc/config.php | 5 +- inc/display.php | 55 ++++++++++++- inc/functions.php | 1 + inc/mod/pages.php | 127 ++++++++++++++++++++++++++++-- mod.php | 26 +++--- stylesheets/style.css | 12 +++ templates/mod/report.html | 2 +- templates/mod/report_content.html | 47 ++++++----- templates/post/edited_at.html | 15 +++- templates/post_reply.html | 2 +- templates/post_thread.html | 2 +- 11 files changed, 241 insertions(+), 53 deletions(-) diff --git a/inc/config.php b/inc/config.php index bcc22f8e..4190b0bb 100644 --- a/inc/config.php +++ b/inc/config.php @@ -1382,7 +1382,10 @@ $config['mod']['flood'] = &$config['mod']['bypass_filters']; // Raw HTML posting $config['mod']['rawhtml'] = ADMIN; - + // Clean/Unclean posts + $config['mod']['clean'] = JANITOR; + $config['mod']['clean_global'] = MOD; + /* Administration */ // View the report queue $config['mod']['reports'] = JANITOR; diff --git a/inc/display.php b/inc/display.php index 1a78e19b..bb6120ee 100644 --- a/inc/display.php +++ b/inc/display.php @@ -389,7 +389,32 @@ class Post { public function build($index=false) { global $board, $config; - return Element('post_reply.html', array('config' => $config, 'board' => $board, 'post' => &$this, 'index' => $index, 'mod' => $this->mod)); + return Element('post_reply.html', array( + 'config' => $config, + 'board' => $board, + 'post' => &$this, + 'index' => $index, + 'mod' => $this->mod, + 'clean' => $this->getClean(), + )); + } + + public function getClean( ) { + global $board; + + if( !isset( $this->clean ) ) { + $query = prepare("SELECT * FROM `post_clean` WHERE `post_id` = :post AND `board_id` = :board"); + $query->bindValue( ':board', $board['uri'] ); + $query->bindValue( ':post', $this->id ); + + $query->execute() or error(db_error($query)); + + if( !($this->clean = $query->fetch(PDO::FETCH_ASSOC)) ) { + $this->clean = array(); + } + } + + return $this->clean; } }; @@ -453,9 +478,35 @@ class Thread { event('show-thread', $this); - $built = Element('post_thread.html', array('config' => $config, 'board' => $board, 'post' => &$this, 'index' => $index, 'hasnoko50' => $hasnoko50, 'isnoko50' => $isnoko50, 'mod' => $this->mod)); + $built = Element('post_thread.html', array( + 'config' => $config, + 'board' => $board, + 'post' => &$this, + 'index' => $index, + 'hasnoko50' => $hasnoko50, + 'isnoko50' => $isnoko50, + 'mod' => $this->mod, + 'clean' => $this->getClean(), + )); return $built; } + public function getClean( ) { + global $board, $config, $debug; + + if( !isset( $this->clean ) ) { + $query = prepare("SELECT * FROM `post_clean` WHERE `post_id` = :post AND `board_id` = :board"); + $query->bindValue( ':board', $board['uri'] ); + $query->bindValue( ':post', $this->id ); + + $query->execute() or error(db_error($query)); + + if( !($this->clean = $query->fetch(PDO::FETCH_ASSOC)) ) { + $this->clean = array(); + } + } + + return $this->clean; + } }; diff --git a/inc/functions.php b/inc/functions.php index 672885be..48a399ec 100755 --- a/inc/functions.php +++ b/inc/functions.php @@ -311,6 +311,7 @@ function _syslog($priority, $message) { function verbose_error_handler($errno, $errstr, $errfile, $errline) { if (error_reporting() == 0) return false; // Looks like this warning was suppressed by the @ operator. + error(utf8tohtml($errstr), true, array( 'file' => $errfile . ':' . $errline, 'errno' => $errno, diff --git a/inc/mod/pages.php b/inc/mod/pages.php index 2b9d8fed..dde0c1bc 100644 --- a/inc/mod/pages.php +++ b/inc/mod/pages.php @@ -2257,6 +2257,7 @@ function mod_rebuild() { )); } + function mod_reports() { global $config, $mod; @@ -2276,7 +2277,7 @@ function mod_reports() { $report_scope = $global ? "global" : "local"; // Get REPORTS. - $query = prepare("SELECT * FROM ``reports`` " . ($mod["type"] == "20" ? "WHERE board = :board" : "") . " WHERE ``".($global ? "global" : "local")."``=TRUE LIMIT :limit"); + $query = prepare("SELECT * FROM ``reports`` " . ($mod["type"] == "20" ? "WHERE board = :board" : "") . " WHERE ``".($global ? "global" : "local")."`` = TRUE LIMIT :limit"); // Limit reports by board if the moderator is local. if( $mod['type'] == '20' ) { @@ -2335,27 +2336,26 @@ function mod_reports() { $report_index[ $content_key ] = array( "board_id" => $report['board'], "post_id" => $report['post'], - "content" => &$report_posts[ $report['board'] ][ $report['post'] ], + "content" => $report_posts[ $report['board'] ][ $report['post'] ], "reports" => array(), ); } // Add the report to the list of reports. - $report_index[ $content_key ]['reports'][ $report['id'] ] = &$report; + $report_index[ $content_key ]['reports'][ $report['id'] ] = $report; // Increment the total report count. ++$reportCount; } - // Only continue if we have something to do. // If there are no valid reports left, we're done. if( $reportCount > 0 ) { // Sort this report index by number of reports, desc. usort( $report_index, function( $a, $b ) { - $ra = $a['reports']; - $rb = $b['reports']; + $ra = count( $a['reports'] ); + $rb = count( $b['reports'] ); if( $ra < $rb ) { return 1; @@ -2404,7 +2404,7 @@ function mod_reports() { 'token_dismiss' => make_secure_link_token( $uri_report_base . '/dismiss' ), 'token_ip' => make_secure_link_token( $uri_report_base . '/dismissall' ), 'token_demote' => make_secure_link_token( $uri_report_base . '/demote' ), - 'token_promote' => make_secure_link_token( $uri_report_base . '/promote' ), + 'token_promote' => make_secure_link_token( $uri_report_base . '/promote' ), )); // Determines if we can "Demote All" / "Promote All" @@ -2431,6 +2431,7 @@ function mod_reports() { ); $uri_content_base = "reports/" . ($global ? "global/" : "" ) . "content/"; + $uri_clean_base = "{$report_item['board_id']}/clean/{$content['id']}"; $content_html = Element('mod/report_content.html', array( 'reports_html' => $report_html, 'reports_can_demote' => $reports_can_demote, @@ -2449,6 +2450,13 @@ function mod_reports() { 'token_content_promote' => make_secure_link_token( "{$uri_content_base}{$report_item['board_id']}/{$content['id']}/promote" ), 'token_content_dismiss' => make_secure_link_token( "{$uri_content_base}{$report_item['board_id']}/{$content['id']}/dismiss" ), + 'uri_clean' => "?/{$uri_clean_base}/local", + 'uri_clean_global' => "?/{$uri_clean_base}/global", + 'uri_clean_both' => "?/{$uri_clean_base}/global+local", + 'token_clean' => make_secure_link_token( $uri_clean_base . '/local' ), + 'token_clean_global' => make_secure_link_token( $uri_clean_base . '/global' ), + 'token_clean_both' => make_secure_link_token( $uri_clean_base . '/global+local' ), + 'global' => $global, 'config' => $config, 'mod' => $mod, @@ -2565,6 +2573,12 @@ function mod_report_dismiss() { $query->execute() or error(db_error($query)); + + // Cleanup - Remove reports that have been completely dismissed. + $query = prepare("DELETE FROM `reports` WHERE `local` = FALSE AND `global` = FALSE"); + $query->execute() or error(db_error($query)); + + if( $all ) { modLog("Dismissed all reports by {$ip}"); } @@ -2799,6 +2813,105 @@ function mod_recent_posts($lim) { } +function mod_clean( $board, $unclean, $post, $global, $local ) { + global $config, $mod; + + if( !openBoard($board) ) { + error($config['error']['noboard']); + } + + $query_global = ""; + $query_global_mod = ""; + if( $global ) { + if( !hasPermission($config['mod']['clean_global'], $board) ) { + error($config['error']['noaccess']); + } + + $query_global = "`clean_global` = :clean"; + $query_global_mod = "`clean_global_mod_id` = :mod"; + } + + $query_local = ""; + $query_local_mod = ""; + if( $local ) { + if( !hasPermission($config['mod']['clean'], $board) ) { + error($config['error']['noaccess']); + } + + $query_local = "`clean_local` = :clean"; + $query_local_mod = "`clean_local_mod_id` = :mod"; + } + + + // Marking this post as "Clean" (report immune?) + if( !$unclean ) { + // Attempt to find a `post_clean` row for this content. + $query = prepare("SELECT * FROM `post_clean` WHERE `board_id` = :board AND `post_id` = :post"); + $query->bindValue( ':board', $board ); + $query->bindValue( ':post', $post ); + + $query->execute() or error(db_error($query)); + + // If the $clean object doesn't exist we need to insert a row for this post. + if( !($clean = $query->fetch(PDO::FETCH_ASSOC)) ) { + $query = prepare("INSERT INTO `post_clean` (`post_id`, `board_id`) VALUES ( :post, :board )"); + $query->bindValue( ':board', $board ); + $query->bindValue( ':post', $post ); + + $query->execute() or error(db_error($query)); + + if( $query->rowCount() == 0 ) { + error("The database failed to create a record for this content in `post_clean` to record clean status."); + } + + $clean = true; + } + } + // Revoking clean status (open it to reports?) + else { + // Attempt to find a `post_clean` row for this content. + $query = prepare("SELECT * FROM `post_clean` WHERE `board_id` = :board AND `post_id` = :post"); + $query->bindValue( ':board', $board ); + $query->bindValue( ':post', $post ); + + $query->execute() or error(db_error($query)); + + if( !($clean = $query->fetch(PDO::FETCH_ASSOC)) ) { + error($config['error']['404']); + } + } + + // Update the `post_clean` row represented by $clean. + if( $clean ) { + // Build our query based on the URI arguments. + if( $global && $local ) { + $query = prepare("UPDATE `post_clean` SET {$query_global}, {$query_global_mod}, {$query_local}, {$query_local_mod} WHERE `board_id` = :board AND `post_id` = :post"); + } + else if( $global ) { + $query = prepare("UPDATE `post_clean` SET {$query_global}, {$query_global_mod} WHERE `board_id` = :board AND `post_id` = :post"); + } + else { + $query = prepare("UPDATE `post_clean` SET {$query_local}, {$query_local_mod} WHERE `board_id` = :board AND `post_id` = :post"); + } + + $query->bindValue( ':clean', !$unclean ); + $query->bindValue( ':mod', $mod['id'] ); + $query->bindValue( ':board', $board ); + $query->bindValue( ':post', $post ); + + $query->execute() or error(db_error($query)); + + // Log the action. + // This is super important because a mod intentionally screwing with clean status needs to be found out, fast. + $log_action = ($unclean ? "Closed" : "Re-opened" ); + $log_scope = ($local && $global ? "local and global" : ($local ? "local" : "global" ) ); + modLog( "{$log_action} reports for post #{$post} in {$log_scope}.", $board); + } + + // Redirect + header('Location: ?/' . sprintf($config['board_path'], $board) . $config['file_index'], true, $config['redirect_http']); +} + function mod_config($board_config = false) { global $config, $mod, $board; diff --git a/mod.php b/mod.php index fc44d004..869d6af9 100644 --- a/mod.php +++ b/mod.php @@ -85,18 +85,20 @@ $pages = array( '/search' => 'search_redirect', // search '/search/(posts|IP_notes|bans|log)/(.+)/(\d+)' => 'search', // search '/search/(posts|IP_notes|bans|log)/(.+)' => 'search', // search - - '/(\%b)/ban(&delete)?/(\d+)' => 'secure_POST ban_post', // ban poster - '/(\%b)/move/(\d+)' => 'secure_POST move', // move thread - '/(\%b)/move_reply/(\d+)' => 'secure_POST move_reply', // move reply - '/(\%b)/edit(_raw)?/(\d+)' => 'secure_POST edit_post', // edit post - '/(\%b)/delete/(\d+)' => 'secure delete', // delete post - '/(\%b)/deletefile/(\d+)/(\d+)' => 'secure deletefile', // delete file from post - '/(\%b+)/spoiler/(\d+)/(\d+)' => 'secure spoiler_image', // spoiler file - '/(\%b)/deletebyip/(\d+)(/global)?' => 'secure deletebyip', // delete all posts by IP address - '/(\%b)/(un)?lock/(\d+)' => 'secure lock', // lock thread - '/(\%b)/(un)?sticky/(\d+)' => 'secure sticky', // sticky thread - '/(\%b)/bump(un)?lock/(\d+)' => 'secure bumplock', // "bumplock" thread + + // Content management + '/(\%b)/ban(&delete)?/(\d+)' => 'secure_POST ban_post', // ban poster + '/(\%b)/move/(\d+)' => 'secure_POST move', // move thread + '/(\%b)/move_reply/(\d+)' => 'secure_POST move_reply', // move reply + '/(\%b)/edit(_raw)?/(\d+)' => 'secure_POST edit_post', // edit post + '/(\%b)/delete/(\d+)' => 'secure delete', // delete post + '/(\%b)/deletefile/(\d+)/(\d+)' => 'secure deletefile', // delete file from post + '/(\%b+)/spoiler/(\d+)/(\d+)' => 'secure spoiler_image', // spoiler file + '/(\%b)/deletebyip/(\d+)(/global)?' => 'secure deletebyip', // delete all posts by IP address + '/(\%b)/(un)?lock/(\d+)' => 'secure lock', // lock thread + '/(\%b)/(un)?sticky/(\d+)' => 'secure sticky', // sticky thread + '/(\%b)/bump(un)?lock/(\d+)' => 'secure bumplock', // "bumplock" thread + '/(\%b)/(un)?clean/(\d+)/(global)?(?:\+)?(local)?' => 'secure clean', // protect/unprotect from reports '/themes' => 'themes_list', // manage themes '/themes/(\w+)' => 'secure_POST theme_configure', // configure/reconfigure theme diff --git a/stylesheets/style.css b/stylesheets/style.css index eb779912..61bc07a5 100644 --- a/stylesheets/style.css +++ b/stylesheets/style.css @@ -288,6 +288,18 @@ div.post.reply { max-width: 94%!important; } +div.post_modified { + font-size: 10px; + min-width: 47.5em; + margin-left: 1.8em; + padding-top: 0.8em; +} + +div.post_modified div.content-status { + margin-top: 0.4em; + padding-bottom: 0em; +} + span.trip { color: #228854; } diff --git a/templates/mod/report.html b/templates/mod/report.html index e3b79d07..5d07e0eb 100644 --- a/templates/mod/report.html +++ b/templates/mod/report.html @@ -1,5 +1,5 @@
  • -
    +
    {% if report.reason %}{{ report.reason }}{% else %}{% trans 'No reason given.' %}{% endif %}
      diff --git a/templates/mod/report_content.html b/templates/mod/report_content.html index 102781dc..e6fff9bd 100644 --- a/templates/mod/report_content.html +++ b/templates/mod/report_content.html @@ -6,6 +6,13 @@
        + {% if mod|hasPermission(config.mod.report_dismiss_content, report.board) %} + +
      • + Dismiss All +
      • + {% endif %} + {% if global and mod|hasPermission(config.mod.report_demote, report.board) %}
      • @@ -26,31 +33,23 @@
      • {% endif %} - {% if mod|hasPermission(config.mod.report_dismiss_post, report.board) %} - + {% if mod|hasPermission(config.mod.clean, report.board) or mod|hasPermission(config.mod.clean_global, report.board) %}
      • - Dismiss All -
      • - {% endif %} - - {% if mod|hasPermission(config.mod.report_content_clean, report.board) %} - -
      • - Clean (/{{ content_board }}/) -
      • - {% endif %} - - {% if mod|hasPermission(config.mod.report_content_clean_global, report.board) %} - -
      • - Clean (Global) -
      • - {% endif %} - - {% if mod|hasPermission(config.mod.report_content_clean, report.board) and mod|hasPermission(config.mod.report_content_clean_global, report.board) %} - -
      • - Clean (/{{ content_board }}/+Global) + Clean  + {% if mod|hasPermission(config.mod.clean, report.board) %} + + (/{{ content_board }}/) + {% endif %} + {% if mod|hasPermission(config.mod.clean_global, report.board) %} +   + + (Global) +   + {% if mod|hasPermission(config.mod.clean, report.board) and mod|hasPermission(config.mod.clean_global, report.board) %} + + (/{{ content_board }}/+Global) + {% endif %} + {% endif %}
      • {% endif %}
      diff --git a/templates/post/edited_at.html b/templates/post/edited_at.html index ac49fc81..4c55a8d4 100644 --- a/templates/post/edited_at.html +++ b/templates/post/edited_at.html @@ -1,4 +1,11 @@ -{% if post.edited_at %} -
      - Post last edited at {{ post.edited_at }} -{% endif %} +
      + {% if post.edited_at %} +
      {% trans 'Post last edited at' %} {{ post.edited_at }}
      + {% endif %} + {% if clean.clean_local == '1' %} +
      {% trans 'Board rules permit this content' %}
      + {% endif %} + {% if clean.clean_global == '1' %} +
      {% trans 'Global rules permit this content' %}
      + {% endif %} +
      \ No newline at end of file diff --git a/templates/post_reply.html b/templates/post_reply.html index 9a32f403..4455a575 100644 --- a/templates/post_reply.html +++ b/templates/post_reply.html @@ -22,8 +22,8 @@ {% if post.modifiers['ban message'] %} {{ config.mod.ban_message|sprintf(post.modifiers['ban message']) }} {% endif %} - {% include 'post/edited_at.html' %}
    + {% include 'post/edited_at.html' %}

    {% endfilter %} diff --git a/templates/post_thread.html b/templates/post_thread.html index 771f5ce0..33e953ee 100644 --- a/templates/post_thread.html +++ b/templates/post_thread.html @@ -55,7 +55,6 @@ {% if post.modifiers['ban message'] %} {{ config.mod.ban_message|sprintf(post.modifiers['ban message']) }} {% endif %} - {% include 'post/edited_at.html' %} {% if post.omitted or post.omitted_images %} @@ -78,6 +77,7 @@ {% endif %} {% trans %}omitted. Click reply to view.{% endtrans %} {% endif %} + {% include 'post/edited_at.html' %} {% if not index %} {% endif %} {% endfilter %}