Seditio Source
Root |
./othercms/dotclear-2.22/plugins/akismet/class.dc.filter.akismet.php
<?php
/**
 * @brief akismet, an antispam filter plugin for Dotclear 2
 *
 * @package Dotclear
 * @subpackage Plugins
 *
 * @copyright Olivier Meunier & Association Dotclear
 * @copyright GPL-2.0-only
 */
if (!defined('DC_RC_PATH')) {
    return;
}

class
dcFilterAkismet extends dcSpamFilter
{
    public
$name    = 'Akismet';
    public
$has_gui = true;
    public
$active  = false;
    public
$help    = 'akismet-filter';

    public function
__construct($core)
    {
       
parent::__construct($core);

        if (
defined('DC_AKISMET_SUPER') && DC_AKISMET_SUPER && !$core->auth->isSuperAdmin()) {
           
$this->has_gui = false;
        }
    }

    protected function
setInfo()
    {
       
$this->description = __('Akismet spam filter');
    }

    public function
getStatusMessage($status, $comment_id)
    {
        return
sprintf(__('Filtered by %s.'), $this->guiLink());
    }

    private function
akInit()
    {
       
$blog = &$this->core->blog;

        if (!
$blog->settings->akismet->ak_key) {
            return
false;
        }

        return new
akismet($blog->url, $blog->settings->akismet->ak_key);
    }

    public function
isSpam($type, $author, $email, $site, $ip, $content, $post_id, &$status)
    {
        if ((
$ak = $this->akInit()) === false) {
            return;
        }

       
$blog = &$this->core->blog;

        try {
            if (
$ak->verify()) {
               
$post = $blog->getPosts(['post_id' => $post_id]);

               
$c = $ak->comment_check(
                   
$post->getURL(),
                   
$type,
                   
$author,
                   
$email,
                   
$site,
                   
$content
               
);

                if (
$c) {
                   
$status = 'Filtered by Akismet';

                    return
true;
                }
            }
        } catch (
Exception $e) {
        }
# If http or akismet is dead, we don't need to know it
   
}

    public function
trainFilter($status, $filter, $type, $author, $email, $site, $ip, $content, $rs)
    {
       
# We handle only false positive from akismet
       
if ($status == 'spam' && $filter != 'dcFilterAkismet') {
            return;
        }

       
$f = $status == 'spam' ? 'submit_spam' : 'submit_ham';

        if ((
$ak = $this->akInit()) === false) {
            return;
        }

        try {
            if (
$ak->verify()) {
               
$ak->{$f}($rs->getPostURL(), $type, $author, $email, $site, $content);
            }
        } catch (
Exception $e) {
        }
# If http or akismet is dead, we don't need to know it
   
}

    public function
gui($url)
    {
       
$blog = &$this->core->blog;

       
$blog->settings->addNamespace('akismet');
       
$ak_key      = $blog->settings->akismet->ak_key;
       
$ak_verified = null;

        if (isset(
$_POST['ak_key'])) {
            try {
               
$ak_key = $_POST['ak_key'];

               
$blog->settings->akismet->put('ak_key', $ak_key, 'string');

               
dcPage::addSuccessNotice(__('Filter configuration have been successfully saved.'));
               
http::redirect($url);
            } catch (
Exception $e) {
               
$this->core->error->add($e->getMessage());
            }
        }

        if (
$blog->settings->akismet->ak_key) {
            try {
               
$ak          = new akismet($blog->url, $blog->settings->akismet->ak_key);
               
$ak_verified = $ak->verify();
            } catch (
Exception $e) {
               
$this->core->error->add($e->getMessage());
            }
        }

       
$res = dcPage::notices();

       
$res .= '<form action="' . html::escapeURL($url) . '" method="post" class="fieldset">' .
       
'<p><label for="ak_key" class="classic">' . __('Akismet API key:') . '</label> ' .
       
form::field('ak_key', 12, 128, $ak_key);

        if (
$ak_verified !== null) {
            if (
$ak_verified) {
               
$res .= ' <img src="images/check-on.png" alt="" /> ' . __('API key verified');
            } else {
               
$res .= ' <img src="images/check-off.png" alt="" /> ' . __('API key not verified');
            }
        }

       
$res .= '</p>';

       
$res .= '<p><a href="https://akismet.com/">' . __('Get your own API key') . '</a></p>' .
       
'<p><input type="submit" value="' . __('Save') . '" />' .
       
$this->core->formNonce() . '</p>' .
           
'</form>';

        return
$res;
    }
}

class
akismet extends netHttp
{
    protected
$base_host  = 'rest.akismet.com';
    protected
$ak_host    = '';
    protected
$ak_version = '1.1';
    protected
$ak_path    = '/%s/%s';

    protected
$ak_key = null;
    protected
$blog_url;

    public function
__construct($blog_url, $api_key)
    {
       
$this->blog_url = $blog_url;
       
$this->ak_key   = $api_key;

       
$this->ak_path = sprintf($this->ak_path, $this->ak_version, '%s');
       
$this->ak_host = $this->ak_key . '.' . $this->base_host;

       
parent::__construct($this->ak_host, 80, DC_QUERY_TIMEOUT);
    }

    public function
verify()
    {
       
$this->host = $this->base_host;
       
$path       = sprintf($this->ak_path, 'verify-key');

       
$data = [
           
'key'  => $this->ak_key,
           
'blog' => $this->blog_url,
        ];

        if (
$this->post($path, $data, 'UTF-8')) {
            return
$this->getContent() == 'valid';
        }

        return
false;
    }

    public function
comment_check($permalink, $type, $author, $email, $url, $content)
    {
       
$info_ignore = ['HTTP_COOKIE'];
       
$info        = [];

        foreach (
$_SERVER as $k => $v) {
            if (
strpos($k, 'HTTP_') === 0 && !in_array($k, $info_ignore)) {
               
$info[$k] = $v;
            }
        }

        return
$this->callFunc('comment-check', $permalink, $type, $author, $email, $url, $content, $info);
    }

    public function
submit_spam($permalink, $type, $author, $email, $url, $content)
    {
       
$this->callFunc('submit-spam', $permalink, $type, $author, $email, $url, $content);

        return
true;
    }

    public function
submit_ham($permalink, $type, $author, $email, $url, $content)
    {
       
$this->callFunc('submit-ham', $permalink, $type, $author, $email, $url, $content);

        return
true;
    }

    protected function
callFunc($function, $permalink, $type, $author, $email, $url, $content, $info = [])
    {
       
$ua      = $info['HTTP_USER_AGENT'] ?? '';
       
$referer = $info['HTTP_REFERER']    ?? '';

       
# Prepare comment data
       
$data = [
           
'blog'                 => $this->blog_url,
           
'user_ip'              => http::realIP(),
           
'user_agent'           => $ua,
           
'referrer'             => $referer,
           
'permalink'            => $permalink,
           
'comment_type'         => $type,
           
'comment_author'       => $author,
           
'comment_author_email' => $email,
           
'comment_author_url'   => $url,
           
'comment_content'      => $content,
        ];

       
$data = array_merge($data, $info);

       
$this->host = $this->ak_host;
       
$path       = sprintf($this->ak_path, $function);

        if (!
$this->post($path, $data, 'UTF-8')) {
            throw new
Exception('HTTP error: ' . $this->getError());    // @phpstan-ignore-line
       
}

        return
$this->getContent() == 'true';
    }
}