[ Index ]
 

Code source de Serendipity 1.2

Accédez au Source d'autres logiciels libres

title

Body

[fermer]

/plugins/serendipity_event_spamblock/ -> serendipity_event_spamblock.php (source)

   1  <?php # $Id: serendipity_event_spamblock.php 1845 2007-08-13 08:03:44Z garvinhicking $
   2  
   3  
   4  if (IN_serendipity !== true) {
   5      die ("Don't hack!");
   6  }
   7  
   8  // Probe for a language include with constants. Still include defines later on, if some constants were missing
   9  $probelang = dirname(__FILE__) . '/' . $serendipity['charset'] . 'lang_' . $serendipity['lang'] . '.inc.php';
  10  if (file_exists($probelang)) {
  11      include $probelang;
  12  }
  13  
  14  include dirname(__FILE__) . '/lang_en.inc.php';
  15  
  16  /* BC - TODO: Remove for 0.8 final */
  17  if (!function_exists('serendipity_serverOffsetHour')) {
  18      function serendipity_serverOffsetHour() {
  19          return time();
  20      }
  21  }
  22  
  23  class serendipity_event_spamblock extends serendipity_event
  24  {
  25  var $filter_defaults;
  26  
  27      function introspect(&$propbag)
  28      {
  29          global $serendipity;
  30  
  31          $this->title = PLUGIN_EVENT_SPAMBLOCK_TITLE;
  32  
  33          $propbag->add('name',          PLUGIN_EVENT_SPAMBLOCK_TITLE);
  34          $propbag->add('description',   PLUGIN_EVENT_SPAMBLOCK_DESC);
  35          $propbag->add('stackable',     false);
  36          $propbag->add('author',        'Garvin Hicking, Sebastian Nohn');
  37          $propbag->add('requirements',  array(
  38              'serendipity' => '0.8',
  39              'smarty'      => '2.6.7',
  40              'php'         => '4.1.0'
  41          ));
  42          $propbag->add('version',       '1.68');
  43          $propbag->add('event_hooks',    array(
  44              'frontend_saveComment' => true,
  45              'external_plugin'      => true,
  46              'frontend_comment'     => true,
  47              'fetchcomments'        => true,
  48              'backend_comments_top' => true,
  49              'backend_view_comment' => true
  50          ));
  51          $propbag->add('configuration', array(
  52              'killswitch',
  53              'hide_for_authors',
  54              'bodyclone',
  55              'entrytitle',
  56              'ipflood',
  57              'csrf',
  58              'captchas',
  59              'captchas_ttl',
  60              'captcha_color',
  61              'forcemoderation',
  62              'forcemoderation_treat',
  63              'forcemoderationt',
  64              'forcemoderationt_treat',
  65              'disable_api_comments',
  66              'trackback_check_url',
  67              'links_moderate',
  68              'links_reject',
  69              'contentfilter_activate',
  70              'contentfilter_urls',
  71              'contentfilter_authors',
  72              'contentfilter_words',
  73              'contentfilter_emails',
  74              'bloggdeblacklist',
  75              'akismet',
  76              'akismet_filter',
  77              'hide_email',
  78              'checkmail',
  79              'required_fields',
  80              'automagic_htaccess',
  81              'logtype',
  82              'logfile'));
  83          $propbag->add('groups', array('ANTISPAM'));
  84  
  85          $this->filter_defaults = array(
  86                                     'authors' => 'casino;phentermine;credit;loans;poker',
  87                                     'emails'  => '',
  88                                     'urls'    => '8gold\.com;911easymoney\.com;canadianlabels\.net;condodream\.com;crepesuzette\.com;debt-help-bill-consolidation-elimination\.com;fidelityfunding\.net;flafeber\.com;gb\.com;houseofsevengables\.com;instant-quick-money-cash-advance-personal-loans-until-pay-day\.com;mediavisor\.com;newtruths\.com;oiline\.com;onlinegamingassociation\.com;online\-+poker\.com;popwow\.com;royalmailhotel\.com;spoodles\.com;sportsparent\.com;stmaryonline\.org;thatwhichis\.com;tmsathai\.org;uaeecommerce\.com;learnhowtoplay\.com',
  89                                     'words'   => 'very good site!;Real good stuff!'
  90          );
  91      }
  92  
  93      function introspect_config_item($name, &$propbag)
  94      {
  95          global $serendipity;
  96  
  97          switch($name) {
  98              case 'disable_api_comments':
  99                  $propbag->add('type', 'radio');
 100                  $propbag->add('name', PLUGIN_EVENT_SPAMBLOCK_API_COMMENTS);
 101                  $propbag->add('description', PLUGIN_EVENT_SPAMBLOCK_API_COMMENTS_DESC);
 102                  $propbag->add('default', 'none');
 103                  $propbag->add('radio', array(
 104                      'value' => array('moderate', 'reject', 'none'),
 105                      'desc'  => array(PLUGIN_EVENT_SPAMBLOCK_API_MODERATE, PLUGIN_EVENT_SPAMBLOCK_API_REJECT, NONE)
 106                  ));
 107                  $propbag->add('radio_per_row', '1');
 108  
 109                  break;
 110  
 111              case 'trackback_check_url':
 112                  $propbag->add('type', 'boolean');
 113                  $propbag->add('name', PLUGIN_EVENT_SPAMBLOCK_TRACKBACKURL);
 114                  $propbag->add('description', PLUGIN_EVENT_SPAMBLOCK_TRACKBACKURL_DESC);
 115                  $propbag->add('default', false);
 116                  break;
 117  
 118              case 'automagic_htaccess':
 119                  $propbag->add('type', 'boolean');
 120                  $propbag->add('name', PLUGIN_EVENT_SPAMBLOCK_HTACCESS);
 121                  $propbag->add('description', PLUGIN_EVENT_SPAMBLOCK_HTACCESS_DESC);
 122                  $propbag->add('default', false);
 123                  break;
 124  
 125              case 'hide_email':
 126                  $propbag->add('type', 'boolean');
 127                  $propbag->add('name', PLUGIN_EVENT_SPAMBLOCK_HIDE_EMAIL);
 128                  $propbag->add('description', PLUGIN_EVENT_SPAMBLOCK_HIDE_EMAIL_DESC);
 129                  $propbag->add('default', false);
 130                  break;
 131  
 132              case 'csrf':
 133                  $propbag->add('type', 'boolean');
 134                  $propbag->add('name', PLUGIN_EVENT_SPAMBLOCK_CSRF);
 135                  $propbag->add('description', PLUGIN_EVENT_SPAMBLOCK_CSRF_DESC);
 136                  $propbag->add('default', true);
 137                  break;
 138  
 139              case 'entrytitle':
 140                  $propbag->add('type', 'boolean');
 141                  $propbag->add('name', PLUGIN_EVENT_SPAMBLOCK_FILTER_TITLE);
 142                  $propbag->add('description', '');
 143                  $propbag->add('default', false);
 144                  break;
 145  
 146              case 'checkmail':
 147                  $propbag->add('type', 'boolean');
 148                  $propbag->add('name', PLUGIN_EVENT_SPAMBLOCK_CHECKMAIL);
 149                  $propbag->add('description', '');
 150                  $propbag->add('default', false);
 151                  break;
 152  
 153              case 'required_fields':
 154                  $propbag->add('type', 'string');
 155                  $propbag->add('name', PLUGIN_EVENT_SPAMBLOCK_REQUIRED_FIELDS);
 156                  $propbag->add('description', PLUGIN_EVENT_SPAMBLOCK_REQUIRED_FIELDS_DESC);
 157                  $propbag->add('default', '');
 158                  break;
 159  
 160              case 'bodyclone':
 161                  $propbag->add('type', 'boolean');
 162                  $propbag->add('name', PLUGIN_EVENT_SPAMBLOCK_BODYCLONE);
 163                  $propbag->add('description', PLUGIN_EVENT_SPAMBLOCK_BODYCLONE_DESC);
 164                  $propbag->add('default', true);
 165                  break;
 166  
 167              case 'captchas':
 168                  $propbag->add('type', 'radio');
 169                  $propbag->add('name', PLUGIN_EVENT_SPAMBLOCK_CAPTCHAS);
 170                  $propbag->add('description', PLUGIN_EVENT_SPAMBLOCK_CAPTCHAS_DESC);
 171                  $propbag->add('default', 'yes');
 172                  $propbag->add('radio', array(
 173                      'value' => array(true, 'no', 'scramble'),
 174                      'desc'  => array(YES, NO, PLUGIN_EVENT_SPAMBLOCK_CAPTCHAS_SCRAMBLE)
 175                  ));
 176                  break;
 177  
 178              case 'hide_for_authors':
 179                  $_groups =& serendipity_getAllGroups();
 180                  $groups = array(
 181                      'all'  => ALL_AUTHORS,
 182                      'none' => NONE
 183                  );
 184  
 185                  foreach($_groups AS $group) {
 186                      $groups[$group['confkey']] = $group['confvalue'];
 187                  }
 188  
 189                  $propbag->add('type', 'multiselect');
 190                  $propbag->add('name', PLUGIN_EVENT_SPAMBLOCK_HIDE);
 191                  $propbag->add('description', PLUGIN_EVENT_SPAMBLOCK_HIDE_DESC);
 192                  $propbag->add('select_values', $groups);
 193                  $propbag->add('select_size',   5);
 194                  $propbag->add('default', 'all');
 195                  break;
 196  
 197              case 'killswitch':
 198                  $propbag->add('type', 'boolean');
 199                  $propbag->add('name', PLUGIN_EVENT_SPAMBLOCK_KILLSWITCH);
 200                  $propbag->add('description', PLUGIN_EVENT_SPAMBLOCK_KILLSWITCH_DESC);
 201                  $propbag->add('default', false);
 202                  break;
 203  
 204              case 'contentfilter_activate':
 205                  $propbag->add('type', 'radio');
 206                  $propbag->add('name', PLUGIN_EVENT_SPAMBLOCK_FILTER_ACTIVATE);
 207                  $propbag->add('description', PLUGIN_EVENT_SPAMBLOCK_FILTER_ACTIVATE_DESC);
 208                  $propbag->add('default', 'moderate');
 209                  $propbag->add('radio', array(
 210                      'value' => array('moderate', 'reject', 'none'),
 211                      'desc'  => array(PLUGIN_EVENT_SPAMBLOCK_API_MODERATE, PLUGIN_EVENT_SPAMBLOCK_API_REJECT, NONE)
 212                  ));
 213                  $propbag->add('radio_per_row', '1');
 214  
 215                  break;
 216  
 217              case 'bloggdeblacklist':
 218                  $propbag->add('type', 'radio');
 219                  $propbag->add('name', PLUGIN_EVENT_SPAMBLOCK_BLOGG_SPAMLIST);
 220                  $propbag->add('description', '');
 221                  $propbag->add('default', 'none');
 222                  $propbag->add('radio', array(
 223                      'value' => array('moderate', 'reject', 'none'),
 224                      'desc'  => array(PLUGIN_EVENT_SPAMBLOCK_API_MODERATE, PLUGIN_EVENT_SPAMBLOCK_API_REJECT, NONE)
 225                  ));
 226                  $propbag->add('radio_per_row', '1');
 227  
 228                  break;
 229  
 230              case 'akismet':
 231                  $propbag->add('type', 'string');
 232                  $propbag->add('name', PLUGIN_EVENT_SPAMBLOCK_AKISMET);
 233                  $propbag->add('description', PLUGIN_EVENT_SPAMBLOCK_AKISMET_DESC);
 234                  $propbag->add('default', '');
 235                  $propbag->add('radio', array(
 236                      'value' => array('moderate', 'reject', 'none'),
 237                      'desc'  => array(PLUGIN_EVENT_SPAMBLOCK_API_MODERATE, PLUGIN_EVENT_SPAMBLOCK_API_REJECT, NONE)
 238                  ));
 239                  $propbag->add('radio_per_row', '1');
 240  
 241                  break;
 242  
 243              case 'akismet_filter':
 244                  $propbag->add('type', 'radio');
 245                  $propbag->add('name', PLUGIN_EVENT_SPAMBLOCK_AKISMET_FILTER);
 246                  $propbag->add('description', '');
 247                  $propbag->add('default', 'reject');
 248                  $propbag->add('radio', array(
 249                      'value' => array('moderate', 'reject', 'none'),
 250                      'desc'  => array(PLUGIN_EVENT_SPAMBLOCK_API_MODERATE, PLUGIN_EVENT_SPAMBLOCK_API_REJECT, NONE)
 251                  ));
 252                  $propbag->add('radio_per_row', '1');
 253  
 254                  break;
 255  
 256              case 'contentfilter_urls':
 257                  $propbag->add('type', 'text');
 258                  $propbag->add('name', PLUGIN_EVENT_SPAMBLOCK_FILTER_URLS);
 259                  $propbag->add('description', PLUGIN_EVENT_SPAMBLOCK_FILTER_URLS_DESC);
 260                  $propbag->add('default', $this->filter_defaults['urls']);
 261                  break;
 262  
 263              case 'contentfilter_authors':
 264                  $propbag->add('type', 'text');
 265                  $propbag->add('name', PLUGIN_EVENT_SPAMBLOCK_FILTER_AUTHORS);
 266                  $propbag->add('description', PLUGIN_EVENT_SPAMBLOCK_FILTER_AUTHORS_DESC);
 267                  $propbag->add('default', $this->filter_defaults['authors']);
 268                  break;
 269  
 270              case 'contentfilter_words':
 271                  $propbag->add('type', 'text');
 272                  $propbag->add('name', PLUGIN_EVENT_SPAMBLOCK_FILTER_WORDS);
 273                  $propbag->add('description', PLUGIN_EVENT_SPAMBLOCK_FILTER_AUTHORS_DESC);
 274                  $propbag->add('default', $this->filter_defaults['words']);
 275                  break;
 276  
 277              case 'contentfilter_emails':
 278                  $propbag->add('type', 'text');
 279                  $propbag->add('name', PLUGIN_EVENT_SPAMBLOCK_FILTER_EMAILS);
 280                  $propbag->add('description', PLUGIN_EVENT_SPAMBLOCK_FILTER_AUTHORS_DESC);
 281                  $propbag->add('default', $this->filter_defaults['emails']);
 282                  break;
 283  
 284              case 'logfile':
 285                  $propbag->add('type', 'string');
 286                  $propbag->add('name', PLUGIN_EVENT_SPAMBLOCK_LOGFILE);
 287                  $propbag->add('description', PLUGIN_EVENT_SPAMBLOCK_LOGFILE_DESC);
 288                  $propbag->add('default', $serendipity['serendipityPath'] . 'spamblock.log');
 289                  break;
 290  
 291              case 'logtype':
 292                  $propbag->add('type', 'radio');
 293                  $propbag->add('name', PLUGIN_EVENT_SPAMBLOCK_LOGTYPE);
 294                  $propbag->add('description', PLUGIN_EVENT_SPAMBLOCK_LOGTYPE_DESC);
 295                  $propbag->add('default', 'db');
 296                  $propbag->add('radio',         array(
 297                      'value' => array('file', 'db', 'none'),
 298                      'desc'  => array(PLUGIN_EVENT_SPAMBLOCK_LOGTYPE_FILE, PLUGIN_EVENT_SPAMBLOCK_LOGTYPE_DB, PLUGIN_EVENT_SPAMBLOCK_LOGTYPE_NONE)
 299                  ));
 300                  $propbag->add('radio_per_row', '1');
 301  
 302                  break;
 303  
 304              case 'ipflood':
 305                  $propbag->add('type', 'string');
 306                  $propbag->add('name', PLUGIN_EVENT_SPAMBLOCK_IPFLOOD);
 307                  $propbag->add('description', PLUGIN_EVENT_SPAMBLOCK_IPFLOOD_DESC);
 308                  $propbag->add('default', 0);
 309                  break;
 310  
 311              case 'captchas_ttl':
 312                  $propbag->add('type', 'string');
 313                  $propbag->add('name', PLUGIN_EVENT_SPAMBLOCK_CAPTCHAS_TTL);
 314                  $propbag->add('description', PLUGIN_EVENT_SPAMBLOCK_CAPTCHAS_TTL_DESC);
 315                  $propbag->add('default', '7');
 316                  break;
 317  
 318              case 'captcha_color':
 319                  $propbag->add('type', 'string');
 320                  $propbag->add('name', PLUGIN_EVENT_SPAMBLOCK_CAPTCHA_COLOR);
 321                  $propbag->add('description', PLUGIN_EVENT_SPAMBLOCK_CAPTCHA_COLOR_DESC);
 322                  $propbag->add('default', '255,255,255');
 323                  $propbag->add('validate', '@^[0-9]{1,3},[0-9]{1,3},[0-9]{1,3}$@');
 324                  break;
 325  
 326              case 'forcemoderation':
 327                  $propbag->add('type', 'string');
 328                  $propbag->add('name', PLUGIN_EVENT_SPAMBLOCK_FORCEMODERATION);
 329                  $propbag->add('description', PLUGIN_EVENT_SPAMBLOCK_FORCEMODERATION_DESC);
 330                  $propbag->add('default', '30');
 331                  break;
 332  
 333              case 'forcemoderation_treat':
 334                  $propbag->add('type', 'radio');
 335                  $propbag->add('name', PLUGIN_EVENT_SPAMBLOCK_FORCEMODERATION_TREAT);
 336                  $propbag->add('description', '');
 337                  $propbag->add('default', 'moderate');
 338                  $propbag->add('radio', array(
 339                      'value' => array('moderate', 'reject'),
 340                      'desc'  => array(PLUGIN_EVENT_SPAMBLOCK_API_MODERATE, PLUGIN_EVENT_SPAMBLOCK_API_REJECT)
 341                  ));
 342                  $propbag->add('radio_per_row', '1');
 343                  break;
 344  
 345              case 'forcemoderationt':
 346                  $propbag->add('type', 'string');
 347                  $propbag->add('name', PLUGIN_EVENT_SPAMBLOCK_FORCEMODERATIONT);
 348                  $propbag->add('description', PLUGIN_EVENT_SPAMBLOCK_FORCEMODERATIONT_DESC);
 349                  $propbag->add('default', '30');
 350                  break;
 351  
 352              case 'forcemoderationt_treat':
 353                  $propbag->add('type', 'radio');
 354                  $propbag->add('name', PLUGIN_EVENT_SPAMBLOCK_FORCEMODERATIONT_TREAT);
 355                  $propbag->add('description', '');
 356                  $propbag->add('default', 'moderate');
 357                  $propbag->add('radio', array(
 358                      'value' => array('moderate', 'reject'),
 359                      'desc'  => array(PLUGIN_EVENT_SPAMBLOCK_API_MODERATE, PLUGIN_EVENT_SPAMBLOCK_API_REJECT)
 360                  ));
 361                  $propbag->add('radio_per_row', '1');
 362                  break;
 363  
 364              case 'links_moderate':
 365                  $propbag->add('type', 'string');
 366                  $propbag->add('name', PLUGIN_EVENT_SPAMBLOCK_LINKS_MODERATE);
 367                  $propbag->add('description', PLUGIN_EVENT_SPAMBLOCK_LINKS_MODERATE_DESC);
 368                  $propbag->add('default', '7');
 369                  break;
 370  
 371              case 'links_reject':
 372                  $propbag->add('type', 'string');
 373                  $propbag->add('name', PLUGIN_EVENT_SPAMBLOCK_LINKS_REJECT);
 374                  $propbag->add('description', PLUGIN_EVENT_SPAMBLOCK_LINKS_REJECT_DESC);
 375                  $propbag->add('default', '13');
 376                  break;
 377  
 378              default:
 379                      return false;
 380          }
 381  
 382          return true;
 383      }
 384  
 385      function htaccess_update($new_ip) {
 386          global $serendipity;
 387  
 388          serendipity_db_query("INSERT INTO {$serendipity['dbPrefix']}spamblock_htaccess (ip, timestamp) VALUES ('" . serendipity_db_escape_string($new_ip) . "', '" . time() . "')");
 389  
 390          $q = "SELECT ip FROM {$serendipity['dbPrefix']}spamblock_htaccess WHERE timestamp > " . (time() - 86400*2) . " GROUP BY ip";
 391          $rows = serendipity_db_query($q, false, 'assoc');
 392  
 393          $deny = array();
 394          foreach($rows AS $row) {
 395              $deny[] = $row['ip'];
 396          }
 397  
 398          $hta = $serendipity['serendipityPath'] . '.htaccess';
 399          if (file_exists($hta) && is_writable($hta)) {
 400              $htaccess = file_get_contents($hta);
 401              $fp = @fopen($hta, 'w');
 402              if (!$fp) {
 403                  return false;
 404              } else {
 405                  // Check if an old htaccess file existed and try to preserve its contents. Otherwise completely wipe the file.
 406                  if ($htaccess != '' && preg_match('@^(.*)#SPAMDENY.*Deny From.+#/SPAMDENY(.*)$@imsU', $htaccess, $match)) {
 407                      // Code outside from s9y-code was found.
 408                      $content = trim($match[1]) . "\n#SPAMDENY\nDeny From " . implode(',', $deny) . "\n#/SPAMDENY\n" . trim($match[2]);
 409                  } else {
 410                      $content = trim($htaccess) . "\n#SPAMDENY\nDeny From " . implode(',', $deny) . "\n#/SPAMDENY\n";
 411                  }
 412                  fwrite($fp, $content);
 413                  fclose($fp);
 414                  return true;
 415              }
 416          }
 417      }
 418  
 419      function &getBlacklist($where, $api_key = '', &$eventData, &$addData) {
 420          global $serendipity;
 421  
 422          $ret = false;
 423          require_once S9Y_PEAR_PATH . 'HTTP/Request.php';
 424          if (function_exists('serendipity_request_start')) serendipity_request_start();
 425  
 426          switch($where) {
 427              case 'akismet.com':
 428                  $this->log($this->logfile, $eventData['id'], 'AKISMET_SAFETY', 'Akismet verification takes place', $addData);
 429                  $ret  = array();
 430                  $data = array(
 431                    'blog'                    => $serendipity['baseURL'],
 432                    'user_agent'              => $_SERVER['HTTP_USER_AGENT'],
 433                    'referrer'                => $_SERVER['HTTP_REFERER'],
 434                    'user_ip'                 => $_SERVER['REMOTE_ADDR'] != getenv('SERVER_ADDR') ? $_SERVER['REMOTE_ADDR'] : getenv('HTTP_X_FORWARDED_FOR'),
 435                    'permalink'               => serendipity_archiveURL($eventData['id'], $eventData['title'], 'serendipityHTTPPath', true, array('timestamp' => $eventData['timestamp'])),
 436                    'comment_type'            => ($addData['type'] == 'NORMAL' ? 'comment' : 'trackback'),
 437                    'comment_author'          => $addData['name'],
 438                    'comment_author_email'    => $addData['email'],
 439                    'comment_author_url'      => $addData['url'],
 440                    'comment_content'         => $addData['comment']
 441                  );
 442                  $opt = array(
 443                      'method'            => 'POST',
 444                      'http'              => '1.1',
 445                      'timeout'           => 20,
 446                      'allowRedirects'    => true,
 447                      'maxRedirects'      => 3,
 448                      'readTimeout'       => array(5,0), 
 449                  );
 450  
 451                  $req    = &new HTTP_Request(
 452                      'http://rest.akismet.com/1.1/verify-key',
 453                       $opt
 454                  );
 455  
 456                  $req->addPostData('key',  $api_key);
 457                  $req->addPostData('blog', $serendipity['baseURL']);
 458  
 459                  if (PEAR::isError($req->sendRequest()) || $req->getResponseCode() != '200') {
 460                      $ret['is_spam'] = false;
 461                      $ret['message'] = 'API Verification Request failed';
 462                      $this->log($this->logfile, $eventData['id'], 'API_ERROR', 'Akismet HTTP verification request failed.', $addData);
 463                      break;
 464                  } else {
 465                      // Fetch response
 466                      $reqdata = $req->getResponseBody();
 467                  }
 468  
 469                  if (!preg_match('@valid@i', $reqdata)) {
 470                      $ret['is_spam'] = false;
 471                      $ret['message'] = 'API Verification failed';
 472                      $this->log($this->logfile, $eventData['id'], 'API_ERROR', 'Akismet API verification failed: ' . $reqdata, $addData);
 473                      break;
 474                  }
 475  
 476                  $req    = &new HTTP_Request(
 477                      'http://' . $api_key . '.rest.akismet.com/1.1/comment-check',
 478                      $opt
 479                  );
 480  
 481                  foreach($data AS $key => $value) {
 482                      $req->addPostData($key, $value);
 483                  }
 484  
 485                  if (PEAR::isError($req->sendRequest()) || $req->getResponseCode() != '200') {
 486                      $ret['is_spam'] = false;
 487                      $ret['message'] = 'Akismet Request failed';
 488                      $this->log($this->logfile, $eventData['id'], 'API_ERROR', 'Akismet HTTP request failed.', $addData);
 489                      break;
 490                  } else {
 491                      // Fetch response
 492                      $reqdata = $req->getResponseBody();
 493                  }
 494  
 495                  if (preg_match('@true@i', $reqdata)) {
 496                      $ret['is_spam'] = true;
 497                      $ret['message'] = $reqdata;
 498                      $this->log($this->logfile, $eventData['id'], 'AKISMET_PASS', 'Passed Akismet verification', $addData);
 499                  } elseif (preg_match('@false@i', $reqdata)) {
 500                      $ret['is_spam'] = false;
 501                      $ret['message'] = $reqdata;
 502                      $this->log($this->logfile, $eventData['id'], 'AKISMET_SPAM', 'Akismet API returned spam', $addData);
 503                  } else {
 504                      $ret['is_spam'] = false;
 505                      $ret['message'] = 'Akismet API failure';
 506                      $this->log($this->logfile, $eventData['id'], 'API_ERROR', 'Akismet API failure: ' . $reqdata, $addData);
 507                  }
 508  
 509                  break;
 510  
 511              case 'blogg.de':
 512                  $target  = $serendipity['serendipityPath'] . PATH_SMARTY_COMPILE . '/blogg.de.blacklist.txt';
 513                  $timeout = 3600; // One hour
 514  
 515                  if (file_exists($target) && filemtime($target) > time()-$timeout) {
 516                      $data = file_get_contents($target);
 517                  } else {
 518                      $data = '';
 519  
 520                      $req    = &new HTTP_Request('http://spam.blogg.de/blacklist.txt');
 521  
 522                      if (PEAR::isError($req->sendRequest()) || $req->getResponseCode() != '200') {
 523                          if (file_exists($target) && filesize($target) > 0) {
 524                              $data = file_get_contents($target);
 525                          }
 526                      } else {
 527                          // Fetch file
 528                          $data = $req->getResponseBody();
 529                          $fp = @fopen($target, 'w');
 530  
 531                          if ($fp) {
 532                              fwrite($fp, $data);
 533                              fclose($fp);
 534                          }
 535                      }
 536                  }
 537  
 538                  $blacklist = explode("\n", $data);
 539                  $ret =& $blacklist;
 540  
 541              default:
 542                  break;
 543          }
 544  
 545          if (function_exists('serendipity_request_end')) serendipity_request_end();
 546          return $ret;
 547      }
 548  
 549      function checkScheme() {
 550          global $serendipity;
 551  
 552          $dbversion = $this->get_config('dbversion', '1');
 553          
 554          if ($dbversion == '1') {
 555              $q   = "CREATE TABLE {$serendipity['dbPrefix']}spamblocklog (
 556                            timestamp int(10) {UNSIGNED} default null,
 557                            type varchar(255),
 558                            reason text,
 559                            entry_id int(10) {UNSIGNED} not null default '0',
 560                            author varchar(80),
 561                            email varchar(200),
 562                            url varchar(200),
 563                            useragent varchar(255),
 564                            ip varchar(15),
 565                            referer varchar(255),
 566                            body text)";
 567              $sql = serendipity_db_schema_import($q);
 568  
 569              $q   = "CREATE INDEX kspamidx ON {$serendipity['dbPrefix']}spamblocklog (timestamp);";
 570              $sql = serendipity_db_schema_import($q);
 571  
 572              $q   = "CREATE INDEX kspamtypeidx ON {$serendipity['dbPrefix']}spamblocklog (type);";
 573              $sql = serendipity_db_schema_import($q);
 574  
 575              $q   = "CREATE INDEX kspamentryidx ON {$serendipity['dbPrefix']}spamblocklog (entry_id);";
 576              $sql = serendipity_db_schema_import($q);
 577  
 578              $q   = "CREATE TABLE {$serendipity['dbPrefix']}spamblock_htaccess (
 579                            timestamp int(10) {UNSIGNED} default null,
 580                            ip varchar(15))";
 581              $sql = serendipity_db_schema_import($q);
 582  
 583              $q   = "CREATE INDEX kshtaidx ON {$serendipity['dbPrefix']}spamblock_htaccess (timestamp);";
 584              $sql = serendipity_db_schema_import($q);
 585  
 586              $this->set_config('dbversion', '2');
 587          }
 588  
 589          return true;
 590      }
 591  
 592      function generate_content(&$title) {
 593          $title = $this->title;
 594      }
 595  
 596      // This method will be called on "fatal" spam errors that are unlikely to occur accidentally by users.
 597      // Their IPs will be constantly blocked.
 598      function IsHardcoreSpammer() {
 599          global $serendipity;
 600  
 601          if (serendipity_db_bool($this->get_config('automagic_htaccess'))) {
 602              $this->htaccess_update($_SERVER['REMOTE_ADDR']);
 603          }
 604      }
 605  
 606      // Checks whether the current author is contained in one of the gorups that need no spam checking
 607      function inGroup() {
 608          global $serendipity;
 609  
 610          $checkgroups = explode('^', $this->get_config('hide_for_authors'));
 611  
 612          if (!isset($serendipity['authorid']) || !is_array($checkgroups)) {
 613              return false;
 614          }
 615  
 616          $mygroups =& serendipity_getGroups($serendipity['authorid'], true);
 617          if (!is_array($mygroups)) {
 618              return false;
 619          }
 620  
 621          foreach($checkgroups AS $key => $groupid) {
 622              if ($groupid == 'all') {
 623                  return true;
 624              } elseif (in_array($groupid, $mygroups)) {
 625                  return true;
 626              }
 627          }
 628  
 629          return false;
 630      }
 631  
 632      function example() {
 633          echo '<div id="captchabox" style="margin: 10px; padding: 5px; border: 1px solid black">' . PLUGIN_EVENT_SPAMBLOCK_LOOK . '<br />';
 634          $this->show_captcha();
 635          echo '</div>';
 636      }
 637  
 638      function show_captcha($use_gd = false) {
 639          global $serendipity;
 640  
 641          if ($use_gd || (function_exists('imagettftext') && function_exists('imagejpeg'))) {
 642              $max_char = 5;
 643              $min_char = 3;
 644              $use_gd   = true;
 645          } else {
 646              $max_char = $min_char = 5;
 647              $use_gd   = false;
 648          }
 649  
 650          if ($use_gd) {
 651              printf('<img src="%s" onclick="this.src=this.src + \'1\'" title="%s" alt="CAPTCHA" class="captcha" />',
 652                  $serendipity['baseURL'] . ($serendipity['rewrite'] == 'none' ? $serendipity['indexFile'] . '?/' : '') . 'plugin/captcha_' . md5(time()),
 653                  htmlspecialchars(PLUGIN_EVENT_SPAMBLOCK_CAPTCHAS_USERDESC2)
 654              );
 655          } else {
 656              $bgcolors = explode(',', $this->get_config('captcha_color', '255,0,255'));
 657              $hexval   = '#' . dechex(trim($bgcolors[0])) . dechex(trim($bgcolors[1])) . dechex(trim($bgcolors[2]));
 658              $this->random_string($max_char, $min_char);
 659              echo '<div class="serendipity_comment_captcha_image" style="background-color: ' . $hexval . '">';
 660              for ($i = 1; $i <= $max_char; $i++) {
 661                  printf('<img src="%s" title="%s" alt="CAPTCHA ' . $i . '" class="captcha" />',
 662                      $serendipity['baseURL'] . ($serendipity['rewrite'] == 'none' ? $serendipity['indexFile'] . '?/' : '') . 'plugin/captcha_' . $i . '_' . md5(time()),
 663                      htmlspecialchars(PLUGIN_EVENT_SPAMBLOCK_CAPTCHAS_USERDESC2)
 664                  );
 665              }
 666              echo '</div>';
 667          }
 668      }
 669  
 670      function event_hook($event, &$bag, &$eventData, $addData = null) {
 671          global $serendipity;
 672  
 673          $hooks = &$bag->get('event_hooks');
 674  
 675          if (isset($hooks[$event])) {
 676              $captchas_ttl = $this->get_config('captchas_ttl', 7);
 677              $_captchas    = $this->get_config('captchas', 'yes');
 678              $captchas     = ($_captchas !== 'no' && ($_captchas === 'yes' || $_captchas === 'scramble' || serendipity_db_bool($_captchas)));
 679  
 680              // Check if the entry is older than the allowed amount of time. Enforce kaptchas if that is true
 681              // of if kaptchas are activated for every entry
 682              $show_captcha = ($captchas && isset($eventData['timestamp']) && ($captchas_ttl < 1 || ($eventData['timestamp'] < (time() - ($captchas_ttl*60*60*24)))) ? true : false);
 683              
 684              // Plugins can override with custom captchas
 685              if (isset($serendipity['plugins']['disable_internal_captcha'])) {
 686                  $show_captcha = false;
 687              }
 688  
 689              $forcemoderation = $this->get_config('forcemoderation', 60);
 690              $forcemoderation_treat = $this->get_config('forcemoderation_treat', 'moderate');
 691              $forcemoderationt = $this->get_config('forcemoderationt', 60);
 692              $forcemoderationt_treat = $this->get_config('forcemoderationt_treat', 'moderate');
 693  
 694              $links_moderate  = $this->get_config('links_moderate', 10);
 695              $links_reject    = $this->get_config('links_reject', 20);
 696  
 697              if (function_exists('imagettftext') && function_exists('imagejpeg')) {
 698                  $max_char = 5;
 699                  $min_char = 3;
 700                  $use_gd   = true;
 701              } else {
 702                  $max_char = $min_char = 5;
 703                  $use_gd   = false;
 704              }
 705  
 706              switch($event) {
 707                  case 'fetchcomments':
 708                      if (is_array($eventData) && !$_SESSION['serendipityAuthedUser'] && serendipity_db_bool($this->get_config('hide_email', false))) {
 709                          // Will force emails to be not displayed in comments and RSS feed for comments. Will not apply to logged in admins (so not in the backend as well)
 710                          @reset($eventData);
 711                          while(list($idx, $comment) = each($eventData)) {
 712                              $eventData[$idx]['no_email'] = true;
 713                          }
 714                      }
 715                      break;
 716  
 717                  case 'frontend_saveComment':
 718                      if (!is_array($eventData) || serendipity_db_bool($eventData['allow_comments'])) {
 719                          $this->checkScheme();
 720  
 721                          $serendipity['csuccess'] = 'true';
 722                          $logfile = $this->logfile = $this->get_config('logfile', $serendipity['serendipityPath'] . 'spamblock.log');
 723                          $required_fields = $this->get_config('required_fields', '');
 724  
 725                          // Check CSRF [comments only, cannot be applied to trackbacks]
 726                          if ($addData['type'] == 'NORMAL' && serendipity_db_bool($this->get_config('csrf', true))) {
 727                              if (!serendipity_checkFormToken(false)) {
 728                                  $this->log($logfile, $eventData['id'], 'REJECTED', PLUGIN_EVENT_SPAMBLOCK_CSRF_REASON, $addData);
 729                                  $eventData = array('allow_comments' => false);
 730                                  $serendipity['messagestack']['comments'][] = PLUGIN_EVENT_SPAMBLOCK_CSRF_REASON;
 731                              }
 732                          }
 733  
 734                          // Check required fields
 735                          if ($addData['type'] == 'NORMAL' && !empty($required_fields)) {
 736                              $required_field_list = explode(',', $required_fields);
 737                              foreach($required_field_list as $required_field) {
 738                                  $required_field = trim($required_field);
 739                                  if (empty($addData[$required_field])) {
 740                                      $this->log($logfile, $eventData['id'], 'REJECTED', PLUGIN_EVENT_SPAMBLOCK_REASON_REQUIRED_FIELD, $addData);
 741                                      $eventData = array('allow_comments' => false);
 742                                      $serendipity['messagestack']['comments'][] = sprintf(PLUGIN_EVENT_SPAMBLOCK_REASON_REQUIRED_FIELD, $required_field);
 743                                      return false;
 744                                  }
 745                              }
 746                          }
 747  
 748                          /*
 749                          if ($addData['type'] != 'NORMAL' && empty($addData['name'])) {
 750                              $eventData = array('allow_coments' => false);
 751                              $this->log($logfile, $eventData['id'], 'INVALIDGARV', 'INVALIDGARV', $addData);
 752                              return false;
 753                          }
 754                          */
 755  
 756                          // Check whether to allow comments from registered authors
 757                          if (serendipity_userLoggedIn() && $this->inGroup()) {
 758                              return true;
 759                          }
 760  
 761                          // Check if entry title is the same as comment body
 762                          if (serendipity_db_bool($this->get_config('entrytitle')) && trim($eventData['title']) == trim($addData['comment'])) {
 763                              $this->log($logfile, $eventData['id'], 'REJECTED', PLUGIN_EVENT_SPAMBLOCK_REASON_TITLE, $addData);
 764                              $eventData = array('allow_comments' => false);
 765                              $serendipity['messagestack']['comments'][] = PLUGIN_EVENT_SPAMBLOCK_ERROR_BODY;
 766                              return false;
 767                          }
 768  
 769                          // Check for global emergency moderation
 770                          if ($this->get_config('killswitch', false) === true) {
 771                              $this->log($logfile, $eventData['id'], 'REJECTED', PLUGIN_EVENT_SPAMBLOCK_REASON_KILLSWITCH, $addData);
 772                              $eventData = array('allow_comments' => false);
 773                              $serendipity['messagestack']['comments'][] = PLUGIN_EVENT_SPAMBLOCK_ERROR_KILLSWITCH;
 774                              return false;
 775                          }
 776  
 777                          // Check for not allowing trackbacks/wfwcomments
 778                          if ( ($addData['type'] != 'NORMAL' || $addData['source'] == 'API') &&
 779                               $this->get_config('disable_api_comments', 'none') != 'none') {
 780                              if ($this->get_config('disable_api_comments') == 'reject') {
 781                                  $this->log($logfile, $eventData['id'], 'REJECTED', PLUGIN_EVENT_SPAMBLOCK_REASON_API, $addData);
 782                                  $eventData = array('allow_comments' => false);
 783                                  $serendipity['messagestack']['comments'][] = PLUGIN_EVENT_SPAMBLOCK_REASON_API;
 784                                  return false;
 785                              } elseif ($this->get_config('disable_api_comments') == 'moderate') {
 786                                  $this->log($logfile, $eventData['id'], 'MODERATE', PLUGIN_EVENT_SPAMBLOCK_REASON_API, $addData);
 787                                  $eventData['moderate_comments'] = true;
 788                                  $serendipity['csuccess']        = 'moderate';
 789                                  $serendipity['moderate_reason'] = PLUGIN_EVENT_SPAMBLOCK_REASON_API;
 790                              }
 791                          }
 792  
 793                          // Filter Akismet Blacklist?
 794                          $akismet_apikey = $this->get_config('akismet');
 795                          $akismet        = $this->get_config('akismet_filter');
 796                          if (!empty($akismet_apikey) && ($akismet == 'moderate' || $akismet == 'reject')) {
 797                              $spam = $this->getBlacklist('akismet.com', $akismet_apikey, $eventData, $addData);
 798                              if ($spam['is_spam'] !== false) {
 799                                  $this->IsHardcoreSpammer();
 800                                  if ($akismet == 'moderate') {
 801                                      $this->log($logfile, $eventData['id'], 'MODERATE', PLUGIN_EVENT_SPAMBLOCK_REASON_AKISMET_SPAMLIST . ': ' . $spam['message'], $addData);
 802                                      $eventData['moderate_comments'] = true;
 803                                      $serendipity['csuccess']        = 'moderate';
 804                                      $serendipity['moderate_reason'] = PLUGIN_EVENT_SPAMBLOCK_ERROR_BODY . ' (Akismet)';
 805                                  } else {
 806                                      $this->log($logfile, $eventData['id'], 'REJECTED', PLUGIN_EVENT_SPAMBLOCK_REASON_AKISMET_SPAMLIST . ': ' . $spam['message'], $addData);
 807                                      $eventData = array('allow_comments' => false);
 808                                      $serendipity['messagestack']['comments'][] = PLUGIN_EVENT_SPAMBLOCK_ERROR_BODY;
 809                                      return false;
 810                                  }
 811                              }
 812                          }
 813  
 814                          // Check Trackback URLs?
 815                          if ($addData['type'] == 'TRACKBACK' && serendipity_db_bool($this->get_config('trackback_check_url'))) {
 816                              require_once S9Y_PEAR_PATH . 'HTTP/Request.php';
 817  
 818                              if (function_exists('serendipity_request_start')) serendipity_request_start();
 819                              $req     = &new HTTP_Request($addData['url'], array('allowRedirects' => true, 'maxRedirects' => 5, 'readTimeout' => array(5,0)));
 820                              $is_valid = false;
 821                              if (PEAR::isError($req->sendRequest()) || $req->getResponseCode() != '200') {
 822                                  $is_valid = false;
 823                              } else {
 824                                  $fdata = $req->getResponseBody();
 825  
 826                                  // Check if the target page contains a link to our blog
 827                                  if (preg_match('@' . preg_quote($serendipity['baseURL'], '@') . '@i', $fdata)) {
 828                                      $is_valid = true;
 829                                  } else {
 830                                      $is_valid = false;
 831                                  }
 832                              }
 833                              if (function_exists('serendipity_request_end')) serendipity_request_end();
 834  
 835                              if ($is_valid === false) {
 836                                  $this->log($logfile, $eventData['id'], 'REJECTED', PLUGIN_EVENT_SPAMBLOCK_REASON_TRACKBACKURL, $addData);
 837                                  $eventData = array('allow_comments' => false);
 838                                  $serendipity['messagestack']['comments'][] = PLUGIN_EVENT_SPAMBLOCK_REASON_TRACKBACKURL;
 839                                  return false;
 840                              }
 841                          }
 842  
 843                          // Check for word filtering
 844                          if ($filter_type = $this->get_config('contentfilter_activate', 'moderate')) {
 845  
 846                              // Filter authors names
 847                              $filter_authors = explode(';', $this->get_config('contentfilter_authors', $this->filter_defaults['authors']));
 848                              if (is_array($filter_authors)) {
 849                                  foreach($filter_authors AS $filter_author) {
 850                                      if (empty($filter_author)) {
 851                                          continue;
 852                                      }
 853                                      if (preg_match('@(' . $filter_author . ')@i', $addData['name'], $wordmatch)) {
 854                                          if ($filter_type == 'moderate') {
 855                                              $this->log($logfile, $eventData['id'], 'MODERATE', PLUGIN_EVENT_SPAMBLOCK_FILTER_AUTHORS . ': ' . $wordmatch[1], $addData);
 856                                              $eventData['moderate_comments'] = true;
 857                                              $serendipity['csuccess']        = 'moderate';
 858                                              $serendipity['moderate_reason'] = PLUGIN_EVENT_SPAMBLOCK_ERROR_BODY . ' (' . PLUGIN_EVENT_SPAMBLOCK_FILTER_AUTHORS . ': ' . $wordmatch[1] . ')';
 859                                          } else {
 860                                              $this->log($logfile, $eventData['id'], 'REJECTED', PLUGIN_EVENT_SPAMBLOCK_FILTER_AUTHORS . ': ' . $wordmatch[1], $addData);
 861                                              $eventData = array('allow_comments' => false);
 862                                              $serendipity['messagestack']['comments'][] = PLUGIN_EVENT_SPAMBLOCK_ERROR_BODY;
 863                                              return false;
 864                                          }
 865                                      }
 866                                  }
 867                              }
 868  
 869                              // Filter URL
 870                              $filter_urls = explode(';', $this->get_config('contentfilter_urls', $this->filter_defaults['urls']));
 871                              if (is_array($filter_urls)) {
 872                                  foreach($filter_urls AS $filter_url) {
 873                                      if (empty($filter_url)) {
 874                                          continue;
 875                                      }
 876                                      if (preg_match('@(' . $filter_url . ')@i', $addData['url'], $wordmatch)) {
 877                                          if ($filter_type == 'moderate') {
 878                                              $this->log($logfile, $eventData['id'], 'MODERATE', PLUGIN_EVENT_SPAMBLOCK_FILTER_URLS . ': ' . $wordmatch[1], $addData);
 879                                              $eventData['moderate_comments'] = true;
 880                                              $serendipity['csuccess']        = 'moderate';
 881                                              $serendipity['moderate_reason'] = PLUGIN_EVENT_SPAMBLOCK_ERROR_BODY . ' (' . PLUGIN_EVENT_SPAMBLOCK_FILTER_URLS . ': ' . $wordmatch[1] . ')';
 882                                          } else {
 883                                              $this->log($logfile, $eventData['id'], 'REJECTED', PLUGIN_EVENT_SPAMBLOCK_FILTER_URLS . ': ' . $wordmatch[1], $addData);
 884                                              $eventData = array('allow_comments' => false);
 885                                              $serendipity['messagestack']['comments'][] = PLUGIN_EVENT_SPAMBLOCK_ERROR_BODY;
 886                                              return false;
 887                                          }
 888                                      }
 889                                  }
 890                              }
 891  
 892                              // Filter Content
 893                              $filter_bodys = explode(';', $this->get_config('contentfilter_words', $this->filter_defaults['words']));
 894                              if (is_array($filter_bodys)) {
 895                                  foreach($filter_bodys AS $filter_body) {
 896                                      if (empty($filter_body)) {
 897                                          continue;
 898                                      }
 899                                      if (preg_match('@(' . $filter_body . ')@i', $addData['comment'], $wordmatch)) {
 900                                          if ($filter_type == 'moderate') {
 901                                              $this->log($logfile, $eventData['id'], 'MODERATE', PLUGIN_EVENT_SPAMBLOCK_FILTER_WORDS . ': ' . $wordmatch[1], $addData);
 902                                              $eventData['moderate_comments'] = true;
 903                                              $serendipity['csuccess']        = 'moderate';
 904                                              $serendipity['moderate_reason'] = PLUGIN_EVENT_SPAMBLOCK_ERROR_BODY . ' (' . PLUGIN_EVENT_SPAMBLOCK_FILTER_WORDS . ': ' . $wordmatch[1] . ')';
 905                                          } else {
 906                                              $this->log($logfile, $eventData['id'], 'REJECTED', PLUGIN_EVENT_SPAMBLOCK_FILTER_WORDS . ': ' . $wordmatch[1], $addData);
 907                                              $eventData = array('allow_comments' => false);
 908                                              $serendipity['messagestack']['comments'][] = PLUGIN_EVENT_SPAMBLOCK_ERROR_BODY;
 909                                              return false;
 910                                          }
 911                                      }
 912                                  }
 913                              }
 914  
 915                              // Filter Emails
 916                              $filter_emails = explode(';', $this->get_config('contentfilter_emails', $this->filter_defaults['emails']));
 917                              if (is_array($filter_emails)) {
 918                                  foreach($filter_emails AS $filter_email) {
 919                                      if (empty($filter_email)) {
 920                                          continue;
 921                                      }
 922                                      if (preg_match('@(' . $filter_email . ')@i', $addData['email'], $wordmatch)) {
 923                                          $this->IsHardcoreSpammer();
 924                                          if ($filter_type == 'moderate') {
 925                                              $this->log($logfile, $eventData['id'], 'MODERATE', PLUGIN_EVENT_SPAMBLOCK_FILTER_EMAILS . ': ' . $wordmatch[1], $addData);
 926                                              $eventData['moderate_comments'] = true;
 927                                              $serendipity['csuccess']        = 'moderate';
 928                                              $serendipity['moderate_reason'] = PLUGIN_EVENT_SPAMBLOCK_ERROR_BODY . ' (' . PLUGIN_EVENT_SPAMBLOCK_FILTER_EMAILS . ': ' . $wordmatch[1] . ')';
 929                                          } else {
 930                                              $this->log($logfile, $eventData['id'], 'REJECTED', PLUGIN_EVENT_SPAMBLOCK_FILTER_EMAILS . ': ' . $wordmatch[1], $addData);
 931                                              $eventData = array('allow_comments' => false);
 932                                              $serendipity['messagestack']['emails'][] = PLUGIN_EVENT_SPAMBLOCK_ERROR_BODY;
 933                                              return false;
 934                                          }
 935                                      }
 936                                  }
 937                              }
 938                          } // Content filtering end
 939  
 940                          // Filter Blogg.de Blacklist?
 941                          $bloggdeblacklist = $this->get_config('bloggdeblacklist');
 942                          if ($bloggdeblacklist == 'moderate' || $bloggdeblacklist == 'reject') {
 943                              $domains = $this->getBlacklist('blogg.de', '', $eventData, $addData);
 944                              if (is_array($domains)) {
 945                                  foreach($domains AS $domain) {
 946                                      $domain = trim($domain);
 947                                      if (empty($domain)) {
 948                                          continue;
 949                                      }
 950  
 951                                      if (preg_match('@' . preg_quote($domain) . '@i', $addData['url'])) {
 952                                          $this->IsHardcoreSpammer();
 953                                          if ($bloggdeblacklist == 'moderate') {
 954                                              $this->log($logfile, $eventData['id'], 'MODERATE', PLUGIN_EVENT_SPAMBLOCK_REASON_BLOGG_SPAMLIST . ': ' . $domain, $addData);
 955                                              $eventData['moderate_comments'] = true;
 956                                              $serendipity['csuccess']        = 'moderate';
 957                                              $serendipity['moderate_reason'] = PLUGIN_EVENT_SPAMBLOCK_ERROR_BODY . ' (' . PLUGIN_EVENT_SPAMBLOCK_REASON_BLOGG_SPAMLIST . ')';
 958                                          } else {
 959                                              $this->log($logfile, $eventData['id'], 'REJECTED', PLUGIN_EVENT_SPAMBLOCK_REASON_BLOGG_SPAMLIST . ': ' . $domain, $addData);
 960                                              $eventData = array('allow_comments' => false);
 961                                              $serendipity['messagestack']['comments'][] = PLUGIN_EVENT_SPAMBLOCK_ERROR_BODY;
 962                                              return false;
 963                                          }
 964                                      }
 965                                  }
 966                              }
 967                          }
 968  
 969                          // Check for maximum number of links before rejecting
 970                          $link_count = substr_count(strtolower($addData['comment']), 'http://');
 971                          if ($links_reject > 0 && $link_count > $links_reject) {
 972                              $this->log($logfile, $eventData['id'], 'REJECTED', PLUGIN_EVENT_SPAMBLOCK_REASON_LINKS_REJECT, $addData);
 973                              $eventData = array('allow_comments' => false);
 974                              $serendipity['messagestack']['comments'][] = PLUGIN_EVENT_SPAMBLOCK_ERROR_BODY;
 975                              return false;
 976                          }
 977  
 978                          // Captcha checking
 979                          if ($show_captcha && $addData['type'] == 'NORMAL') {
 980                              if (!isset($_SESSION['spamblock']['captcha']) || !isset($serendipity['POST']['captcha']) || strtolower($serendipity['POST']['captcha']) != strtolower($_SESSION['spamblock']['captcha'])) {
 981                                  $this->log($logfile, $eventData['id'], 'REJECTED', sprintf(PLUGIN_EVENT_SPAMBLOCK_REASON_CAPTCHAS, $serendipity['POST']['captcha'], $_SESSION['spamblock']['captcha']), $addData);
 982                                  $eventData = array('allow_comments' => false);
 983                                  $serendipity['messagestack']['comments'][] = PLUGIN_EVENT_SPAMBLOCK_ERROR_CAPTCHAS;
 984                                  return false;
 985                              } else {
 986  // DEBUG
 987  //                                $this->log($logfile, $eventData['id'], 'REJECTED', 'Captcha passed: ' . $serendipity['POST']['captcha'] . ' / ' . $_SESSION['spamblock']['captcha'] . ' // Source: ' . $_SERVER['REQUEST_URI'], $addData);
 988                              }
 989                          } else {
 990  // DEBUG
 991  //                            $this->log($logfile, $eventData['id'], 'REJECTED', 'Captcha not needed: ' . $serendipity['POST']['captcha'] . ' / ' . $_SESSION['spamblock']['captcha'] . ' // Source: ' . $_SERVER['REQUEST_URI'], $addData);
 992                          }
 993  
 994                          // Check for forced comment moderation
 995                          if ($addData['type'] == 'NORMAL' && $forcemoderation > 0 && $eventData['timestamp'] < (time() - ($forcemoderation * 60 * 60 * 24))) {
 996                              $this->log($logfile, $eventData['id'], $forcemoderation_treat, PLUGIN_EVENT_SPAMBLOCK_REASON_FORCEMODERATION, $addData);
 997                              if ($forcemoderation_treat == 'reject') {
 998                                  $eventData = array('allow_comments' => false);
 999                                  $serendipity['messagestack']['comments'][] = PLUGIN_EVENT_SPAMBLOCK_REASON_FORCEMODERATION;
1000                                  return false;
1001                              } else {
1002                                  $eventData['moderate_comments'] = true;
1003                                  $serendipity['csuccess']        = 'moderate';
1004                                  $serendipity['moderate_reason'] = PLUGIN_EVENT_SPAMBLOCK_REASON_FORCEMODERATION;
1005                              }
1006                          }
1007  
1008                          // Check for forced trackback moderation
1009                          if ($addData['type'] != 'NORMAL' && $forcemoderationt > 0 && $eventData['timestamp'] < (time() - ($forcemoderationt * 60 * 60 * 24))) {
1010                              $this->log($logfile, $eventData['id'], $forcemoderationt_treat, PLUGIN_EVENT_SPAMBLOCK_REASON_FORCEMODERATION, $addData);
1011                              if ($forcemoderationt_treat == 'reject') {
1012                                  $eventData = array('allow_comments' => false);
1013                                  $serendipity['messagestack']['comments'][] = PLUGIN_EVENT_SPAMBLOCK_REASON_FORCEMODERATION;
1014                                  return false;
1015                              } else {
1016                                  $eventData['moderate_comments'] = true;
1017                                  $serendipity['csuccess']        = 'moderate';
1018                                  $serendipity['moderate_reason'] = PLUGIN_EVENT_SPAMBLOCK_REASON_FORCEMODERATION;
1019                              }
1020                          }
1021  
1022                          // Check for maximum number of links before forcing moderation
1023                          if ($links_moderate > 0 && $link_count > $links_moderate) {
1024                              $this->log($logfile, $eventData['id'], 'REJECTED', PLUGIN_EVENT_SPAMBLOCK_REASON_LINKS_MODERATE, $addData);
1025                              $eventData['moderate_comments'] = true;
1026                              $serendipity['csuccess']        = 'moderate';
1027                              $serendipity['moderate_reason'] = PLUGIN_EVENT_SPAMBLOCK_REASON_LINKS_MODERATE;
1028                          }
1029  
1030                          // Check for identical comments. We allow to bypass trackbacks from our server to our own blog.
1031                          if ( $this->get_config('bodyclone', true) === true && $_SERVER['REMOTE_ADDR'] != $_SERVER['SERVER_ADDR']) {
1032                              $query = "SELECT count(id) AS counter FROM {$serendipity['dbPrefix']}comments WHERE body = '" . serendipity_db_escape_string($addData['comment']) . "'";
1033                              $row   = serendipity_db_query($query, true);
1034                              if (is_array($row) && $row['counter'] > 0) {
1035                                  $this->IsHardcoreSpammer();
1036                                  $this->log($logfile, $eventData['id'], 'REJECTED', PLUGIN_EVENT_SPAMBLOCK_REASON_BODYCLONE, $addData);
1037                                  $eventData = array('allow_comments' => false);
1038                                  $serendipity['messagestack']['comments'][] = PLUGIN_EVENT_SPAMBLOCK_ERROR_BODY;
1039                                  return false;
1040                              }
1041                          }
1042  
1043                          // Check last IP
1044                          if ($addData['type'] == 'NORMAL' && $this->get_config('ipflood', 2) != 0 ) {
1045                              $query = "SELECT max(timestamp) AS last_post FROM {$serendipity['dbPrefix']}comments WHERE ip = '" . serendipity_db_escape_string($_SERVER['REMOTE_ADDR']) . "'";
1046                              $row   = serendipity_db_query($query, true);
1047                              if (is_array($row) && $row['last_post'] > (time() - $this->get_config('ipflood', 2)*60)) {
1048                                  $this->log($logfile, $eventData['id'], 'REJECTED', PLUGIN_EVENT_SPAMBLOCK_REASON_IPFLOOD, $addData);
1049                                  $eventData = array('allow_comments' => false);
1050                                  $serendipity['messagestack']['comments'][] = PLUGIN_EVENT_SPAMBLOCK_ERROR_IP;
1051                                  return false;
1052                              }
1053                          }
1054  
1055                          // Check invalid email
1056                          if ($addData['type'] == 'NORMAL' && serendipity_db_bool($this->get_config('checkmail', false))) {
1057                              if (!empty($addData['email']) && strstr($addData['email'], '@') === false) {
1058                                  $this->log($logfile, $eventData['id'], 'REJECTED', PLUGIN_EVENT_SPAMBLOCK_REASON_CHECKMAIL, $addData);
1059                                  $eventData = array('allow_comments' => false);
1060                                  $serendipity['messagestack']['comments'][] = PLUGIN_EVENT_SPAMBLOCK_REASON_CHECKMAIL;
1061                                  return false;
1062                              }
1063                          }
1064  
1065                          if ($eventData['moderate_comments'] == true) {
1066                              return false;
1067                          }
1068                      }
1069  
1070                      return true;
1071                      break;
1072  
1073                  case 'frontend_comment':
1074                      if (serendipity_db_bool($this->get_config('hide_email', false))) {
1075                          echo '<div class="serendipity_commentDirection serendipity_comment_spamblock">' . PLUGIN_EVENT_SPAMBLOCK_HIDE_EMAIL_NOTICE . '</div>';
1076                      }
1077  
1078                      if (serendipity_db_bool($this->get_config('csrf', true))) {
1079                          echo serendipity_setFormToken('form');
1080                      }
1081  
1082                      // Check whether to allow comments from registered authors
1083                      if (serendipity_userLoggedIn() && $this->inGroup()) {
1084                          return true;
1085                      }
1086  
1087                      if ($show_captcha) {
1088                          echo '<div class="serendipity_commentDirection serendipity_comment_captcha">';
1089                          if (!isset($serendipity['POST']['preview']) || strtolower($serendipity['POST']['captcha'] != strtolower($_SESSION['spamblock']['captcha']))) {
1090                              echo '<br />' . PLUGIN_EVENT_SPAMBLOCK_CAPTCHAS_USERDESC . '<br />';
1091                              $this->show_captcha($use_gd);
1092                              echo '<br />';
1093                              echo '<label for="captcha">'. PLUGIN_EVENT_SPAMBLOCK_CAPTCHAS_USERDESC3 . '</label><br /><input class="input_textbox" type="text" size="5" name="serendipity[captcha]" value="" id="captcha" />';
1094                          } elseif (isset($serendipity['POST']['captcha'])) {
1095                              echo '<input type="hidden" name="serendipity[captcha]" value="' . htmlspecialchars($serendipity['POST']['captcha']) . '" />';
1096                          }
1097                          echo '</div>';
1098                      }
1099  
1100                      return true;
1101                      break;
1102  
1103  
1104                  case 'external_plugin':
1105                      $parts     = explode('_', $eventData);
1106                      if (!empty($parts[1])) {
1107                          $param     = (int) $parts[1];
1108                      } else {
1109                          $param     = null;
1110                      }
1111  
1112                      $methods = array('captcha');
1113  
1114                      if (!in_array($parts[0], $methods)) {
1115                          return;
1116                      }
1117  
1118                      list($musec, $msec) = explode(' ', microtime());
1119                      $srand = (float) $msec + ((float) $musec * 100000);
1120                      srand($srand);
1121                      mt_srand($srand);
1122                      $width    = 120;
1123                      $height   = 40;
1124  
1125                      $bgcolors = explode(',', $this->get_config('captcha_color', '255,255,255'));
1126                      $fontfiles = array('Vera.ttf', 'VeraSe.ttf', 'chumbly.ttf', '36daysago.ttf');
1127  
1128                      if ($use_gd) {
1129                          $strings  = $this->random_string($max_char, $min_char);
1130                          $fontname = $fontfiles[array_rand($fontfiles)];
1131                          $font     = $serendipity['serendipityPath'] . 'plugins/serendipity_event_spamblock/' . $fontname;
1132  
1133                          if (!file_exists($font)) {
1134                              // Search in shared plugin directory
1135                              $font = S9Y_INCLUDE_PATH . 'plugins/serendipity_event_spamblock/' . $fontname;
1136                          }
1137  
1138                          if (!file_exists($font)) {
1139                              die(PLUGIN_EVENT_SPAMBLOCK_ERROR_NOTTF);
1140                          }
1141  
1142                          header('Content-Type: image/jpeg');
1143                          $image  = imagecreate($width, $height);
1144                          $bgcol  = imagecolorallocate($image, trim($bgcolors[0]), trim($bgcolors[1]), trim($bgcolors[2]));
1145                          // imagettftext($image, 10, 1, 1, 15, imagecolorallocate($image, 255, 255, 255), $font, 'String: ' . $string);
1146  
1147                          $pos_x  = 5;
1148                          foreach($strings AS $idx => $charidx) {
1149                              $color = imagecolorallocate($image, mt_rand(50, 235), mt_rand(50, 235), mt_rand(50,235));
1150                              $size  = mt_rand(15, 21);
1151                              $angle = mt_rand(-20, 20);
1152                              $pos_y = ceil($height - (mt_rand($size/3, $size/2)));
1153  
1154                              imagettftext(
1155                                $image,
1156                                $size,
1157                                $angle,
1158                                $pos_x,
1159                                $pos_y,
1160                                $color,
1161                                $font,
1162                                $this->chars[$charidx]
1163                              );
1164  
1165                              $pos_x = $pos_x + $size + 2;
1166  
1167                          }
1168  
1169                          if ($_captchas === 'scramble') {
1170                              $line_diff = mt_rand(5, 15);
1171                              $pixel_col = imagecolorallocate($image, trim($bgcolors[0])-mt_rand(10,50), trim($bgcolors[1])-mt_rand(10,50), trim($bgcolors[2])-mt_rand(10,50));
1172                              for ($y = $line_diff; $y < $height; $y += $line_diff) {
1173                                  $row_diff = mt_rand(5, 15);
1174                                  for ($x = $row_diff; $x < $width; $x+= $row_diff) {
1175                                      imagerectangle($image, $x, $y, $x+1, $y+1, $pixel_col);
1176                                  }
1177                              }
1178                          }
1179                          imagejpeg($image, '', 90);
1180                          imagedestroy($image);
1181                      } else {
1182                          header('Content-Type: image/png');
1183                          $output_char = strtolower($_SESSION['spamblock']['captcha']{$parts[1] - 1});
1184                          $cap = $serendipity['serendipityPath'] . 'plugins/serendipity_event_spamblock/captcha_' . $output_char . '.png';
1185                          if (!file_exists($cap)) {
1186                              $cap = S9Y_INCLUDE_PATH . 'plugins/serendipity_event_spamblock/captcha_' . $output_char . '.png';
1187                          }
1188  
1189                          if (file_exists($cap)) {
1190                              echo file_get_contents($cap);
1191                          }
1192                      }
1193                      return true;
1194                      break;
1195  
1196                  case 'backend_comments_top':
1197  
1198                      // Add Author to blacklist. If already filtered, it will be removed from the filter. (AKA "Toggle")
1199                      if (isset($serendipity['GET']['spamBlockAuthor'])) {
1200                          $item    = $this->getComment('author', $serendipity['GET']['spamBlockAuthor']);
1201                          $items   = &$this->checkFilter('authors', $item, true);
1202                          $this->set_config('contentfilter_authors', implode(';', $items));
1203                      }
1204  
1205                      // Add URL to blacklist. If already filtered, it will be removed from the filter. (AKA "Toggle")
1206                      if (isset($serendipity['GET']['spamBlockURL'])) {
1207                          $item    = $this->getComment('url', $serendipity['GET']['spamBlockURL']);
1208                          $items   = &$this->checkFilter('urls', $item, true);
1209                          $this->set_config('contentfilter_urls', implode(';', $items));
1210                      }
1211  
1212                      // Add E-mail to blacklist. If already filtered, it will be removed from the filter. (AKA "Toggle")
1213                      if (isset($serendipity['GET']['spamBlockEmail'])) {
1214                          $item    = $this->getComment('email', $serendipity['GET']['spamBlockEmail']);
1215                          $items   = &$this->checkFilter('emails', $item, true);
1216                          $this->set_config('contentfilter_emails', implode(';', $items));
1217                      }
1218  
1219                      echo ' - ' . WORD_OR . ' - <a class="serendipityPrettyButton" href="serendipity_admin.php?serendipity[adminModule]=plugins&amp;serendipity[plugin_to_conf]=' . $this->instance . '">' . PLUGIN_EVENT_SPAMBLOCK_CONFIG . '</a>';
1220                      return true;
1221                      break;
1222  
1223                  case 'backend_view_comment':
1224                      $author_is_filtered = $this->checkFilter('authors', $eventData['author']);
1225                      $clink1 = 'clink1' . $eventData['id'];
1226                      $clink2 = 'clink2' . $eventData['id'];
1227  
1228                      $eventData['action_author'] .= ' <a id="' . $clink1 . '" class="serendipityIconLink" title="' . ($author_is_filtered ? PLUGIN_EVENT_SPAMBLOCK_REMOVE_AUTHOR : PLUGIN_EVENT_SPAMBLOCK_ADD_AUTHOR) . '" href="serendipity_admin.php?serendipity[adminModule]=comments&amp;serendipity[spamBlockAuthor]=' . $eventData['id'] . $addData . '#' . $clink1 . '"><img src="' . serendipity_getTemplateFile('admin/img/' . ($author_is_filtered ? 'un' : '') . 'configure.png') . '" alt="" /></a>';
1229  
1230                      if (!empty($eventData['url'])) {
1231                          $url_is_filtered    = $this->checkFilter('urls', $eventData['url']);
1232                          $eventData['action_url']    .= ' <a id="' . $clink2 . '" class="serendipityIconLink" title="' . ($url_is_filtered ? PLUGIN_EVENT_SPAMBLOCK_REMOVE_URL : PLUGIN_EVENT_SPAMBLOCK_ADD_URL) . '" href="serendipity_admin.php?serendipity[adminModule]=comments&amp;serendipity[spamBlockURL]=' . $eventData['id'] . $addData . '#' . $clink2 . '"><img src="' . serendipity_getTemplateFile('admin/img/' . ($url_is_filtered ? 'un' : '') . 'configure.png') . '" alt="" /></a>';
1233                      }
1234  
1235                      if (!empty($eventData['email'])) {
1236                          $email_is_filtered    = $this->checkFilter('emails', $eventData['email']);
1237                          $eventData['action_email']    .= ' <a id="' . $clink2 . '" class="serendipityIconLink" title="' . ($email_is_filtered ? PLUGIN_EVENT_SPAMBLOCK_REMOVE_EMAIL : PLUGIN_EVENT_SPAMBLOCK_ADD_EMAIL) . '" href="serendipity_admin.php?serendipity[adminModule]=comments&amp;serendipity[spamBlockEmail]=' . $eventData['id'] . $addData . '#' . $clink2 . '"><img src="' . serendipity_getTemplateFile('admin/img/' . ($email_is_filtered ? 'un' : '') . 'configure.png') . '" alt="" /></a>';
1238                      }
1239  
1240                      return true;
1241                      break;
1242  
1243                  default:
1244                      return false;
1245                      break;
1246              }
1247          } else {
1248              return false;
1249          }
1250      }
1251  
1252      function &checkFilter($what, $match, $getItems = false) {
1253          $items = explode(';', $this->get_config('contentfilter_' . $what, $this->filter_defaults[$what]));
1254  
1255          $filtered = false;
1256          if (is_array($items)) {
1257              foreach($items AS $key => $item) {
1258                  if (empty($match)) {
1259                      continue;
1260                  }
1261  
1262                  if (empty($item)) {
1263                      unset($items[$key]);
1264                      continue;
1265                  }
1266  
1267                  if (preg_match('@' . $item . '@', $match)) {
1268                      $filtered = true;
1269                      unset($items[$key]);
1270                  }
1271              }
1272          }
1273  
1274          if ($getItems) {
1275              if (!$filtered && !empty($match)) {
1276                  $items[] = preg_quote($match, '@');
1277              }
1278  
1279              return $items;
1280          }
1281  
1282          return $filtered;
1283      }
1284  
1285      function getComment($key, $id) {
1286          global $serendipity;
1287          $c = serendipity_db_query("SELECT $key FROM {$serendipity['dbPrefix']}comments WHERE id = '" . (int)$id . "'", true, 'assoc');
1288  
1289          if (!is_array($c) || !isset($c[$key])) {
1290              return false;
1291          }
1292  
1293          return $c[$key];
1294      }
1295  
1296      function random_string($max_char, $min_char) {
1297          $this->chars = array(2, 3, 4, 7, 9); // 1, 5, 6 and 8 may look like characters.
1298          $this->chars = array_merge($this->chars, array('A','B','C','D','E','F','H','J','K','L','M','N','P','Q','R','T','U','V','W','X','Y','Z')); // I, O, S may look like numbers
1299  
1300          $strings   = array_rand($this->chars, mt_rand($min_char, $max_char));
1301          $string    = '';
1302          foreach($strings AS $idx => $charidx) {
1303              $string .= $this->chars[$charidx];
1304          }
1305          $_SESSION['spamblock'] = array('captcha' => $string);
1306  
1307          return $strings;
1308      }
1309  
1310      function log($logfile, $id, $switch, $reason, $comment) {
1311          global $serendipity;
1312  
1313          $method = $this->get_config('logtype');
1314  
1315          switch($method) {
1316              case 'file':
1317                  if (empty($logfile)) {
1318                      return;
1319                  }
1320  
1321                  $fp = @fopen($logfile, 'a+');
1322                  if (!is_resource($fp)) {
1323                      return;
1324                  }
1325  
1326                  fwrite($fp, sprintf(
1327                      '[%s] - [%s: %s] - [#%s, Name "%s", E-Mail "%s", URL "%s", User-Agent "%s", IP %s] - [%s]' . "\n",
1328                      date('Y-m-d H:i:s', serendipity_serverOffsetHour()),
1329                      $switch,
1330                      $reason,
1331                      $id,
1332                      str_replace("\n", ' ', $comment['name']),
1333                      str_replace("\n", ' ', $comment['email']),
1334                      str_replace("\n", ' ', $comment['url']),
1335                      str_replace("\n", ' ', $_SERVER['HTTP_USER_AGENT']),
1336                      $_SERVER['REMOTE_ADDR'],
1337                      str_replace("\n", ' ', $comment['comment'])
1338                  ));
1339  
1340                  fclose($fp);
1341                  break;
1342  
1343              case 'none':
1344                  return;
1345                  break;
1346  
1347              case 'db':
1348              default:
1349                  $q = sprintf("INSERT INTO {$serendipity['dbPrefix']}spamblocklog
1350                                            (timestamp, type, reason, entry_id, author, email, url,  useragent, ip,   referer, body)
1351                                     VALUES (%d,        '%s',  '%s',  '%s',     '%s',   '%s',  '%s', '%s',      '%s', '%s',    '%s')",
1352  
1353                             serendipity_serverOffsetHour(),
1354                             serendipity_db_escape_string($switch),
1355                             serendipity_db_escape_string($reason),
1356                             serendipity_db_escape_string($id),
1357                             serendipity_db_escape_string($comment['name']),
1358                             serendipity_db_escape_string($comment['email']),
1359                             serendipity_db_escape_string($comment['url']),
1360                             substr(serendipity_db_escape_string($_SERVER['HTTP_USER_AGENT']), 0, 255),
1361                             serendipity_db_escape_string($_SERVER['REMOTE_ADDR']),
1362                             substr(serendipity_db_escape_string(isset($_SESSION['HTTP_REFERER']) ? $_SESSION['HTTP_REFERER'] : $_SERVER['HTTP_REFERER']), 0, 255),
1363                             serendipity_db_escape_string($comment['comment'])
1364                  );
1365  
1366                  serendipity_db_query($q);
1367                  break;
1368          }
1369      }
1370  }
1371  
1372  /* vim: set sts=4 ts=4 expandtab : */


Généré le : Sat Nov 24 09:00:37 2007 par Balluche grâce à PHPXref 0.7
  Clicky Web Analytics