You are here

function spam_content_filter in Spam 6

Same name and namespace in other branches
  1. 5.3 spam.module \spam_content_filter()
  2. 5 spam.module \spam_content_filter()

API call to determine the likeliness that a given piece of content is spam, returning a rating from 1% likelihood to 99% likelihood. It is unlikely that you want to call this function directly.

Parameters

$content: An array holding the complete content.

$type: A string naming the type of content to be filtered.

1 call to spam_content_filter()
spam_content_is_spam in ./spam.module
API call to simply test if content is spam or not. No action is taken.

File

./spam.module, line 119
Spam module, v3 Copyright(c) 2006-2008 Jeremy Andrews <jeremy@tag1consulting.com>. All rights reserved.

Code

function spam_content_filter($content, $type, $extra, $filter_test = FALSE) {
  $id = spam_invoke_module($type, 'content_id', $content, $extra);
  if (!spam_filter_content_type($content, $type, $extra)) {
    return;
  }
  static $scores = array();
  if (isset($scores["{$type}-{$id}"])) {
    return $scores["{$type}-{$id}"];
  }
  spam_log(SPAM_DEBUG, 'spam_content_filter', t('invoking content filters'), $type, $id);

  // There's no need to scan the same content multiple times.
  if (!$id || !isset($scores["{$type}-{$id}"])) {

    // Determine which fields we need to run through the spam filter.
    $fields = spam_invoke_module($type, 'filter_fields', $content, $extra);
    if (!empty($fields) && is_array($fields['main'])) {
      $score = $total = 0;
      $filters = db_query('SELECT name, module, gain FROM {spam_filters} WHERE status = %d ORDER BY weight', SPAM_FILTER_ENABLED);
      $counter = 0;
      while ($filter = db_fetch_object($filters)) {
        $counter++;
        spam_log(SPAM_DEBUG, 'spam_content_filter', t('invoking @filter [@counter], gain = @gain', array(
          '@filter' => $filter->name,
          '@counter' => $counter,
          '@gain' => $filter->gain,
        )), $type, $id);
        $actions[$filter->module] = spam_invoke_module($filter->module, 'filter', $type, $content, $fields, $extra, $filter_test);
        $actions_total = empty($actions[$filter->module]['total']) ? 0 : $actions[$filter->module]['total'];
        spam_log(SPAM_VERBOSE, 'spam_content_filter', t('@filter: total(@total) redirect(@redirect) gain(@gain)', array(
          '@filter' => $filter->name,
          '@total' => $actions_total,
          '@redirect' => isset($actions[$filter->module]['redirect']) ? $actions[$filter->module]['redirect'] : '',
          '@gain' => $filter->gain,
        )), $type, $id);
        if ($actions_total) {
          $score += $actions_total * $filter->gain;
          $total += $filter->gain;
          spam_log(SPAM_DEBUG, 'spam_content_filter', t('current score(@score) current total(@total) average(@average)', array(
            '@score' => $score,
            '@total' => $total,
            '@average' => spam_sanitize_score($score / $total),
          )), $type, $id);
          if (isset($actions[$filter->module]['redirect'])) {
            if (!isset($extra['redirect']) || $extra['redirect']) {

              // Do not redirect when $extra['redirect'] === FALSE (i.e. called from batch or cron job).
              $redirect = $actions[$filter->module]['redirect'];
              break;
            }
          }
        }
      }
      if (!$counter) {
        spam_log(SPAM_VERBOSE, 'spam_content_filter', t('No filters enabled, content not scanned.'), $type, $id);
      }
      if ($total) {
        $log_score = spam_sanitize_score($score / $total);
      }
      else {
        $log_score = 1;
      }
      if ($id) {
        $scores["{$type}-{$id}"] = $log_score;
      }
    }
    else {
      spam_log(SPAM_VERBOSE, 'spam_content_filter', t('No main filter field defined, skipping.  Returned fields: !fields', array(
        '!fields' => implode(', ', $fields),
      )), $type, $id);
    }
    if (isset($redirect)) {
      if ($id) {

        // A filter has us redirecting to an error screen, but this content
        // has an id so we need to update its spam status in the database first.
        if ($scores["{$type}-{$id}"] >= variable_get('spam_threshold', SPAM_DEFAULT_THRESHOLD)) {
          spam_mark_as_spam($type, $id);
        }
        else {
          spam_mark_as_not_spam($type, $id);
        }
      }
      else {
        _spam_update_statistics(t('prevented spam @type', array(
          '@type' => $type,
        )));
      }
      _spam_update_statistics(t('detected spam'));
      _spam_update_statistics(t('content_filter redirect'));
      spam_log(SPAM_VERBOSE, 'spam_content_filter', t('Spam score [!score], redirecting to: !url', array(
        '!score' => $log_score,
        '!url' => $redirect,
      )), $type, $id);
      if (spam_bypass_filters() || user_access('bypass filters')) {
        spam_log(SPAM_DEBUG, 'spam_content_filter', t('bypassing filter redirect'), $type, $id);
        return;
      }
      drupal_goto($redirect);
    }
  }
  else {
    spam_log(SPAM_VERBOSE, 'spam_content_filter', t('Skipped content filters: id(!id) score(!score).', array(
      '!id' => $id,
      '!score' => $scores["{$type}-{$id}"],
    )), $type, $id);
  }
  if ($id) {
    $score = $scores["{$type}-{$id}"];
  }
  else {
    if ($total) {
      $score = spam_sanitize_score($score / $total);
    }
    else {
      $score = 1;
    }
  }
  spam_log(SPAM_LOG, 'spam_content_filter', t('final average(@score)', array(
    '@score' => $score,
  )), $type, $id);
  return $score;
}