additional_plugins/serendipity_event_recaptcha/serendipity_event_recaptcha.php
Garvin Hicking 5731762a34 Added parameters to html_entity_decode() and htmlentities().
I did not use the wrapper method for those few occurences since it was too much work.
I'm sorry :-D
2014-11-29 12:18:56 +01:00

362 lines
14 KiB
PHP

<?php #
if (IN_serendipity !== true) {
die ("Don't hack!");
}
// Probe for a language include with constants. Still include defines later on, if some constants were missing
$probelang = dirname(__FILE__) . '/' . $serendipity['charset'] . 'lang_' . $serendipity['lang'] . '.inc.php';
if (file_exists($probelang)) {
include $probelang;
}
include dirname(__FILE__) . '/lang_en.inc.php';
require_once dirname(__FILE__) . '/recaptcha/recaptchalib.php';
$GLOBALS['recaptcha_api_server'] = 'http://api.recaptcha.net';
$GLOBALS['recaptcha_api_secure_server'] = 'https://api-secure.recaptcha.net';
$GLOBALS['recaptcha_verify_server'] = 'api-verify.recaptcha.net';
class serendipity_event_recaptcha extends serendipity_event
{
var $error=null;
function introspect(&$propbag)
{
global $serendipity;
$this->title = PLUGIN_EVENT_RECAPTCHA_TITLE;
$propbag->add('name', PLUGIN_EVENT_RECAPTCHA_TITLE);
$propbag->add('description', PLUGIN_EVENT_RECAPTCHA_DESC);
$propbag->add('stackable', false);
$propbag->add('author', 'Christian Brabandt (based on work of Garvin Hicking, Sebastian Nohn)');
$propbag->add('requirements', array(
'serendipity' => '1.0',
'smarty' => '2.6.7',
'php' => '4.1.0'
));
$propbag->add('version', '0.11');
$propbag->add('event_hooks', array(
'frontend_configure' => true,
'frontend_saveComment' => true,
'frontend_comment' => true
));
$propbag->add('configuration', array(
'info',
'sep',
'hide_for_authors',
'recaptcha',
'recaptcha_style',
'recaptcha_pub',
'recaptcha_priv',
'captchas_ttl',
'logtype',
'logfile'));
$propbag->add('groups', array('ANTISPAM'));
}
function introspect_config_item($name, &$propbag)
{
global $serendipity;
switch($name) {
case 'recaptcha':
$propbag->add('type', 'radio');
$propbag->add('name', PLUGIN_EVENT_RECAPTCHA_RECAPTCHA);
$propbag->add('description', PLUGIN_EVENT_RECAPTCHA_RECAPTCHA_DESC);
$propbag->add('default', 'no');
$propbag->add('radio', array(
'value' => array('yes', 'no'),
'desc' => array(YES, NO)
));
break;
case 'recaptcha_pub':
$propbag->add('type', 'string');
$propbag->add('name', PLUGIN_EVENT_RECAPTCHA_RECAPTCHA_PUB);
$propbag->add('description', PLUGIN_EVENT_RECAPTCHA_RECAPTCHA_PUB_DESC);
$propbag->add('default', '');
break;
case 'recaptcha_priv':
$propbag->add('type', 'string');
$propbag->add('name', PLUGIN_EVENT_RECAPTCHA_RECAPTCHA_PRIV);
$propbag->add('description', PLUGIN_EVENT_RECAPTCHA_RECAPTCHA_PRIV_DESC);
$propbag->add('default', '');
break;
case 'recaptcha_style':
$propbag->add('type', 'radio');
$propbag->add('name', PLUGIN_EVENT_RECAPTCHA_RECAPTCHA_STYLE);
$propbag->add('description', PLUGIN_EVENT_RECAPTCHA_RECAPTCHA_STYLE_DESC);
$propbag->add('default', 'red');
$propbag->add('radio', array(
'value' => array('red', 'white', 'blackglass'),
'desc' => array('Red', 'White', 'Blackglass')
));
break;
case 'hide_for_authors':
$_groups =& serendipity_getAllGroups();
$groups = array(
'all' => ALL_AUTHORS,
'none' => NONE
);
foreach($_groups AS $group) {
$groups[$group['confkey']] = $group['confvalue'];
}
$propbag->add('type', 'multiselect');
$propbag->add('name', PLUGIN_EVENT_RECAPTCHA_HIDE);
$propbag->add('description', PLUGIN_EVENT_RECAPTCHA_HIDE_DESC);
$propbag->add('select_values', $groups);
$propbag->add('select_size', 5);
$propbag->add('default', 'all');
break;
case 'logfile':
$propbag->add('type', 'string');
$propbag->add('name', PLUGIN_EVENT_RECAPTCHA_LOGFILE);
$propbag->add('description', PLUGIN_EVENT_RECAPTCHA_LOGFILE_DESC);
$propbag->add('default', $serendipity['serendipityPath'] . 'spamblock.log');
break;
case 'logtype':
$propbag->add('type', 'radio');
$propbag->add('name', PLUGIN_EVENT_RECAPTCHA_LOGTYPE);
$propbag->add('description', PLUGIN_EVENT_RECAPTCHA_LOGTYPE_DESC);
$propbag->add('default', 'db');
$propbag->add('radio', array(
'value' => array('file', 'db', 'none'),
'desc' => array(PLUGIN_EVENT_RECAPTCHA_LOGTYPE_FILE, PLUGIN_EVENT_RECAPTCHA_LOGTYPE_DB, PLUGIN_EVENT_RECAPTCHA_LOGTYPE_NONE)
));
$propbag->add('radio_per_row', '1');
break;
case 'captchas_ttl':
$propbag->add('type', 'string');
$propbag->add('name', PLUGIN_EVENT_RECAPTCHA_CAPTCHAS_TTL);
$propbag->add('description', PLUGIN_EVENT_RECAPTCHA_CAPTCHAS_TTL_DESC);
$propbag->add('default', '7');
break;
case 'info':
$suche='!http(?:s)?:\/\/(?:(?:[^.]*)\.)?([^.\/]*)!';
$result=preg_match($suche,$serendipity['baseURL'],$domain);
$propbag->add('type', 'content');
$propbag->add('default', PLUGIN_EVENT_RECAPTCHA_INFO1.$domain[1]. PLUGIN_EVENT_RECAPTCHA_INFO2);
break;
case 'sep':
$propbag->add('type', 'seperator');
break;
default:
return false;
}
return true;
}
function generate_content(&$title) {
$title = $this->title;
}
// Checks whether the current author is contained in one of the groups that
// need no spam checking
function inGroup() {
global $serendipity;
$checkgroups = explode('^', $this->get_config('hide_for_authors'));
if (!isset($serendipity['authorid']) || !is_array($checkgroups)) {
return false;
}
$mygroups =& serendipity_getGroups($serendipity['authorid'], true);
if (!is_array($mygroups)) {
return false;
}
foreach($checkgroups AS $key => $groupid) {
if ($groupid == 'all') {
return true;
} elseif (in_array($groupid, $mygroups)) {
return true;
}
}
return false;
}
function event_hook($event, &$bag, &$eventData, $addData = null) {
global $serendipity;
$hooks = &$bag->get('event_hooks');
if (isset($hooks[$event])) {
$captchas_ttl = $this->get_config('captchas_ttl', 7);
$_recaptcha = $this->get_config('recaptcha', 'no');
$recaptcha = ($_recaptcha ==='yes' || $_recaptcha !== 'no' || serendipity_db_bool($_recaptcha));
// Check if the entry is older than the allowed amount of time.
// Enforce captchas if that is true of if captchas are activated
// for every entry
$show_captcha = (($recaptcha) && isset($eventData['timestamp']) && ($captchas_ttl < 1 || ($eventData['timestamp'] < (time() - ($captchas_ttl*60*60*24)))) ? true : false);
switch($event) {
case 'frontend_configure':
// set a variable, so that the spamblock plugin can disable the captcha when recaptcha is found.
if ($_recaptcha) {
$serendipity['plugins']['disable_internal_captcha'] = true;
}
return true;
break;
case 'frontend_saveComment':
if (!is_array($eventData) || serendipity_db_bool($eventData['allow_comments'])) {
//$serendipity['csuccess'] = 'true';
$logfile = $this->logfile = $this->get_config('logfile', $serendipity['serendipityPath'] . 'spamblock.log');
// Check whether to allow comments from registered authors
if (serendipity_userLoggedIn() && $this->inGroup()) {
return true;
}
// Captcha checking
if ($show_captcha && $addData['type'] == 'NORMAL') {
$privatekey = $this->get_config('recaptcha_priv');
if ($_POST["recaptcha_response_field"] != 1) {
$resp = recaptcha_check_answer($privatekey,
$_SERVER["REMOTE_ADDR"],
$_POST["recaptcha_challenge_field"],
$_POST["recaptcha_response_field"]);
if (!$resp->is_valid) {
# set the error code so that we can display it
$this->error = $resp->error;
$this->log($logfile, $eventData['id'], 'REJECTED', $this->error, $addData);
$eventData = array('allow_comments' => false);
$serendipity['messagestack']['comments'][] = PLUGIN_EVENT_RECAPTCHA_ERROR_CAPTCHAS;
return false;
}
} else {
return false;
}
}
}
return true;
break;
case 'frontend_comment':
// Check whether to allow comments from registered authors
if (serendipity_userLoggedIn() && $this->inGroup()) {
return true;
}
if ($show_captcha) {
$pubkey = $this->get_config('recaptcha_pub');
$privkey = $this->get_config('recaptcha_priv');
if ( $recaptcha && (($pubkey == null || $pubkey == '') || ($privkey == null || $pubkey == '')) ) {
$recaptcha = false;
//$captchas = true;
printf('<div class="serendipity_center serendipity_msg_important">%s</div>',PLUGIN_EVENT_RECAPTCHA_ERROR_RECAPTCHA);
}
// The response from recaptcha.net
$resp = null;
$theme = $this->get_config('recaptcha_style', 'red');
echo "\n<script type=\"text/javascript\">\n var RecaptchaOptions = { theme : '".$theme."', lang : '" . $serendipity['lang'] . "' };\n</script>";
echo recaptcha_get_html($pubkey, $this->error);
}
return true;
break;
default:
return false;
break;
}
} else {
return false;
}
}
function log($logfile, $id, $switch, $reason, $comment) {
global $serendipity;
$method = $this->get_config('logtype');
switch($method) {
case 'file':
if (empty($logfile)) {
return;
}
$fp = @fopen($logfile, 'a+');
if (!is_resource($fp)) {
return;
}
fwrite($fp, sprintf(
'[%s] - [%s: %s] - [#%s, Name "%s", E-Mail "%s", URL "%s", User-Agent "%s", IP %s] - [%s]' . "\n",
date('Y-m-d H:i:s', serendipity_serverOffsetHour()),
$switch,
$reason,
$id,
str_replace("\n", ' ', $comment['name']),
str_replace("\n", ' ', $comment['email']),
str_replace("\n", ' ', $comment['url']),
str_replace("\n", ' ', $_SERVER['HTTP_USER_AGENT']),
$_SERVER['REMOTE_ADDR'],
str_replace("\n", ' ', $comment['comment'])
));
fclose($fp);
break;
case 'none':
return;
break;
case 'db':
default:
$q = sprintf("INSERT INTO {$serendipity['dbPrefix']}spamblocklog
(timestamp, type, reason, entry_id, author, email, url, useragent, ip, referer, body)
VALUES (%d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s')",
serendipity_serverOffsetHour(),
serendipity_db_escape_string($switch),
serendipity_db_escape_string($reason),
serendipity_db_escape_string($id),
serendipity_db_escape_string($comment['name']),
serendipity_db_escape_string($comment['email']),
serendipity_db_escape_string($comment['url']),
serendipity_db_escape_string($_SERVER['HTTP_USER_AGENT']),
serendipity_db_escape_string($_SERVER['REMOTE_ADDR']),
serendipity_db_escape_string(isset($_SESSION['HTTP_REFERER']) ? $_SESSION['HTTP_REFERER'] : $_SERVER['HTTP_REFERER']),
serendipity_db_escape_string($comment['comment'])
);
serendipity_db_query($q);
break;
}
}
}
/* vim: set sts=4 ts=4 expandtab : */