b2evolution PHP Cross Reference Blogging Systems

Source: /inc/antispam/antispam.ctrl.php - 575 lines - 18334 bytes - Text - Print

Description: This file implements the UI controller for the antispam management.

   1  <?php
   2  /**
   3   * This file implements the UI controller for the antispam management.
   4   *
   5   * This file is part of the b2evolution/evocms project - {@link http://b2evolution.net/}.
   6   * See also {@link http://sourceforge.net/projects/evocms/}.
   7   *
   8   * @copyright (c)2003-2014 by Francois PLANQUE - {@link http://fplanque.net/}.
   9   * Parts of this file are copyright (c)2004 by Vegar BERG GULDAL - {@link http://funky-m.com/}.
  10   *
  11   * @license http://b2evolution.net/about/license.html GNU General Public License (GPL)
  12   *
  13   * {@internal Open Source relicensing agreement:
  14   * Daniel HAHLER grants Francois PLANQUE the right to license
  15   * Daniel HAHLER's contributions to this file and the b2evolution project
  16   * under any OSI approved OSS license (http://www.opensource.org/licenses/).
  17   * Vegar BERG GULDAL grants Francois PLANQUE the right to license
  18   * Vegar BERG GULDAL's contributions to this file and the b2evolution project
  19   * under any OSI approved OSS license (http://www.opensource.org/licenses/).
  20   * Halton STEWART grants Francois PLANQUE the right to license
  21   * Halton STEWART's contributions to this file and the b2evolution project
  22   * under any OSI approved OSS license (http://www.opensource.org/licenses/).
  23   * }}
  24   *
  25   * @package admin
  26   *
  27   * {@internal Below is a list of authors who have contributed to design/coding of this file: }}
  28   * @author blueyed: Daniel HAHLER.
  29   * @author fplanque: Francois PLANQUE.
  30   * @author vegarg: Vegar BERG GULDAL.
  31   * @author halton: Halton STEWART.
  32   *
  33   * @todo Allow applying / re-checking of the known data, not just after an update!
  34   *
  35   * @version $Id: antispam.ctrl.php 6136 2014-03-08 07:59:48Z manuel $
  36   */
  37  if( !defined('EVO_MAIN_INIT') ) die( 'Please, do not access this page directly.' );
  38  
  39  param( 'display_mode', 'string' );
  40  
  41  if( $display_mode != 'js' )
  42  {
  43      $AdminUI->set_path( 'options', 'antispam' );
  44  }
  45  else
  46  {    // This is an Ajax response
  47      // fp> TODO: have a more systematic way of handling AJAX responses
  48      header_content_type( 'text/html', $io_charset );
  49  }
  50  
  51  param_action( '' );
  52  param( 'confirm', 'string' );
  53  param( 'keyword', 'string', '', true );
  54  param( 'domain', 'string' );
  55  param( 'filteron', 'string', '', true );
  56  param( 'filter', 'array/string', array() );
  57  
  58  $tab3 = param( 'tab3', 'string', '', true );
  59  $tool = param( 'tool', 'string', '', true );
  60  
  61  if( isset($filter['off']) )
  62  {
  63      unset( $filteron );
  64      forget_param( 'filteron' );
  65  }
  66  
  67  // Check permission:
  68  $current_User->check_perm( 'spamblacklist', 'view', true );
  69  
  70  
  71  if( param( 'iprange_ID', 'integer', '', true) )
  72  {    // Load IP Range object
  73      load_class( 'antispam/model/_iprange.class.php', 'IPRange' );
  74      $IPRangeCache = & get_IPRangeCache();
  75      if( ( $edited_IPRange = & $IPRangeCache->get_by_ID( $iprange_ID, false ) ) === false )
  76      {    // We could not find the goal to edit:
  77          unset( $edited_IPRange );
  78          forget_param( 'iprange_ID' );
  79          $Messages->add( sprintf( T_('Requested &laquo;%s&raquo; object does not exist any longer.'), T_('IP Range') ), 'error' );
  80      }
  81  }
  82  
  83  switch( $action )
  84  {
  85      case 'ban': // only an action if further "actions" given
  86          // Check that this action request is not a CSRF hacked request:
  87          $Session->assert_received_crumb( 'antispam' );
  88  
  89          // Check permission:
  90          $current_User->check_perm( 'spamblacklist', 'edit', true ); // TODO: This should become different for 'edit'/'add' perm level - check for 'add' here.
  91  
  92          $keyword = evo_substr( $keyword, 0, 80 );
  93          param( 'delhits', 'integer', 0 );
  94          $all_statuses = get_visibility_statuses( 'keys', array( 'trash', 'redirected' ) );
  95          $delstatuses = array();
  96          foreach( $all_statuses as $status )
  97          { // collect which comments should be delteded
  98              if( param( 'del'.$status, 'integer', 0 ) )
  99              { // matching comments with this status should be deleted
 100                  $delstatuses[] = $status;
 101              }
 102          }
 103          $delcomments = count( $delstatuses );
 104          param( 'blacklist_locally', 'integer', 0 );
 105          param( 'report', 'integer', 0 );
 106  
 107          // Check if the string is too short,
 108          // it has to be a minimum of 5 characters to avoid being too generic
 109          if( evo_strlen($keyword) < 5 )
 110          {
 111              $Messages->add( sprintf( T_('The keyword &laquo;%s&raquo; is too short, it has to be a minimum of 5 characters!'), htmlspecialchars($keyword) ), 'error' );
 112              break;
 113          }
 114  
 115          if( $delhits )
 116          { // Delete all banned hit-log entries
 117              $r = $DB->query('DELETE FROM T_hitlog
 118                                                  WHERE hit_referer LIKE '.$DB->quote('%'.$keyword.'%'),
 119                                                  'Delete all banned hit-log entries' );
 120  
 121              $Messages->add( sprintf( T_('Deleted %d logged hits matching &laquo;%s&raquo;.'), $r, htmlspecialchars($keyword) ), 'success' );
 122          }
 123  
 124          if( $delcomments )
 125          { // select banned comments
 126              $del_condition = blog_restrict( $delstatuses );
 127              $keyword_cond = '(comment_author LIKE '.$DB->quote('%'.$keyword.'%').'
 128                              OR comment_author_email LIKE '.$DB->quote('%'.$keyword.'%').'
 129                              OR comment_author_url LIKE '.$DB->quote('%'.$keyword.'%').'
 130                              OR comment_content LIKE '.$DB->quote('%'.$keyword.'%').')';
 131              // asimo> we don't need transaction here 
 132              if( $display_mode == 'js' )
 133              {
 134                  $query = 'SELECT comment_ID FROM T_comments
 135                                WHERE '.$keyword_cond.$del_condition;
 136                  $deleted_ids = implode( ',', $DB->get_col($query, 0, 'Get comment ids awaiting for delete') );
 137              };
 138              // asimo> If a comment whith this keyword content was inserted here, the user will not even observe that (This is good)
 139              $r = $DB->query('DELETE FROM T_comments
 140                                WHERE '.$keyword_cond.$del_condition );
 141              $Messages->add( sprintf( T_('Deleted %d comments matching &laquo;%s&raquo;.'), $r, htmlspecialchars($keyword) ), 'success' );
 142          }
 143  
 144          if( $blacklist_locally )
 145          { // Local blacklist:
 146              if( antispam_create( $keyword ) )
 147              {
 148                  $Messages->add( sprintf( T_('The keyword &laquo;%s&raquo; has been blacklisted locally.'), htmlspecialchars($keyword) ), 'success' );
 149                  // Redirect so that a reload doesn't write to the DB twice:
 150                  if( $display_mode != 'js' )
 151                  {
 152                      header_redirect( '?ctrl=antispam', 303 ); // Will EXIT
 153                      // We have EXITed already at this point!!
 154                  }
 155              }
 156              else
 157              { // TODO: message?
 158              }
 159          }
 160  
 161          if( $report )
 162          { // Report this keyword as abuse:
 163              antispam_report_abuse( $keyword );
 164          }
 165  
 166          param( 'request', 'string', '' );
 167          if( $display_mode == 'js' && $request != 'checkban' )
 168          {
 169              if( $delcomments && $r ) // $r not null => means the commentlist was deleted successfully
 170              {
 171                  send_javascript_message( array( 'refreshAfterBan' => array( $deleted_ids ), 'closeAntispamSettings' => array() ), true );
 172              }
 173              else
 174              {
 175                  send_javascript_message( array( 'closeAntispamSettings' => array() ), true );
 176              }
 177          }
 178  
 179          // We'll ask the user later what to do, if no "sub-action" given.
 180          break;
 181  
 182  
 183      case 'remove':
 184          // Remove a domain from ban list:
 185  
 186          // Check that this action request is not a CSRF hacked request:
 187          $Session->assert_received_crumb( 'antispam' );
 188  
 189          // Check permission:
 190          $current_User->check_perm( 'spamblacklist', 'edit', true );
 191  
 192          param( 'hit_ID', 'integer', true );    // Required!
 193          $Messages->add( sprintf( T_('Removing entry #%d from the ban list...'), $hit_ID), 'note' );
 194          antispam_delete( $hit_ID );
 195          break;
 196  
 197  
 198      case 'report':
 199          // Report an entry as abuse to centralized blacklist:
 200  
 201          // Check that this action request is not a CSRF hacked request:
 202          $Session->assert_received_crumb( 'antispam' );
 203  
 204          // Check permission:
 205          $current_User->check_perm( 'spamblacklist', 'edit', true );
 206  
 207          // Report this keyword as abuse:
 208          antispam_report_abuse( $keyword );
 209          break;
 210  
 211  
 212      case 'poll':
 213          // request abuse list from central blacklist:
 214  
 215          // Check that this action request is not a CSRF hacked request:
 216          $Session->assert_received_crumb( 'antispam' );
 217  
 218          // Check permission:
 219          $current_User->check_perm( 'spamblacklist', 'edit', true );
 220  
 221          ob_start();
 222          antispam_poll_abuse();
 223          $Debuglog->add( ob_get_contents(), 'antispam_poll' );
 224          ob_end_clean();
 225          break;
 226  
 227      case 'update':
 228          // Check that this action request is not a CSRF hacked request:
 229          $Session->assert_received_crumb( 'antispam' );
 230  
 231          // Check permission:
 232          $current_User->check_perm( 'options', 'edit', true );
 233  
 234          // fp> Restore defaults has been removed because it's extra maintenance work and no real benefit to the user.
 235  
 236          param_integer_range( 'antispam_threshold_publish', -100, 100, T_('The threshold must be between -100 and 100.') );
 237          $Settings->set( 'antispam_threshold_publish', $antispam_threshold_publish );
 238  
 239          param_integer_range( 'antispam_threshold_delete', -100, 100, T_('The threshold must be between -100 and 100.') );
 240          $Settings->set( 'antispam_threshold_delete', $antispam_threshold_delete );
 241  
 242          param( 'antispam_block_spam_referers', 'integer', 0 );
 243          $Settings->set( 'antispam_block_spam_referers', $antispam_block_spam_referers );
 244  
 245          param( 'antispam_report_to_central', 'integer', 0 );
 246          $Settings->set( 'antispam_report_to_central', $antispam_report_to_central );
 247  
 248          $changed_weight = false;
 249          param( 'antispam_plugin_spam_weight', 'array/integer', array() );
 250          foreach( $antispam_plugin_spam_weight as $l_plugin_ID => $l_weight )
 251          {
 252              if( ! is_numeric($l_weight) )
 253              {
 254                  continue;
 255              }
 256              if( $l_weight < 0 || $l_weight > 100 )
 257              {
 258                  param_error( 'antispam_plugin_spam_weight['.$l_plugin_ID.']', T_('Spam weight has to be in the range of 0-100.') );
 259                  continue;
 260              }
 261              if( $DB->query( '
 262                      UPDATE T_plugins
 263                           SET plug_spam_weight = '.$DB->quote($l_weight).'
 264                       WHERE plug_ID = '.(int)$l_plugin_ID ) )
 265              {
 266                  $changed_weight = true;
 267              }
 268          }
 269          if( $changed_weight )
 270          { // Reload plugins table (for display):
 271              $Plugins->loaded_plugins_table = false;
 272              $Plugins->load_plugins_table();
 273          }
 274  
 275          // Suspicious users
 276          $Settings->set( 'antispam_suspicious_group', param( 'antispam_suspicious_group', 'integer', 0 ) );
 277  
 278          // Trust groups
 279          $trust_groups = param( 'antispam_trust_groups', 'array/integer', array() );
 280          $Settings->set( 'antispam_trust_groups', implode( ',', $trust_groups ) );
 281  
 282          if( ! $Messages->has_errors() )
 283          {
 284              $Settings->dbupdate();
 285  
 286              $Messages->add( T_('Settings updated.'), 'success' );
 287              // Redirect so that a reload doesn't write to the DB twice:
 288              header_redirect( '?ctrl=antispam&tab3=settings', 303 ); // Will EXIT
 289              // We have EXITed already at this point!!
 290          }
 291  
 292      case 'find_spam_comments':
 293          // Check that this action request is not a CSRF hacked request:
 294          $Session->assert_received_crumb( 'antispam' );
 295  
 296          // Check permission:
 297          $current_User->check_perm( 'options', 'edit', true );
 298  
 299          $keywords = $DB->get_col('SELECT aspm_string FROM T_antispam');
 300          $keywords = array_chunk( $keywords, 100 );
 301          $rows_affected = 0;
 302  
 303          @ignore_user_abort(true);
 304          set_max_execution_time(900);
 305  
 306          // Delete comments in chunks of 100 keywords per SQL query
 307          foreach( $keywords as $chunk )
 308          {
 309              $arr = array();
 310              foreach( $chunk as $word )
 311              {
 312                  $arr[] = $DB->quote('%'.$word.'%');
 313              }
 314  
 315              $DB->query('DELETE FROM T_comments
 316                          WHERE (comment_author LIKE '.implode(' OR comment_author LIKE ', $arr).')
 317                          OR (comment_author_email LIKE '.implode(' OR comment_author_email LIKE ', $arr).')
 318                          OR (comment_author_url LIKE '.implode(' OR comment_author_url LIKE ', $arr).')
 319                          OR (comment_content LIKE '.implode(' OR comment_content LIKE ', $arr).')',
 320                          'Delete spam comments');
 321  
 322              $rows_affected = $rows_affected + $DB->rows_affected;
 323          }
 324          $Messages->add( sprintf( T_('Deleted %d comments'), $rows_affected ), 'success' );
 325          break;
 326  
 327      case 'find_spam_referers':
 328          // Check that this action request is not a CSRF hacked request:
 329          $Session->assert_received_crumb( 'antispam' );
 330  
 331          // Check permission:
 332          $current_User->check_perm( 'options', 'edit', true );
 333  
 334          $keywords = $DB->get_col('SELECT aspm_string FROM T_antispam');
 335          $keywords = array_chunk( $keywords, 100 );
 336          $rows_affected = 0;
 337  
 338          @ignore_user_abort(true);
 339          set_max_execution_time(900);
 340  
 341          // Delete hits in chunks of 100 keywords per SQL query
 342          foreach( $keywords as $chunk )
 343          {
 344              $arr = array();
 345              foreach( $chunk as $word )
 346              {
 347                  $arr[] = $DB->quote('%'.$word.'%');
 348              }
 349  
 350              $DB->query('DELETE FROM T_hitlog
 351                          WHERE hit_referer LIKE '.implode(' OR hit_referer LIKE ', $arr),
 352                          'Delete all banned hit-log entries' );
 353  
 354              $rows_affected = $rows_affected + $DB->rows_affected;
 355          }
 356          $Messages->add( sprintf( T_('Deleted %d logged hits'), $rows_affected ), 'success' );
 357          break;
 358  
 359      case 'iprange_create':
 360          // Create new IP Range...
 361  
 362          // Check that this action request is not a CSRF hacked request:
 363          $Session->assert_received_crumb( 'iprange' );
 364  
 365          // Check permission:
 366          $current_User->check_perm( 'spamblacklist', 'edit', true );
 367  
 368          $edited_IPRange = new IPRange();
 369  
 370          // load data from request
 371          if( $edited_IPRange->load_from_Request() )
 372          {    // We could load data from form without errors:
 373              // Insert in DB:
 374              $edited_IPRange->dbinsert();
 375              $Messages->add( T_('New IP Range created.'), 'success' );
 376  
 377              // Redirect so that a reload doesn't write to the DB twice:
 378              header_redirect( '?ctrl=antispam&tab3=ipranges', 303 ); // Will EXIT
 379              // We have EXITed already at this point!!
 380          }
 381          $action = 'iprange_new';
 382          break;
 383  
 384      case 'iprange_update':
 385          // Update IP Range...
 386  
 387          // Check that this action request is not a CSRF hacked request:
 388          $Session->assert_received_crumb( 'iprange' );
 389  
 390          // Check permission:
 391          $current_User->check_perm( 'spamblacklist', 'edit', true );
 392  
 393          // Make sure we got an iprange_ID:
 394          param( 'iprange_ID', 'integer', true );
 395  
 396          // load data from request
 397          if( $edited_IPRange->load_from_Request() )
 398          {    // We could load data from form without errors:
 399              // Update IP Range in DB:
 400              $edited_IPRange->dbupdate();
 401              $Messages->add( T_('IP Range updated.'), 'success' );
 402  
 403              // Redirect so that a reload doesn't write to the DB twice:
 404              header_redirect( '?ctrl=antispam&tab3=ipranges', 303 ); // Will EXIT
 405              // We have EXITed already at this point!!
 406          }
 407          $action = 'iprange_edit';
 408          break;
 409  
 410      case 'iprange_delete':
 411          // Delete IP Range...
 412  
 413          // Check that this action request is not a CSRF hacked request:
 414          $Session->assert_received_crumb( 'iprange' );
 415  
 416          // Check permission:
 417          $current_User->check_perm( 'spamblacklist', 'edit', true );
 418  
 419          // Make sure we got an iprange_ID:
 420          param( 'iprange_ID', 'integer', true );
 421  
 422          if( $edited_IPRange->dbdelete() )
 423          {
 424              $Messages->add( T_('IP Range deleted.'), 'success' );
 425  
 426              // Redirect so that a reload doesn't write to the DB twice:
 427              header_redirect( '?ctrl=antispam&tab3=ipranges', 303 ); // Will EXIT
 428              // We have EXITed already at this point!!
 429          }
 430          break;
 431  
 432      case 'bankruptcy_delete':
 433          // Delete ALL comments from selected blogs
 434  
 435          // Check that this action request is not a CSRF hacked request:
 436          $Session->assert_received_crumb( 'antispam' );
 437  
 438          // Check permission:
 439          $current_User->check_perm( 'options', 'edit', true );
 440  
 441          $bankruptcy_blogs_IDs = param( 'bankruptcy_blogs', 'array/integer', array() );
 442  
 443          if( empty( $bankruptcy_blogs ) )
 444          {
 445              $Messages->add( T_('Please select at least one blog.'), 'error' );
 446          }
 447  
 448          if( !param_errors_detected() )
 449          { // Try to obtain some serious time to do some serious processing (15 minutes)
 450              set_max_execution_time( 900 );
 451              // Turn off the output buffering to do the correct work of the function flush()
 452              @ini_set( 'output_buffering', 'off' );
 453              // Set this to start deleting in the template file
 454              $delete_bankruptcy_blogs = true;
 455          }
 456          break;
 457  }
 458  
 459  if( $display_mode != 'js')
 460  {
 461      $AdminUI->breadcrumbpath_init( false );  // fp> I'm playing with the idea of keeping the current blog in the path here...
 462      $AdminUI->breadcrumbpath_add( T_('System'), '?ctrl=system' );
 463      $AdminUI->breadcrumbpath_add( T_('Antispam'), '?ctrl=antispam' );
 464  
 465      if( empty($tab3) )
 466      {
 467          $tab3 = 'blacklist';
 468      }
 469      switch( $tab3 )
 470      {
 471          case 'settings':
 472              $AdminUI->breadcrumbpath_add( T_('Settings'), '?ctrl=antispam&amp;tab3='.$tab3 );
 473              break;
 474  
 475          case 'tools':
 476              $AdminUI->breadcrumbpath_add( T_('Tools'), '?ctrl=antispam&amp;tab3='.$tab3 );
 477              break;
 478  
 479          case 'blacklist':
 480              $AdminUI->breadcrumbpath_add( T_('Blacklist'), '?ctrl=antispam' );
 481              break;
 482  
 483          case 'ipranges':
 484              if( empty( $action ) )
 485              {    // View a list of IP ranges
 486                  require_js( 'jquery/jquery.jeditable.js', 'rsc_url' );
 487              }
 488              elseif( ! $current_User->check_perm( 'spamblacklist', 'edit' ) )
 489              {    // Check permission to create/edit IP range
 490                  $Messages->add( T_('You have no permission to edit IP range!'), 'error' );
 491                  $action = '';
 492              }
 493              $AdminUI->breadcrumbpath_add( T_('IP Ranges'), '?ctrl=antispam&amp;tab3='.$tab3 );
 494              break;
 495      }
 496  
 497      if( !empty($tab3) )
 498      {
 499          $AdminUI->append_path_level( $tab3 );
 500      }
 501  
 502      // Display <html><head>...</head> section! (Note: should be done early if actions do not redirect)
 503      $AdminUI->disp_html_head();
 504      
 505      // Display title, menu, messages, etc. (Note: messages MUST be displayed AFTER the actions)
 506      $AdminUI->disp_body_top();
 507  
 508      // Begin payload block:
 509      $AdminUI->disp_payload_begin();
 510  }
 511  
 512  switch( $tab3 )
 513  {
 514      case 'settings':
 515          $AdminUI->disp_view( 'antispam/views/_antispam_settings.form.php' );
 516          break;
 517  
 518      case 'tools':
 519          // Check permission:
 520          $current_User->check_perm( 'options', 'edit', true );
 521  
 522          switch( $tool )
 523          {
 524              case 'bankruptcy':
 525                  $comment_status = param( 'comment_status', 'string', 'draft' );
 526                  $AdminUI->disp_view( 'antispam/views/_antispam_tools_bankruptcy.view.php' );
 527                  break;
 528  
 529              default:
 530                  $AdminUI->disp_view( 'antispam/views/_antispam_tools.view.php' );
 531                  break;
 532          }
 533          break;
 534  
 535      case 'ipranges':
 536          switch( $action )
 537          {
 538              case 'iprange_new':
 539                  $edited_IPRange = new IPRange();
 540                  $AdminUI->disp_view( 'antispam/views/_antispam_ipranges.form.php' );
 541                  break;
 542  
 543              case 'iprange_edit':
 544                  $AdminUI->disp_view( 'antispam/views/_antispam_ipranges.form.php' );
 545                  break;
 546  
 547              default:    // View list of the IP Ranges
 548                  $AdminUI->disp_view( 'antispam/views/_antispam_ipranges.view.php' );
 549                  break;
 550          }
 551          break;
 552  
 553      case 'blacklist':
 554      default:
 555          if( $action == 'ban' && !$Messages->has_errors() && !( $delhits || $delcomments || $blacklist_locally || $report ) )
 556          {    // Nothing to do, ask user:
 557              $AdminUI->disp_view( 'antispam/views/_antispam_ban.form.php' );
 558          }
 559          else
 560          {    // Display blacklist:
 561              $AdminUI->disp_view( 'antispam/views/_antispam_list.view.php' );
 562          }
 563          break;
 564  }
 565  
 566  // End payload block:
 567  if( $display_mode != 'js')
 568  {
 569      $AdminUI->disp_payload_end();
 570  
 571      // Display body bottom, debug info and close </html>:
 572      $AdminUI->disp_global_footer();
 573  }
 574  
 575  ?>

title

Description

title

Description

title

Description

title

title

Body