2012-07-06 16:57:26 +02:00
< ? 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' ;
2012-08-16 23:35:02 +02:00
include dirname ( __FILE__ ) . '/version.inc.php' ;
2012-07-07 13:32:50 +02:00
require_once dirname ( __FILE__ ) . '/json/json.php4.include.php' ;
2012-07-06 16:57:26 +02:00
@ define ( 'PLUGIN_EVENT_SPAMBLOCK_BEE_DEBUG' , FALSE );
2012-07-07 19:37:28 +02:00
@ define ( 'PLUGIN_EVENT_SPAMBLOCK_SWTCH_OFF' , 'OFF' );
@ define ( 'PLUGIN_EVENT_SPAMBLOCK_SWTCH_MODERATE' , 'MODERATE' );
@ define ( 'PLUGIN_EVENT_SPAMBLOCK_SWTCH_REJECT' , 'REJECT' );
2012-08-12 16:57:59 +02:00
/**
* Serendipity plug - in for providing spam protection via a
* Honey Pot field and a hidden Captcha .
*
* @ author Grischa Brockhaus
* @ author Janek Bevendorff
*/
2012-07-06 16:57:26 +02:00
class serendipity_event_spamblock_bee extends serendipity_event
{
2012-08-12 16:57:59 +02:00
/**
* Plug - in title
* @ var string
*/
var $title = PLUGIN_EVENT_SPAMBLOCK_BEE_TITLE ;
/**
* Whether to use a Honey Pot
* @ var boolean
*/
var $useHoneyPot = true ;
/**
* Whether the Captcha is enabled and what to do when validation failed
* @ var string
*/
var $hiddenCaptchaHandle = null ;
/**
* Method for retrieving the correct answer of the hidden Captcha .
* Either 'default' , 'json' or 'smarty' .
* @ var string
*/
2012-08-12 16:05:43 +02:00
var $answerRetrievalMethod = null ;
2012-08-12 16:57:59 +02:00
/**
* Correct answer for the Captcha . If RegExp matching is on , it ' ll
* also contain an index 'pattern'
* @ var array
*/
var $captchaAnswer = array ( 'answer' => null );
/**
* Type of question asked in the Captcha . This is either 'math' or 'custom'
* @ var string
*/
var $captchaQuestionType = null ;
/**
* Whether to use RegExp matching for the hidden Captcha
* @ var boolean
*/
2012-08-12 16:05:43 +02:00
var $useRegularExpressions = false ;
2012-08-12 16:57:59 +02:00
/**
* Constructor . Initialize class variables from configuration
* @ return void
*/
2012-08-12 16:05:43 +02:00
function serendipity_event_spamblock_bee () {
$this -> answerRetrievalMethod = $this -> get_config ( 'answer_retrieval_method' , 'default' );
$this -> captchaQuestionType = $this -> get_config ( 'question_type' , 'math' );
$this -> useHoneyPot = $this -> get_config ( 'do_honeypot' , true );
$this -> hiddenCaptchaHandle = $this -> get_config ( 'do_hiddencaptcha' , PLUGIN_EVENT_SPAMBLOCK_SWTCH_MODERATE );
$this -> useRegularExpressions = $this -> get_config ( 'use_regexp' , false );
}
2012-07-06 16:57:26 +02:00
2012-08-12 16:57:59 +02:00
/**
* Declare Serendipity backend properties .
*
* @ param serendipity_property_bag $propbag
*/
2012-07-06 16:57:26 +02:00
function introspect ( & $propbag )
{
global $serendipity ;
$propbag -> add ( 'name' , PLUGIN_EVENT_SPAMBLOCK_BEE_TITLE );
$propbag -> add ( 'description' , PLUGIN_EVENT_SPAMBLOCK_BEE_DESC );
$propbag -> add ( 'stackable' , false );
2012-08-15 02:19:32 +02:00
$propbag -> add ( 'author' , 'Grischa Brockhaus, Janek Bevendorff' );
2012-07-06 16:57:26 +02:00
$propbag -> add ( 'requirements' , array (
'serendipity' => '0.8' ,
'smarty' => '2.6.7' ,
'php' => '4.1.0'
));
2012-07-06 18:36:18 +02:00
2012-08-16 23:35:02 +02:00
$propbag -> add ( 'version' , PLUGIN_SPAMBLOCK_BEE_VERSION ); // setup via version.inc.php
2012-07-06 18:36:18 +02:00
2012-07-06 16:57:26 +02:00
$propbag -> add ( 'event_hooks' , array (
'frontend_comment' => true ,
'frontend_saveComment' => true ,
2012-08-12 16:05:43 +02:00
'frontend_footer' => true ,
'css' => true ,
2012-07-06 18:36:18 +02:00
'external_plugin' => true ,
2012-07-06 16:57:26 +02:00
));
$propbag -> add ( 'groups' , array ( 'ANTISPAM' ));
2012-07-07 13:32:50 +02:00
$configuration = array ( 'header_desc' , 'do_honeypot' , 'do_hiddencaptcha' );
2012-07-06 17:39:08 +02:00
if ( ! class_exists ( 'serendipity_event_spamblock' )) { // Only do that, if spamblock is not installed.
2012-07-07 16:44:20 +02:00
$configuration = array_merge ( $configuration , array ( 'entrytitle' , 'samebody' , 'required_fields' ));
2012-07-06 17:39:08 +02:00
}
2012-07-07 13:32:50 +02:00
$configuration = array_merge ( $configuration , array ( 'spamlogtype' , 'spamlogfile' , 'plugin_path' ));
2012-08-16 00:44:49 +02:00
$configuration = array_merge ( $configuration , array (
'advanced_cc_desc' , 'answer_retrieval_method' , 'question_type' ,
2012-08-16 13:18:07 +02:00
'questions' , 'answers' , 'use_regexp'
2012-08-16 00:44:49 +02:00
));
2012-07-06 16:57:26 +02:00
$propbag -> add ( 'configuration' , $configuration );
2012-07-07 13:32:50 +02:00
$propbag -> add ( 'config_groups' , array (
2012-08-11 22:02:16 +02:00
PLUGIN_EVENT_SPAMBLOCK_BEE_CONFIG_SECTION_LOGGING => array (
2012-08-12 16:05:43 +02:00
'spamlogtype' , 'spamlogfile' , 'plugin_path'
2012-08-11 22:02:16 +02:00
),
PLUGIN_EVENT_SPAMBLOCK_BEE_CONFIG_SECTION_ADVANCED => array (
2012-08-16 00:44:49 +02:00
'advanced_cc_desc' , 'answer_retrieval_method' , 'question_type' ,
2012-08-16 13:18:07 +02:00
'questions' , 'answers' , 'use_regexp'
2012-07-07 13:32:50 +02:00
)
2012-08-11 22:02:16 +02:00
)
2012-07-07 13:32:50 +02:00
);
2012-07-06 16:57:26 +02:00
}
2012-08-12 16:57:59 +02:00
/**
* Set plug - in title .
*
* @ param string $title
*/
2012-07-06 16:57:26 +02:00
function generate_content ( & $title ) {
$title = PLUGIN_EVENT_SPAMBLOCK_BEE_TITLE ;
}
2012-08-12 16:57:59 +02:00
/**
* Generate backend configuration fields
*
* @ param string $name field name
* @ param serendipity_property_bag $propbag properties
* @ return bool
*/
2012-07-06 16:57:26 +02:00
function introspect_config_item ( $name , & $propbag )
{
global $serendipity ;
2012-07-07 19:37:28 +02:00
$rejectType = array (
PLUGIN_EVENT_SPAMBLOCK_SWTCH_OFF => PLUGIN_EVENT_SPAMBLOCK_BEE_RESULT_OFF ,
PLUGIN_EVENT_SPAMBLOCK_SWTCH_MODERATE => PLUGIN_EVENT_SPAMBLOCK_BEE_RESULT_MODERATE ,
2012-08-12 16:05:43 +02:00
PLUGIN_EVENT_SPAMBLOCK_SWTCH_REJECT => PLUGIN_EVENT_SPAMBLOCK_BEE_RESULT_REJECT ,
2012-07-07 19:37:28 +02:00
);
2012-08-11 22:02:16 +02:00
$retrievalMethod = array (
2012-08-16 13:18:07 +02:00
'default' => PLUGIN_EVENT_SPAMBLOCK_BEE_CONFIG_ADV_RM_DEFAULT ,
'json' => PLUGIN_EVENT_SPAMBLOCK_BEE_CONFIG_ADV_RM_JSON ,
'smarty' => PLUGIN_EVENT_SPAMBLOCK_BEE_CONFIG_ADV_RM_SMARTY ,
'smarty_enc' => PLUGIN_EVENT_SPAMBLOCK_BEE_CONFIG_ADV_RM_SMARTY_ENC
2012-08-11 22:02:16 +02:00
);
$questionType = array (
2012-08-16 13:18:07 +02:00
'math' => PLUGIN_EVENT_SPAMBLOCK_BEE_CONFIG_ADV_QT_MATH ,
2012-08-11 22:02:16 +02:00
'custom' => PLUGIN_EVENT_SPAMBLOCK_BEE_CONFIG_ADV_QT_CUSTOM
);
2012-07-06 16:57:26 +02:00
switch ( $name ) {
2012-07-06 17:39:08 +02:00
case 'header_desc' :
2012-08-11 22:02:16 +02:00
$propbag -> add ( 'type' , 'content' );
$propbag -> add ( 'default' , PLUGIN_EVENT_SPAMBLOCK_BEE_EXTRA_DESC .
'<img src="' . $serendipity [ 'baseURL' ] . 'index.php?/plugin/spamblockbee.png" alt="" title="' . PLUGIN_EVENT_SPAMBLOCK_BEE_TITLE . '" style="float:right">' );
2012-07-06 17:39:08 +02:00
break ;
2012-07-07 19:37:28 +02:00
2012-07-06 16:57:26 +02:00
case 'do_honeypot' :
$propbag -> add ( 'type' , 'boolean' );
$propbag -> add ( 'name' , PLUGIN_EVENT_SPAMBLOCK_BEE_CONFIG_SPAM_HONEYPOT );
$propbag -> add ( 'description' , PLUGIN_EVENT_SPAMBLOCK_BEE_CONFIG_SPAM_HONEYPOT_DESC );
$propbag -> add ( 'default' , true );
break ;
2012-08-11 22:02:16 +02:00
2012-07-07 13:32:50 +02:00
case 'do_hiddencaptcha' :
2012-07-07 19:37:28 +02:00
$propbag -> add ( 'type' , 'select' );
2012-07-07 13:32:50 +02:00
$propbag -> add ( 'name' , PLUGIN_EVENT_SPAMBLOCK_BEE_CONFIG_SPAM_HCAPTCHA );
$propbag -> add ( 'description' , PLUGIN_EVENT_SPAMBLOCK_BEE_CONFIG_SPAM_HCAPTCHA_DESC );
2012-07-07 19:37:28 +02:00
$propbag -> add ( 'select_values' , $rejectType );
$propbag -> add ( 'default' , PLUGIN_EVENT_SPAMBLOCK_SWTCH_MODERATE );
break ;
case 'required_fields' :
2012-08-11 22:02:16 +02:00
$propbag -> add ( 'type' , 'string' );
$propbag -> add ( 'name' , PLUGIN_EVENT_SPAMBLOCK_BEE_REQUIRED_FIELDS );
2012-07-07 19:37:28 +02:00
$propbag -> add ( 'description' , PLUGIN_EVENT_SPAMBLOCK_BEE_REQUIRED_FIELDS_DESC );
2012-08-11 22:02:16 +02:00
$propbag -> add ( 'default' , '' );
2012-07-07 13:32:50 +02:00
break ;
2012-08-11 22:02:16 +02:00
2012-07-07 19:37:28 +02:00
case 'entrytitle' :
2012-08-11 22:02:16 +02:00
$propbag -> add ( 'type' , 'select' );
$propbag -> add ( 'name' , PLUGIN_EVENT_SPAMBLOCK_BEE_FILTER_TITLE );
$propbag -> add ( 'description' , PLUGIN_EVENT_SPAMBLOCK_BEE_FILTER_TITLE_DESC );
$propbag -> add ( 'select_values' , $rejectType );
$propbag -> add ( 'default' , PLUGIN_EVENT_SPAMBLOCK_SWTCH_REJECT );
2012-07-07 19:37:28 +02:00
break ;
2012-08-11 22:02:16 +02:00
2012-07-07 19:37:28 +02:00
case 'samebody' :
2012-08-11 22:02:16 +02:00
$propbag -> add ( 'type' , 'select' );
$propbag -> add ( 'name' , PLUGIN_EVENT_SPAMBLOCK_BEE_FILTER_SAMEBODY );
$propbag -> add ( 'description' , PLUGIN_EVENT_SPAMBLOCK_BEE_FILTER_SAMEBODY_DESC );
2012-07-07 19:37:28 +02:00
$propbag -> add ( 'select_values' , $rejectType );
2012-08-11 22:02:16 +02:00
$propbag -> add ( 'default' , PLUGIN_EVENT_SPAMBLOCK_SWTCH_REJECT );
2012-07-07 19:37:28 +02:00
break ;
2012-07-06 16:57:26 +02:00
case 'spamlogtype' :
$logtypevalues = array (
'none' => PLUGIN_EVENT_SPAMBLOCK_BEE_CONFIG_SPAM_LOGTYPE_NONE ,
'file' => PLUGIN_EVENT_SPAMBLOCK_BEE_CONFIG_SPAM_LOGTYPE_FILE ,
'db' => PLUGIN_EVENT_SPAMBLOCK_BEE_CONFIG_SPAM_LOGTYPE_DATABASE ,
);
2012-08-11 22:02:16 +02:00
$propbag -> add ( 'type' , 'select' );
$propbag -> add ( 'name' , PLUGIN_EVENT_SPAMBLOCK_BEE_CONFIG_SPAM_LOGTYPE );
$propbag -> add ( 'description' , PLUGIN_EVENT_SPAMBLOCK_BEE_CONFIG_SPAM_LOGTYPE_DESC );
2012-07-06 16:57:26 +02:00
$propbag -> add ( 'select_values' , $logtypevalues );
2012-08-11 22:02:16 +02:00
$propbag -> add ( 'default' , 'none' );
2012-07-06 16:57:26 +02:00
break ;
2012-08-11 22:02:16 +02:00
2012-07-06 16:57:26 +02:00
case 'spamlogfile' :
2012-08-11 22:02:16 +02:00
$propbag -> add ( 'type' , 'string' );
$propbag -> add ( 'name' , PLUGIN_EVENT_SPAMBLOCK_BEE_CONFIG_SPAM_LOGFILE );
2012-07-06 16:57:26 +02:00
$propbag -> add ( 'description' , PLUGIN_EVENT_SPAMBLOCK_BEE_CONFIG_SPAM_LOGFILE_DESC );
2012-08-11 22:02:16 +02:00
$propbag -> add ( 'default' , $serendipity [ 'serendipityPath' ] . 'spamblock.log' );
2012-07-06 16:57:26 +02:00
break ;
2012-07-07 19:37:28 +02:00
2012-07-06 16:57:26 +02:00
case 'plugin_path' :
2012-08-11 22:02:16 +02:00
$propbag -> add ( 'type' , 'string' );
$propbag -> add ( 'name' , PLUGIN_EVENT_SPAMBLOCK_BEE_PATH );
2012-07-06 16:57:26 +02:00
$propbag -> add ( 'description' , PLUGIN_EVENT_SPAMBLOCK_BEE_PATH_DESC );
2012-08-11 22:02:16 +02:00
$propbag -> add ( 'default' , $serendipity [ 'serendipityHTTPPath' ] . 'plugins/serendipity_event_spamblock_bee/' );
2012-07-06 16:57:26 +02:00
break ;
2012-08-11 22:02:16 +02:00
case 'advanced_cc_desc' :
$propbag -> add ( 'type' , 'content' );
$propbag -> add ( 'default' , PLUGIN_EVENT_SPAMBLOCK_BEE_CONFIG_ADV_DESC );
break ;
case 'answer_retrieval_method' :
$propbag -> add ( 'type' , 'select' );
$propbag -> add ( 'name' , PLUGIN_EVENT_SPAMBLOCK_BEE_CONFIG_ADV_ANSWER_RETRIEVAL );
$propbag -> add ( 'description' , PLUGIN_EVENT_SPAMBLOCK_BEE_CONFIG_ADV_ANSWER_RETRIEVAL_DESC );
$propbag -> add ( 'select_values' , $retrievalMethod );
$propbag -> add ( 'default' , 'default' );
break ;
case 'question_type' :
$propbag -> add ( 'type' , 'select' );
$propbag -> add ( 'name' , PLUGIN_EVENT_SPAMBLOCK_BEE_CONFIG_ADV_QUESTION_TYPE );
$propbag -> add ( 'description' , PLUGIN_EVENT_SPAMBLOCK_BEE_CONFIG_ADV_QUESTION_TYPE_DESC );
$propbag -> add ( 'select_values' , $questionType );
$propbag -> add ( 'default' , 'math' );
break ;
case 'questions' :
$propbag -> add ( 'type' , 'text' );
2012-08-15 02:04:51 +02:00
$propbag -> add ( 'rows' , 8 );
2012-08-11 22:02:16 +02:00
$propbag -> add ( 'name' , PLUGIN_EVENT_SPAMBLOCK_BEE_CONFIG_ADV_QUESTIONS );
$propbag -> add ( 'description' , PLUGIN_EVENT_SPAMBLOCK_BEE_CONFIG_ADV_QUESTIONS_DESC );
$propbag -> add ( 'default' , PLUGIN_EVENT_SPAMBLOCK_BEE_CONFIG_ADV_DEFAULT_QUESTIONS );
break ;
case 'answers' :
$propbag -> add ( 'type' , 'text' );
2012-08-15 02:04:51 +02:00
$propbag -> add ( 'rows' , 8 );
2012-08-11 22:02:16 +02:00
$propbag -> add ( 'name' , PLUGIN_EVENT_SPAMBLOCK_BEE_CONFIG_ADV_ANSWERS );
$propbag -> add ( 'description' , PLUGIN_EVENT_SPAMBLOCK_BEE_CONFIG_ADV_ANSWERS_DESC );
$propbag -> add ( 'default' , PLUGIN_EVENT_SPAMBLOCK_BEE_CONFIG_ADV_DEFAULT_ANSWERS );
break ;
case 'use_regexp' :
$propbag -> add ( 'type' , 'boolean' );
$propbag -> add ( 'name' , PLUGIN_EVENT_SPAMBLOCK_BEE_CONFIG_ADV_USE_REGEXP );
$propbag -> add ( 'description' , PLUGIN_EVENT_SPAMBLOCK_BEE_CONFIG_ADV_USE_REGEXP_DESC );
$propbag -> add ( 'default' , false );
break ;
2012-07-06 16:57:26 +02:00
default :
return false ;
}
return true ;
}
2012-08-12 16:57:59 +02:00
/**
* Hook for Serendipity events , initialize plug - in features
*
* @ param string $event
* @ param serendipity_property_bag $bag
* @ param array $eventData
* @ param array $addData
* @ return bool
*/
2012-07-06 16:57:26 +02:00
function event_hook ( $event , & $bag , & $eventData , $addData = null ) {
global $serendipity ;
2012-08-12 16:57:59 +02:00
2012-07-06 16:57:26 +02:00
$hooks = & $bag -> get ( 'event_hooks' );
if ( isset ( $hooks [ $event ])) {
switch ( $event ) {
2012-07-06 18:36:18 +02:00
case 'external_plugin' :
switch ( $eventData ) {
case 'spamblockbee.png' :
header ( 'Content-Type: image/png' );
echo file_get_contents ( dirname ( __FILE__ ) . '/spamblockbee.png' );
break ;
2012-07-07 13:32:50 +02:00
case 'spamblockbeecaptcha' :
2012-08-12 16:05:43 +02:00
echo $this -> produceCaptchaAnswerJson ();
2012-07-07 13:32:50 +02:00
break ;
2012-07-06 18:36:18 +02:00
}
break ;
2012-07-06 16:57:26 +02:00
case 'frontend_saveComment' :
2012-08-12 16:05:43 +02:00
// Check only, if no one else denied it before
if ( ! is_array ( $eventData ) || serendipity_db_bool ( $eventData [ 'allow_comments' ] )) {
return $this -> checkComment ( $eventData , $addData );
}
2012-07-07 19:37:28 +02:00
return true ;
2012-08-12 16:05:43 +02:00
break ;
2012-07-06 16:57:26 +02:00
case 'frontend_comment' :
$this -> printCommentEditExtras ( $eventData , $addData );
break ;
2012-07-07 13:32:50 +02:00
case 'frontend_footer' :
// Comment header code only if in single article mode
if ( ! empty ( $eventData [ 'GET' ][ 'id' ])) {
$this -> printJsExtras ();
}
break ;
case 'css' :
2012-07-06 16:57:26 +02:00
$this -> printCss ( $eventData , $addData );
break ;
default :
return false ;
break ;
}
return true ;
} else {
return false ;
}
}
2012-08-12 16:05:43 +02:00
2012-08-12 16:57:59 +02:00
/**
* Check if Honey Pot or Captcha have been filled correctly ( or if any
* other indications for spam can be found ) .
*
* @ param array $eventData
* @ param array $addData
* @ return bool
*/
2012-07-06 16:57:26 +02:00
function checkComment ( & $eventData , & $addData ) {
global $serendipity ;
if ( " NORMAL " == $addData [ 'type' ]) { // only supported for normal comments
2012-07-07 19:37:28 +02:00
2012-08-12 16:57:59 +02:00
// Check for Honey Pot:
2012-08-17 13:39:01 +02:00
$phone = $serendipity [ 'POST' ][ 'phone' ];
if ( $this -> useHoneyPot && ( ! empty ( $phone ) || $phone == '0' ) ) {
if ( mb_strlen ( $phone ) > 40 ) {
2012-08-16 23:35:02 +02:00
$phone = mb_substr ( $phone , 0 , 40 ) . '..' ;
2012-08-17 13:39:01 +02:00
}
$this -> spamlog ( $eventData [ 'id' ], 'REJECTED' , " BEE Honeypot [ " . $phone . " ] " , $addData );
2012-07-06 16:57:26 +02:00
$eventData = array ( 'allow_comments' => false );
return false ;
}
2012-08-12 16:05:43 +02:00
// Check hidden Captcha
if ( PLUGIN_EVENT_SPAMBLOCK_SWTCH_OFF != $this -> hiddenCaptchaHandle ) {
$answer = trim ( strtolower ( $serendipity [ 'POST' ][ 'beecaptcha' ]));
$correctAnswer = $this -> getCaptchaAnswer ();
$correctAnswer [ 'answer' ] = strtolower ( $correctAnswer [ 'answer' ]);
$isCorrect = false ;
2012-08-11 22:02:16 +02:00
2012-08-12 16:05:43 +02:00
// If provided answer is longer than 1000 characters and RegExp matching is on,
// reject comment for security reasons (minimize risk of ReDoS)
2012-08-17 13:30:35 +02:00
if ( $this -> useRegularExpressions && mb_strlen ( $answer ) > 1000 ) {
2012-08-15 02:17:43 +02:00
$this -> processComment ( $this -> hiddenCaptchaHandle , $eventData , $addData , PLUGIN_EVENT_SPAMBLOCK_BEE_ERROR_HCAPTCHA , " BEE HiddenCaptcha [ Captcha input too long ] " );
2012-08-12 16:05:43 +02:00
return false ;
2012-08-11 22:02:16 +02:00
}
2012-08-12 16:05:43 +02:00
if ( $this -> captchaQuestionType == 'custom' && $this -> useRegularExpressions ) {
// Sanitize regular expression and remove answer part
$pattern = preg_replace ( '/^\s*\/(.*)\/\s*[imsxeADSUXJu]*\s*$/s' , '$1' , $correctAnswer [ 'pattern' ]);
// Try to match pattern with given answer
$match = @ preg_match ( '/' . $pattern . '/si' , $answer );
// If pattern contains errors, fall back to basic string comparison
if ( $match === false ) {
$this -> useRegularExpressions = false ;
} else {
$isCorrect = ( $match === 1 );
2012-07-06 16:57:26 +02:00
}
}
2012-08-12 16:05:43 +02:00
if ( $this -> captchaQuestionType != 'custom' || ! $this -> useRegularExpressions ) {
$isCorrect = ( $answer == $correctAnswer [ 'answer' ]);
}
// Also allow numbers as words
if ( ! $isCorrect && $this -> captchaQuestionType == 'math' ) {
$number = $this -> generateNumberString ( $correctAnswer [ 'answer' ]);
$isCorrect = ( $answer == $number && $number != 'ERROR' );
}
if ( ! $isCorrect ) {
2012-08-17 13:30:35 +02:00
if ( mb_strlen ( $answer ) > 40 ) {
2012-08-16 23:35:02 +02:00
$answer = mb_substr ( $answer , 0 , 40 ) . '..' ;
2012-08-17 13:30:35 +02:00
}
$this -> processComment ( $this -> hiddenCaptchaHandle , $eventData , $addData , PLUGIN_EVENT_SPAMBLOCK_BEE_ERROR_HCAPTCHA , " BEE HiddenCaptcha [ $correctAnswer[answer] != $answer ] " );
2012-08-12 17:46:56 +02:00
return $isCorrect ;
2012-08-12 16:05:43 +02:00
}
2012-07-06 16:57:26 +02:00
}
2012-08-16 14:06:16 +02:00
// AntiSpam check, the general spamblock supports, too: Only if spamblock is not installed.
if ( ! class_exists ( 'serendipity_event_spamblock' )) {
// Check for required fields. Don't log but tell the user about the fields.
$required_fields = $this -> get_config ( 'required_fields' , '' );
if ( ! empty ( $required_fields )) {
$required_field_list = explode ( ',' , $required_fields );
foreach ( $required_field_list as $required_field ) {
$required_field = trim ( $required_field );
if ( empty ( $addData [ $required_field ])) {
$this -> reject ( $eventData , $addData , sprintf ( PLUGIN_EVENT_SPAMBLOCK_BEE_REASON_REQUIRED_FIELD , $required_field ));
return false ;
}
}
}
}
2012-08-11 22:02:16 +02:00
}
2012-07-07 13:32:50 +02:00
// AntiSpam check, the general spamblock supports, too: Only if spamblock is not installed.
if ( ! class_exists ( 'serendipity_event_spamblock' )) {
2012-08-16 14:06:16 +02:00
2012-07-07 13:32:50 +02:00
// Check if entry title is the same as comment body
2012-07-08 13:12:07 +02:00
$spamHandle = $this -> get_config ( 'entrytitle' , PLUGIN_EVENT_SPAMBLOCK_SWTCH_REJECT );
2012-08-12 17:46:56 +02:00
if ( PLUGIN_EVENT_SPAMBLOCK_SWTCH_OFF != $spamHandle ) {
// Remove the blog name from the comment which might be in <title>
$comment = str_replace ( $serendipity [ 'blogTitle' ], '' , $addData [ 'comment' ]);
2012-08-16 21:56:25 +02:00
$comment = str_replace ( $eventData [ 'title' ], '' , $comment );
// Now blog- and entry title was stripped from comment.
// Remove special letters, that might have been between them:
$comment = trim ( preg_replace ( '@[\s\-_:\(\)\|/]*@' , '' , $comment ));
// Now that we stripped blog and entry title: Do we have an empty comment?
if ( empty ( $comment )) {
2012-08-12 17:46:56 +02:00
$this -> processComment ( $spamHandle , $eventData , $addData , PLUGIN_EVENT_SPAMBLOCK_BEE_ERROR_BODY , " BEE Body the same as title " );
return false ;
}
2012-07-07 16:44:20 +02:00
}
// This check loads from DB, so do it last!
// Check if we already have a comment with the same body. (it's a reload normaly)
2012-07-08 13:12:07 +02:00
$spamHandle = $this -> get_config ( 'samebody' , PLUGIN_EVENT_SPAMBLOCK_SWTCH_REJECT );
if ( PLUGIN_EVENT_SPAMBLOCK_SWTCH_OFF != $spamHandle ) {
2012-07-07 16:44:20 +02:00
$query = " SELECT count(id) AS counter FROM { $serendipity [ 'dbPrefix' ] } comments WHERE type = ' " . $addData [ 'type' ] . " ' AND body = ' " . serendipity_db_escape_string ( $addData [ 'comment' ]) . " ' " ;
// This is a little different to the normal Spam Plugin:
// We allow the same comment, if it is a trackback, but never on the same article
// (One article sending trackbacks to more than one local article)
if ( $addData [ 'type' ] == 'PINGBACK' || $addData [ 'type' ] == 'TRACKBACK' ) {
$query .= ' AND entry_id=' . $eventData [ 'id' ];
}
$row = serendipity_db_query ( $query , true );
if ( is_array ( $row ) && $row [ 'counter' ] > 0 ) {
2012-07-08 13:12:07 +02:00
$this -> processComment ( $spamHandle , $eventData , $addData , PLUGIN_EVENT_SPAMBLOCK_BEE_ERROR_BODY , " BEE Body already saved " );
2012-07-07 16:44:20 +02:00
return false ;
}
2012-07-07 13:32:50 +02:00
}
}
2012-07-06 16:57:26 +02:00
return true ;
}
2012-07-07 19:37:28 +02:00
/**
2012-08-12 16:57:59 +02:00
* Reject or moderate a comment . Convenience function .
*
* @ param string $spamHandle
* @ param array $eventData
* @ param array $addData
* @ param string $remoteResponse
* @ param string $logResponse
* @ return void
2012-07-07 19:37:28 +02:00
*/
2012-07-08 13:12:07 +02:00
function processComment ( $spamHandle , & $eventData , & $addData , $remoteResponse , $logResponse = NULL ) {
if ( $spamHandle == PLUGIN_EVENT_SPAMBLOCK_SWTCH_MODERATE ) {
$this -> moderate ( $eventData , $addData , $remoteResponse , $logResponse );
2012-07-07 19:37:28 +02:00
}
else {
$this -> reject ( $eventData , $addData , $remoteResponse , $logResponse );
}
}
/**
2012-08-12 16:57:59 +02:00
* Reject a comment with optional log entry .
*
* @ param array $eventData
* @ param array $addData
* @ param string $remoteResponse
* @ param string $logResponse
2012-07-07 19:37:28 +02:00
*/
function reject ( & $eventData , & $addData , $remoteResponse , $logResponse = NULL ) {
global $serendipity ;
2012-08-12 16:57:59 +02:00
2012-07-07 19:37:28 +02:00
if ( ! empty ( $logResponse )) {
$this -> spamlog ( $eventData [ 'id' ], 'REJECTED' , $logResponse , $addData );
}
$eventData = array ( 'allow_comments' => false );
2012-07-11 23:14:49 +02:00
$serendipity [ 'csuccess' ] = 'false' ;
2012-07-07 19:37:28 +02:00
$serendipity [ 'messagestack' ][ 'comments' ][] = $remoteResponse ;
2012-08-12 16:57:59 +02:00
2012-07-11 23:14:49 +02:00
$this -> log ( print_r ( $serendipity [ 'messagestack' ], true ));
2012-07-07 19:37:28 +02:00
}
2012-08-12 16:57:59 +02:00
2012-07-07 19:37:28 +02:00
/**
2012-07-08 13:12:07 +02:00
* Moderate a comment with optional log entry
2012-08-12 16:57:59 +02:00
* @ param array $eventData
* @ param array $addData
* @ param string $remoteResponse
* @ param string $logResponse
* @ return void
2012-07-07 19:37:28 +02:00
*/
2012-07-08 13:12:07 +02:00
function moderate ( & $eventData , & $addData , $remoteResponse , $logResponse = NULL ) {
2012-07-07 19:37:28 +02:00
global $serendipity ;
2012-07-11 23:14:49 +02:00
2012-07-08 13:12:07 +02:00
if ( ! empty ( $logResponse )) {
2012-07-11 23:14:49 +02:00
$this -> spamlog ( $eventData [ 'id' ], 'MODERATE' , $logResponse , $addData );
2012-07-08 13:12:07 +02:00
}
2012-07-07 19:37:28 +02:00
$eventData [ 'moderate_comments' ] = true ;
$serendipity [ 'csuccess' ] = 'moderate' ;
$serendipity [ 'moderate_reason' ] = $remoteResponse ;
2012-07-11 23:14:49 +02:00
$serendipity [ 'messagestack' ][ 'comments' ][] = $remoteResponse ;
$this -> log ( print_r ( $serendipity [ 'messagestack' ], true ));
2012-07-07 19:37:28 +02:00
}
2012-08-12 16:57:59 +02:00
/**
* Produce JSON string with the correct for fetching via Ajax .
*
* @ return string The generated JSON string
*/
2012-08-12 16:05:43 +02:00
function produceCaptchaAnswerJson () {
2012-08-16 00:44:49 +02:00
$answer = $this -> getCaptchaAnswer ();
$scrambleKey = rand ();
if ( ! isset ( $answer [ 'answer' ])) {
$answer = array ( 'answer' => 'ERROR' );
2012-08-16 13:18:07 +02:00
} else {
2012-08-16 00:44:49 +02:00
$answer [ 'answer' ] = rawurlencode ( $this -> xorScramble ( $answer [ 'answer' ], $scrambleKey ));
$answer [ 'scrambleKey' ] = $scrambleKey ;
2012-08-11 22:02:16 +02:00
}
2012-08-16 00:44:49 +02:00
return json_encode ( $answer );
2012-07-07 13:32:50 +02:00
}
2012-08-12 16:57:59 +02:00
/**
* Write the Honey Pot and Captcha field to the output buffer .
*
* @ param array $eventData
* @ param array $addData
*/
function printCommentEditExtras ( & $eventData , & $addData ) {
global $serendipity ;
2012-08-12 19:18:53 +02:00
2012-08-12 16:57:59 +02:00
// Don't put extras on admin menu. They are not working there:
if ( isset ( $eventData [ 'GET' ][ 'action' ]) && $eventData [ 'GET' ][ 'action' ] == 'admin' ) return ;
// Honeypot
if ( serendipity_db_bool ( $this -> useHoneyPot )) {
echo '<div id="serendipity_comment_phone" class="serendipity_commentDirection comment_phone_input" >' . " \n " ;
echo '<label for="serendipity_commentform_phone">Phone*</label>' . " \n " ;
echo '<input class="comment_phone_input" type="text" id="serendipity_commentform_phone" name="serendipity[phone]" value="" placeholder="' . PLUGIN_EVENT_SPAMBLOCK_BEE_WARN_HONEPOT . '"/>' . " \n " ;
echo " </div> \n " ;
}
// Captcha
if ( PLUGIN_EVENT_SPAMBLOCK_SWTCH_OFF != $this -> hiddenCaptchaHandle ) {
$question = $this -> generateCaptchaQuestion ();
echo '<div id="serendipity_comment_beecaptcha" class="form_field">' . " \n " ;
echo '<label for="bee_captcha">' . $question . '</label>' . " \n " ;
echo '<input class="" type="text" id="bee_captcha" name="serendipity[beecaptcha]" value="" placeholder=""/>' . " \n " ;
echo " </div> \n " ;
2012-08-12 19:18:53 +02:00
2012-08-16 13:18:07 +02:00
if ( $this -> answerRetrievalMethod == 'smarty' || $this -> answerRetrievalMethod == 'smarty_enc' ) {
2012-08-12 19:18:53 +02:00
$answer = $this -> getCaptchaAnswer ();
2012-08-16 13:18:07 +02:00
if ( $this -> answerRetrievalMethod == 'smarty_enc' ) {
2012-08-16 00:44:49 +02:00
$scrambleKey = rand ();
$answer [ 'answer' ] = $this -> xorScramble ( $answer [ 'answer' ], $scrambleKey );
$serendipity [ 'smarty' ] -> assign ( 'beeCaptchaScrambleKey' , $scrambleKey );
}
2012-08-12 19:18:53 +02:00
$serendipity [ 'smarty' ] -> assign ( 'beeCaptchaAnswer' , $answer [ 'answer' ]);
}
2012-08-12 16:57:59 +02:00
}
}
/**
* If retrieval method != 'smarty' and the hidden Captcha is turned on ,
* print the needed JavaScript for filling out and hiding the Captcha to the buffer .
*/
2012-07-07 13:32:50 +02:00
function printJsExtras () {
2012-08-16 13:18:07 +02:00
if ( $this -> answerRetrievalMethod == 'smarty' || $this -> answerRetrievalMethod == 'smarty_enc' ) {
2012-08-11 22:02:16 +02:00
return ;
}
2012-07-07 13:32:50 +02:00
global $serendipity ;
2012-08-12 16:05:43 +02:00
if ( PLUGIN_EVENT_SPAMBLOCK_SWTCH_OFF != $this -> hiddenCaptchaHandle ) {
2012-08-16 00:44:49 +02:00
$path = $this -> path = $this -> get_config ( 'plugin_path' , $serendipity [ 'serendipityHTTPPath' ] . 'plugins/serendipity_event_spamblock_bee/' );
$answer = $this -> getCaptchaAnswer ();
$answer = $answer [ 'answer' ];
$jsProperties = array ( 'method' => $this -> answerRetrievalMethod );
2012-08-11 22:02:16 +02:00
2012-08-12 16:05:43 +02:00
if ( $this -> answerRetrievalMethod == 'json' ) {
2012-08-16 00:44:49 +02:00
$jsProperties [ 'url' ] = $serendipity [ 'baseURL' ] . 'index.php/plugin/spamblockbeecaptcha' ;
2012-08-16 13:18:07 +02:00
echo '<script>var spamBeeData = ' . json_encode ( $jsProperties ) . ';</script>' . " \n " ;
2012-08-11 22:02:16 +02:00
} else {
2012-08-16 13:18:07 +02:00
$scrambleKey = rand ();
$answer = rawurlencode ( $this -> xorScramble ( $answer , $scrambleKey ));
$jsProperties [ 'scrambleKey' ] = $scrambleKey ;
$jsProperties [ 'answer' ] = is_numeric ( $answer ) ? $answer : trim ( $answer );
2012-08-11 22:02:16 +02:00
}
2012-08-16 13:18:07 +02:00
unset ( $jsProperties [ 'pattern' ]);
2012-08-11 22:02:16 +02:00
2012-08-16 13:18:07 +02:00
if ( $this -> answerRetrievalMethod == 'default' ) {
2012-08-16 00:44:49 +02:00
// Do some weird obfuscation stuff to the JS code
$spamBeeVar = $this -> generateUniqueVarName ( array ());
// Shuffle array but preserve keys
$jsPropertiesKeys = array_keys ( $jsProperties );
shuffle ( $jsPropertiesKeys );
$jsProperties = array_merge ( array_flip ( $jsPropertiesKeys ) , $jsProperties );
echo '<script>var spamBeeData = function() { var ' . $spamBeeVar . ' = {};' ;
$jsVars = array ();
$existingKeys = array ( $spamBeeVar );
foreach ( $jsProperties as $property => $value ) {
$varName = $this -> generateUniqueVarName ( $existingKeys );
$jsVars [ $varName ] = $property ;
$existingKeys [] = $varName ;
// URL encode all characters to make values appear almost equal
$encVal = '' ;
$valLength = mb_strlen ( $value );
for ( $i = 0 ; $i < $valLength ; ++ $i ) {
$encVal .= '%' . bin2hex ( mb_substr ( $value , $i , 1 ));
}
echo 'var ' . $varName . " = unescape(' " . $encVal . " '); " ;
}
foreach ( $jsVars as $var => $value ) {
echo $spamBeeVar . " [' " . $value . " '] = " . $var . ';' ;
}
echo 'return ' . $spamBeeVar . '; }();' ;
2012-08-16 13:18:07 +02:00
echo " </script> \n " ;
2012-08-16 00:44:49 +02:00
}
2012-08-16 13:18:07 +02:00
2012-08-16 00:44:49 +02:00
echo '<script src="' . $path . 'serendipity_event_spamblock_bee.js"></script>' ;
2012-07-07 13:32:50 +02:00
}
}
2012-08-16 00:44:49 +02:00
/**
* Generate a unique random variable name . Used for generating obfuscated
* JS code . To make sure , the name is really unique , pass an array of all
* variable names already existing to this function .
* Returns an empty string if no unique variable name could be generated .
*
* @ param array $existingVarNames
* @ param int $length
* @ return string
*/
function generateUniqueVarName ( $existingVarNames , $length = 5 ) {
$varName = '' ;
$pool = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_' ;
$attempts = 0 ;
for ( $i = 0 ; $i < $length ; ++ $i ) {
2012-08-16 01:43:40 +02:00
$varName .= $pool [ rand ( 0 , strlen ( $pool ) - 1 )];
2012-08-16 00:44:49 +02:00
// If variable name has been generated, but is not unique, start over again
if ( $i == ( $length - 1 ) && in_array ( $varName , $existingVarNames )) {
// If we already have 10 attempts, give up and return empty string (should not happen)
if ( $attempts >= 9 ) {
return '' ;
}
$i = 0 ;
++ $attempts ;
}
}
return $varName ;
}
2012-08-12 16:57:59 +02:00
/**
* If retrieval method != 'json' and the hidden Captcha is enabled , print
* the needed CSS for hiding it to the output buffer .
*
* @ param array $eventData
* @ param array $addData
*/
2012-07-06 16:57:26 +02:00
function printCss ( & $eventData , & $addData ) {
2012-08-16 13:18:07 +02:00
if ( $this -> answerRetrievalMethod == 'smarty' || $this -> answerRetrievalMethod == 'smarty_enc' ) {
2012-08-12 16:57:59 +02:00
return ;
}
2012-07-06 16:57:26 +02:00
global $serendipity ;
2012-07-07 13:32:50 +02:00
// Hide and reveal classes by @yellowled used be the RSS chooser:
2012-08-12 16:05:43 +02:00
if ( PLUGIN_EVENT_SPAMBLOCK_SWTCH_OFF != $this -> hiddenCaptchaHandle ) {
2012-07-07 13:32:50 +02:00
?>
. spambeehidden {
border : 0 ;
clip : rect ( 0 0 0 0 );
height : 1 px ;
margin : - 1 px ;
overflow : hidden ;
padding : 0 ;
position : absolute ;
width : 1 px ;
}
< ? php
}
2012-07-06 17:39:08 +02:00
if ( ! ( strpos ( $eventData , '.comment_phone_input' ))) {
2012-07-06 16:57:26 +02:00
?>
2012-07-06 17:39:08 +02:00
. comment_phone_input {
2012-08-12 16:05:43 +02:00
max - width : 100 % ;
display : none ;
visibility : hidden ;
2012-07-06 18:59:00 +02:00
}
2012-07-06 16:57:26 +02:00
< ? php
}
}
function hashString ( $what ) {
$installation_secret = $this -> get_config ( 'installation_secret' );
if ( empty ( $installation_secret )) {
$installation_secret = md5 ( date ( 'l jS \of F Y h:i:s A' ));
$this -> set_config ( 'installation_secret' , $installation_secret );
}
return md5 ( $installation_secret . ':' . $what );
}
2012-08-12 16:57:59 +02:00
/**
* Generate the question for the Captcha and save the answer to the session .
*
* @ return string the question
*/
2012-08-11 22:02:16 +02:00
function generateCaptchaQuestion () {
2012-08-12 16:05:43 +02:00
if ( $this -> captchaQuestionType == 'custom' ) {
2012-08-11 22:02:16 +02:00
$question = $this -> selectRandomCustomCaptchaQuestion ();
if ( null === $question ) {
// no valid question could be selected, fall back to math questions
2012-08-12 16:13:36 +02:00
$this -> captchaQuestionType = 'math' ;
2012-08-11 22:02:16 +02:00
$this -> set_config ( 'question_type' , 'math' );
} else {
2012-08-12 16:05:43 +02:00
$this -> setCaptchaAnswer ( $question [ 'answer' ]);
2012-08-11 22:02:16 +02:00
return $question [ 'question' ];
}
}
2012-08-12 16:05:43 +02:00
if ( $this -> captchaQuestionType == 'math' ) {
$captchaData = $this -> generateCaptchaMathProblem ();
$this -> setCaptchaAnswer ( $captchaData [ 'answer' ]);
2012-08-11 22:02:16 +02:00
$method = PLUGIN_EVENT_SPAMBLOCK_BEE_CAPTCHA_PLUS ;
if ( $captchaData [ 'operator' ] == '-' ) {
$method = PLUGIN_EVENT_SPAMBLOCK_BEE_CAPTCHA_MINUS ;
}
return PLUGIN_EVENT_SPAMBLOCK_BEE_CAPTCHA_QUEST . ' ' .
$this -> generateNumberString ( $captchaData [ 'n1' ]) . " " .
$method . " " . $this -> generateNumberString ( $captchaData [ 'n2' ]) . '?' ;
}
}
2012-08-12 16:57:59 +02:00
/**
* Get correct answer for current Captcha question .
* This method returns an array with one or two indices :
* array (
* 'answer' => the answer to the question
* 'pattern' => the pattern for matching the answer ( only present
* when regExp matching is turned on )
* )
*
* @ return array
*/
2012-08-12 16:05:43 +02:00
function getCaptchaAnswer () {
if ( ! isset ( $this -> captchaAnswer [ 'answer' ]) && isset ( $_SESSION [ 'spamblockbee' ][ 'captcha' ])) {
$this -> captchaAnswer = $_SESSION [ 'spamblockbee' ][ 'captcha' ];
}
// If for some reason RegExp matching is on, but no pattern is present,
2012-08-12 20:43:47 +02:00
// turn off RegExp matching
2012-08-12 16:05:43 +02:00
if ( $this -> useRegularExpressions && ! isset ( $this -> captchaAnswer [ 'pattern' ])) {
$this -> useRegularExpressions = false ;
}
return $this -> captchaAnswer ;
}
2012-08-12 16:57:59 +02:00
/**
* Save the answer for the Captcha question .
* Call this method when you have changed the question .
* If RegExp matching is turned on , pass a string in the format / pattern /: answer .
*
* @ param string $answer
*/
2012-08-12 16:05:43 +02:00
function setCaptchaAnswer ( $answer ) {
$answer = array ( 'answer' => $answer );
// Split answer into array if RegExp matching is on
if ( $this -> captchaQuestionType == 'custom' && $this -> useRegularExpressions ) {
$delimiterIndex = strrpos ( $answer [ 'answer' ], ':' );
if ( $delimiterIndex !== false ) {
$answer = array (
'pattern' => substr ( $answer [ 'answer' ], 0 , $delimiterIndex ),
'answer' => substr ( $answer [ 'answer' ], $delimiterIndex + 1 )
);
} else {
// Answer contains either no pattern or no answer part, fall back to string matching
$this -> useRegularExpressions = false ;
}
}
$this -> captchaAnswer = $answer ;
$_SESSION [ 'spamblockbee' ][ 'captcha' ] = $this -> captchaAnswer ;
}
2012-08-12 16:57:59 +02:00
/**
* Generate a simple arithmetic problem for use in the Captcha .
* Returns an array containing the operator , the operands and the result .
*
* @ return array
*/
2012-08-11 22:02:16 +02:00
function generateCaptchaMathProblem () {
2012-07-07 13:32:50 +02:00
$result = array ();
$number1 = rand ( 0 , 9 );
$number2 = rand ( 0 , 9 );
if (( $number1 + $number2 ) > 10 ) {
// Substract them
2012-08-11 22:02:16 +02:00
$result [ 'operator' ] = '-' ;
2012-07-07 13:32:50 +02:00
if ( $number1 > $number2 ) {
$result [ 'n1' ] = $number1 ;
$result [ 'n2' ] = $number2 ;
2012-08-11 22:02:16 +02:00
$result [ 'answer' ] = $number1 - $number2 ;
2012-07-07 13:32:50 +02:00
}
else {
$result [ 'n2' ] = $number1 ;
$result [ 'n1' ] = $number2 ;
2012-08-11 22:02:16 +02:00
$result [ 'answer' ] = $number2 - $number1 ;
2012-07-07 13:32:50 +02:00
}
2012-08-11 22:02:16 +02:00
} else {
2012-07-07 13:32:50 +02:00
// Add them
2012-08-11 22:02:16 +02:00
$result [ 'operator' ] = '+' ;
2012-07-07 13:32:50 +02:00
$result [ 'n1' ] = $number1 ;
$result [ 'n2' ] = $number2 ;
2012-08-11 22:02:16 +02:00
$result [ 'answer' ] = $number1 + $number2 ;
2012-07-07 13:32:50 +02:00
}
2012-08-11 22:02:16 +02:00
2012-07-07 13:32:50 +02:00
return $result ;
}
2012-08-12 16:57:59 +02:00
/**
* Turn numbers between 0 and 10 into words .
*
* @ param int $number
* @ return string
*/
2012-07-07 13:32:50 +02:00
function generateNumberString ( $number ) {
//$number = (int)$number;
switch ( $number ) {
case 0 : return PLUGIN_EVENT_SPAMBLOCK_BEE_CAPTCHA_0 ;
case 1 : return PLUGIN_EVENT_SPAMBLOCK_BEE_CAPTCHA_1 ;
case 2 : return PLUGIN_EVENT_SPAMBLOCK_BEE_CAPTCHA_2 ;
case 3 : return PLUGIN_EVENT_SPAMBLOCK_BEE_CAPTCHA_3 ;
case 4 : return PLUGIN_EVENT_SPAMBLOCK_BEE_CAPTCHA_4 ;
case 5 : return PLUGIN_EVENT_SPAMBLOCK_BEE_CAPTCHA_5 ;
case 6 : return PLUGIN_EVENT_SPAMBLOCK_BEE_CAPTCHA_6 ;
case 7 : return PLUGIN_EVENT_SPAMBLOCK_BEE_CAPTCHA_7 ;
case 8 : return PLUGIN_EVENT_SPAMBLOCK_BEE_CAPTCHA_8 ;
case 9 : return PLUGIN_EVENT_SPAMBLOCK_BEE_CAPTCHA_9 ;
case 10 : return PLUGIN_EVENT_SPAMBLOCK_BEE_CAPTCHA_10 ;
default : return " ERROR " ;
}
}
2012-08-12 16:57:59 +02:00
/**
* Select a random question from the list of custom questions .
* Returns an array with to indices :
* array (
* 'question' => the selected question
* 'answer' => the answer for that question
* )
*
* @ return array
*/
2012-08-11 22:02:16 +02:00
function selectRandomCustomCaptchaQuestion () {
$questions = trim ( $this -> get_config ( 'questions' , '' ));
$answers = trim ( $this -> get_config ( 'answers' , '' ));
if ( empty ( $questions ) || empty ( $answers )) {
return null ;
}
$questions = preg_split ( '/(?:\r?\n|\r)/' , $questions );
$answers = preg_split ( '/(?:\r?\n|\r)/' , $answers );
// ignore questions without answer
if ( count ( $questions ) > count ( $answers )) {
array_splice ( $questions , count ( $answers ));
}
// if no questions left
if ( ! count ( $questions )) {
return null ;
}
$questionIndex = rand ( 0 , count ( $questions ) - 1 );
return array (
'question' => trim ( $questions [ $questionIndex ]),
'answer' => trim ( $answers [ $questionIndex ])
);
}
2012-08-16 00:44:49 +02:00
/**
* Scramble a UTF - 8 string with a simple XOR cipher in order
* to perform string obfuscation .
*
* @ param string $string
* @ param int $key
* @ return string
*/
function xorScramble ( $string , $key ) {
$scrambled = '' ;
$length = mb_strlen ( $string , 'UTF-8' );
for ( $i = 0 ; $i < $length ; ++ $i ) {
$chr = mb_substr ( $string , $i , 1 , 'UTF-8' );
$ord = $this -> ordUtf8 ( $chr );
$scrambled .= $this -> chrUtf8 ( $ord ^ $key );
}
return $scrambled ;
}
/**
* Multi - byte safe UTF - 8 version of chr ()
* Thanks to http :// pastebin . com / fmiSnNin
*
* @ param int $ord
* @ return string
*/
function chrUtf8 ( $ord )
{
return mb_convert_encoding ( pack ( 'n' , $ord ) , 'UTF-8' , 'UTF-16BE' );
}
/**
* Multi - byte safe UTF - 8 version of ord () .
* Thanks to http :// pastebin . com / fmiSnNin
* Returns - 1 on error .
*
* @ param string $chr
* @ return int
*/
function ordUtf8 ( $chr )
{
// Return value of ord() if only single-byte
if ( strlen ( $chr ) == 1 ) {
return ord ( $chr );
}
$codePoint = ord ( $chr [ 0 ]);
if ( $codePoint <= 0x7f ) {
return $codePoint ;
} else if ( $codePoint < 0xc2 ) {
return - 1 ;
} else if ( $codePoint <= 0xdf ) {
return ( $codePoint & 0x1f ) << 6 | ( ord ( $chr [ 1 ]) & 0x3f );
} else if ( $codePoint <= 0xef ) {
return ( $codePoint & 0x0f ) << 12 | ( ord ( $chr [ 1 ]) & 0x3f ) << 6 | ( ord ( $chr [ 2 ]) & 0x3f );
} else if ( $codePoint <= 0xf4 ) {
return ( $codePoint & 0x0f ) << 18 | ( ord ( $chr [ 1 ]) & 0x3f ) << 12 | ( ord ( $chr [ 2 ]) & 0x3f ) << 6 | ( ord ( $chr [ 3 ]) & 0x3f );
} else {
return - 1 ;
}
}
2012-08-12 16:57:59 +02:00
/**
* Log spam to file
* @ param string $message
*/
2012-07-06 16:57:26 +02:00
function log ( $message ){
if ( ! PLUGIN_EVENT_SPAMBLOCK_BEE_DEBUG ) return ;
2012-07-06 17:39:08 +02:00
$fp = fopen ( dirname ( __FILE__ ) . '/spambee.log' , 'a' );
2012-07-06 16:57:26 +02:00
fwrite ( $fp , date ( 'Y.m.d H:i:s' ) . " - " . $message . " \n " );
fflush ( $fp );
fclose ( $fp );
}
2012-08-12 16:57:59 +02:00
/**
* Log spam to database
* @ param string $id
* @ param string $switch
* @ param string $reason
* @ param string $addData
*/
2012-08-12 16:05:43 +02:00
function spamlog ( $id , $switch , $reason , $addData ) {
2012-07-06 16:57:26 +02:00
global $serendipity ;
2012-07-07 13:32:50 +02:00
2012-07-06 16:57:26 +02:00
$method = $this -> get_config ( 'spamlogtype' , 'none' );
2012-07-07 13:32:50 +02:00
$logfile = $this -> get_config ( 'spamlogfile' , $serendipity [ 'serendipityPath' ] . 'spamblock.log' );
2012-07-06 16:57:26 +02:00
switch ( $method ) {
case 'file' :
if ( empty ( $logfile )) {
return ;
}
2012-08-12 16:05:43 +02:00
if ( strpos ( $logfile , '%' ) !== false ) {
$logfile = strftime ( $logfile );
}
2012-07-06 16:57:26 +02:00
$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 " , ' ' , $addData [ 'name' ]),
str_replace ( " \n " , ' ' , $addData [ 'email' ]),
str_replace ( " \n " , ' ' , $addData [ 'url' ]),
str_replace ( " \n " , ' ' , $_SERVER [ 'HTTP_USER_AGENT' ]),
$_SERVER [ 'REMOTE_ADDR' ],
str_replace ( " \n " , ' ' , $addData [ 'comment' ])
));
fclose ( $fp );
break ;
case 'none' :
return ;
break ;
case 'db' :
default :
2012-07-07 13:32:50 +02:00
$reason = serendipity_db_escape_string ( $reason );
2012-07-06 16:57:26 +02:00
$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 ( $addData [ 'name' ]),
serendipity_db_escape_string ( $addData [ 'email' ]),
serendipity_db_escape_string ( $addData [ 'url' ]),
substr ( serendipity_db_escape_string ( $_SERVER [ 'HTTP_USER_AGENT' ]), 0 , 255 ),
serendipity_db_escape_string ( $_SERVER [ 'REMOTE_ADDR' ]),
substr ( serendipity_db_escape_string ( isset ( $_SESSION [ 'HTTP_REFERER' ]) ? $_SESSION [ 'HTTP_REFERER' ] : $_SERVER [ 'HTTP_REFERER' ]), 0 , 255 ),
serendipity_db_escape_string ( $addData [ 'comment' ])
);
serendipity_db_schema_import ( $q );
break ;
}
}
2012-08-16 23:35:02 +02:00
}