diff --git a/README.md b/README.md index 5e4b721..075f4fd 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ bitrix-antispam =============== -1C Bitrix anti-spam mod. 3.11.19 +1C Bitrix anti-spam mod. 3.12.0 Information page, http://cleantalk.org/bitrix-antispam-module-bez-captcha diff --git a/cleantalk.antispam/default_option.php b/cleantalk.antispam/default_option.php new file mode 100644 index 0000000..efaa679 --- /dev/null +++ b/cleantalk.antispam/default_option.php @@ -0,0 +1,22 @@ + 1, + 'form_new_user' => 1, + 'form_comment_blog' => 1, + 'form_comment_forum' => 1, + 'form_forum_private_messages' => 1, + 'form_comment_treelike' => 1, + 'form_send_example' => 1, + 'form_order' => 1, + 'web_form' => 1, + 'form_global_check' => 0, + 'form_global_check_without_email' => 0, + 'form_sfw' => 1, + 'site_exclusions' => '', + 'form_exclusions_url' => '', + 'form_exclusions_url__regexp' => 0, + 'form_exclusions_fields' => '', + 'form_exclusions_fields__regexp' => 0, + 'form_exclusions_webform' => '', + 'complete_deactivation' => 0, +); diff --git a/cleantalk.antispam/description.en b/cleantalk.antispam/description.en index 9bf9ace..25b4005 100644 --- a/cleantalk.antispam/description.en +++ b/cleantalk.antispam/description.en @@ -1,9 +1,23 @@ -Fix. Settings. API key fieldset moved to the top of the section. -Fix. Settings. Reset settings button implemented. -Fix. Settings. Init default setting on installation. -New. Settings. Complete deactivation option added. -New. Settings. Complete deactivation implemented. -New. Settings. Regexp for fields exclusions. -New. Settings. Saving exclusion regexp implemented. -Fix. Exclusion. Fields exclusions fixed. -New. Exclusion. Url exclusions by regexp. \ No newline at end of file + diff --git a/cleantalk.antispam/description.ru b/cleantalk.antispam/description.ru index 2904693..25b4005 100644 --- a/cleantalk.antispam/description.ru +++ b/cleantalk.antispam/description.ru @@ -1,5 +1,23 @@ -Настройки: Поле API KEY перемещено вверх страницы. -Настройки: Сброс настроек реализован. -Настройки: Реализованы значения настроек по умолчанию. -Новое: Полная деактивация реализована. -Настройки: Опция исключений по URL и имени поля формы теперь может сравнивать по регулярному выражению. \ No newline at end of file + diff --git a/cleantalk.antispam/include.php b/cleantalk.antispam/include.php index 376caf2..56c21c8 100644 --- a/cleantalk.antispam/include.php +++ b/cleantalk.antispam/include.php @@ -22,7 +22,7 @@ use Cleantalk\Common\Firewall\Modules\SFW; if ( ! defined( 'CLEANTALK_USER_AGENT' ) ) - define( 'CLEANTALK_USER_AGENT', 'bitrix-31119' ); + define( 'CLEANTALK_USER_AGENT', 'bitrix-3.12.0' ); define('APBCT_TBL_FIREWALL_DATA', 'cleantalk_sfw'); // Table with firewall data. define('APBCT_TBL_FIREWALL_LOG', 'cleantalk_sfw_logs'); // Table with firewall logs. @@ -52,7 +52,7 @@ static public function apbct_sfw_update($access_key = '') { if (empty($access_key)) { return false; } - } + } $firewall = new Firewall( $access_key, DB::getInstance(), @@ -61,7 +61,7 @@ static public function apbct_sfw_update($access_key = '') { $firewall->setSpecificHelper( new CleantalkHelper() ); $fw_updater = $firewall->getUpdater( APBCT_TBL_FIREWALL_DATA ); $fw_updater->update(); - + } static public function apbct_sfw_send_logs($access_key = '') { if( empty( $access_key ) ){ @@ -69,47 +69,47 @@ static public function apbct_sfw_send_logs($access_key = '') { if (empty($access_key)) { return false; } - } + } $firewall = new Firewall( $access_key, DB::getInstance(), APBCT_TBL_FIREWALL_LOG ); $firewall->setSpecificHelper( new CleantalkHelper() ); $result = $firewall->sendLogs(); return true; - } - + } + /** * Show message when spam is blocked * @param string message */ - + static function CleantalkDie($message){ - + if( isset( $_POST['feedback_type'] ) && $_POST['feedback_type'] == 'buyoneclick' ) { - - $result = Array( 'error' => true, 'msg' => 'js_kr_error_send' ); - print json_encode( $result ); - - // AJAX response + + $result = Array( 'error' => true, 'msg' => 'js_kr_error_send' ); + print json_encode( $result ); + + // AJAX response }elseif( isset( $_SERVER['HTTP_X_REQUESTED_WITH'] ) && strtolower( $_SERVER['HTTP_X_REQUESTED_WITH'] ) == 'xmlhttprequest'){ - - die(json_encode(array( - 'apbct' => array( - 'blocked' => true, - 'comment' => $message, - ), - 'error' => array( - 'msg' => $message, - ) - ))); - + + die(json_encode(array( + 'apbct' => array( + 'blocked' => true, + 'comment' => $message, + ), + 'error' => array( + 'msg' => $message, + ) + ))); + }else{ - + $error_tpl = file_get_contents( dirname( __FILE__ ) . "/error.html" ); print str_replace( '%ERROR_TEXT%', $message, $error_tpl ); - + } - + die(); } private static function apbct_run_cron() @@ -142,31 +142,17 @@ public static function OnPageStartHandler() { global $USER; - $cleantalk_site_exclusions = COption::GetOptionString('cleantalk.antispam', 'site_exclusions', ''); - - if (!empty($cleantalk_site_exclusions)) { - $context = \Bitrix\Main\Application::getInstance()->getContext(); - $siteId = $context->getSite(); - $cleantalk_site_exclusions = explode(',', $cleantalk_site_exclusions); - if (in_array($siteId, $cleantalk_site_exclusions)) { - return; - } + // Skip service request - iblock.vode component ajax loading + if ( + defined('PUBLIC_AJAX_MODE') && + $_POST['checkVote'] === 'Y' && + ( isset($_REQUEST['vote_id']) && is_string($_REQUEST['vote_id']) && ! empty($_REQUEST['vote_id']) ) + ) { + return; } - // Set exclusions to the class - $cleantalk_url_exclusions = COption::GetOptionString( 'cleantalk.antispam', 'form_exclusions_url', '' ); - if (!empty($cleantalk_url_exclusions)) { - $cleantalk_url_exclusions = explode(',', $cleantalk_url_exclusions); - foreach ($cleantalk_url_exclusions as $key => $exclusion) { - if ( - ( - COption::GetOptionInt( 'cleantalk.antispam', 'form_exclusions_url__regexp', 0 ) && - preg_match('@' . stripslashes($exclusion) . '@', $_SERVER['REQUEST_URI']) === 1 - ) || - stripos($_SERVER['REQUEST_URI'], $exclusion) !== false - ) { - return; - } - } + + if ( self::siteIsExclusion() || self::urlIsExclusion() ){ + return; } if (!is_object($USER)) $USER = new CUser; @@ -180,19 +166,19 @@ public static function OnPageStartHandler() $sfw_last_update = COption::GetOptionInt( 'cleantalk.antispam', 'sfw_last_update', 0); $sfw_last_send_log = COption::GetOptionInt( 'cleantalk.antispam', 'sfw_last_send_log', 0); $new_checked = time(); - + // Don't take any actions if module is disabled if( ! $ct_status ) return; - + // Remote calls if( RemoteCalls::check() ) { $rc = new RemoteCalls( $ct_key); $rc->perform(); } - + if( ! $USER->IsAdmin() ){ - + // Set cookies if( ! headers_sent() ) self::ct_cookie(); @@ -216,9 +202,9 @@ public static function OnPageStartHandler() $firewall->run(); } - + // Global check - if ($ct_status == 1 && $ct_global == 1) { + if ($ct_status == 1 && $ct_global == 1) { // Exclusions if( empty($_POST) || (isset($_POST['AUTH_FORM'], $_POST['TYPE'], $_POST['USER_LOGIN'])) || @@ -228,8 +214,8 @@ public static function OnPageStartHandler() (isset($_POST['action']) && $_POST['action'] == 'saveOrderAjax') || strpos($_SERVER['REQUEST_URI'],'/user-profile.php?update=Y')!==false || ( isset( $_SERVER['USER_AGENT'] ) && strpos( $_SERVER['USER_AGENT'], '.NET Framework' ) !== false ) || - ( isset( $_SERVER['USER_AGENT'] ) && strpos( $_SERVER['USER_AGENT'], 'Bitrix Telephony Controller' ) !== false ) || - (isset($_POST['comment_post_id'], $_POST['comment'], $_POST['blog_upload_cid'])) || + ( isset( $_SERVER['USER_AGENT'] ) && strpos( $_SERVER['USER_AGENT'], 'Bitrix Telephony Controller' ) !== false ) || + (isset($_POST['comment_post_id'], $_POST['comment'], $_POST['blog_upload_cid'])) || strpos($_SERVER['REQUEST_URI'], '/order/make') || (isset($_POST['NEW_PASSWORD'], $_POST['NEW_PASSWORD_CONFIRM']) && strpos($_SERVER['REQUEST_URI'], 'personal/profile/') !== false) || (isset($_POST['t'], $_POST['dl'], $_POST['dt']) && $_POST['t'] == 'pageview') || @@ -243,12 +229,12 @@ public static function OnPageStartHandler() $ct_webform= COption::GetOptionInt('cleantalk.antispam', 'web_form', 0); $webforms_id_checking = COption::GetOptionString( 'cleantalk.antispam', 'form_exclusions_webform', '' ); if ($ct_webform == 1 && $webforms_id_checking && !empty($webforms_id_checking) && isset($_POST['WEB_FORM_ID'])) { - $webforms_id_checking = explode(',', $webforms_id_checking); - if (in_array($_POST['WEB_FORM_ID'], $webforms_id_checking)) + $webforms_id_checking = explode(',', $webforms_id_checking); + if (in_array($_POST['WEB_FORM_ID'], $webforms_id_checking)) return; } - $form_data = apbct__filter_form_data($_POST); + $form_data = self::apbct__filter_form_data($_POST); $ct_temp_msg_data = CleantalkHelper::get_fields_any($form_data); // @todo Works via links need to be fixed // SLAM Easyform ajax integration @@ -259,9 +245,9 @@ public static function OnPageStartHandler() } $ct_temp_msg_data = CleantalkHelper::get_fields_any( $_POST['FIELDS'], '', array(), null, array( 'nick' => $nickname, 'first' => '', 'last' => '' ) ); } - + if ($ct_temp_msg_data === null) { - $form_data = apbct__filter_form_data($_GET); + $form_data = self::apbct__filter_form_data($_GET); $ct_temp_msg_data = CleantalkHelper::get_fields_any($form_data); } @@ -274,68 +260,68 @@ public static function OnPageStartHandler() $arUser["message"] = ($ct_temp_msg_data['message'] ? $ct_temp_msg_data['message'] : array()); if ($arUser['subject'] != '') - $arUser['message']['subject'] = $arUser['subject']; + $arUser['message']['subject'] = $arUser['subject']; foreach ($_POST as $key => $value) { - if (strpos(strtolower($key), 'smt') !== false) - $arUser['type'] = 'contact_form_bitrix_smt'; - if (strpos(strtolower($key), 'iblock_submit') !== false) - $arUser['type'] = 'contact_form_bitrix_iblock_ajax'; + if (strpos(strtolower($key), 'smt') !== false) + $arUser['type'] = 'contact_form_bitrix_smt'; + if (strpos(strtolower($key), 'iblock_submit') !== false) + $arUser['type'] = 'contact_form_bitrix_iblock_ajax'; } // Try to get compressed data from the _POST if( $arUser["sender_email"] == '' && $arUser['type'] === 'feedback_general_contact_form' && isset( $_POST['data'] ) && is_string( $_POST['data'] ) ) { parse_str( urldecode($_POST['data']),$second_chance); - $form_data = apbct__filter_form_data($second_chance); + $form_data = self::apbct__filter_form_data($second_chance); $ct_temp_msg_data = CleantalkHelper::get_fields_any($form_data); $arUser["sender_email"] = ($ct_temp_msg_data['email'] ? $ct_temp_msg_data['email'] : ''); } if(($arUser["sender_email"] != '' && $arUser['type'] == 'feedback_general_contact_form') || $ct_global_without_email == 1 || $arUser['type'] != 'feedback_general_contact_form') { - + $aResult = CleantalkAntispam::CheckAllBefore($arUser,FALSE); - + if( isset( $aResult ) && is_array( $aResult ) ){ - + if( $aResult['errno'] == 0 ){ - + if( $aResult['allow'] == 1 ){ - + //Not spammer - just return; return; - + }else{ if( $arUser['type'] == 'contact_form_bitrix_smt' ){ - + echo '
' . $aResult['ct_result_comment'] . '
'; die(); - + }elseif( $arUser['type'] == 'contact_form_bitrix_iblock_ajax' ){ - + echo json_encode( array( 'STATUS' => 'success', - 'MSG' => $aResult['ct_result_comment'], - 'CAPTCHA' => '' + 'MSG' => $aResult['ct_result_comment'], + 'CAPTCHA' => '' ) ); die(); - + }else{ - + CleantalkAntispam::CleantalkDie( $aResult['ct_result_comment'] ); return false; - + } } } } } - } + } }else{ if($ct_key!='' && $ct_key!='enter key') { $new_status=$show_review; if($new_checked-$last_checked>86400) { - + $result = CleantalkAPI::method__notice_paid_till($ct_key, preg_replace('/http[s]?:\/\//', '', $_SERVER['HTTP_HOST'], 1)); if(empty($result['error'])){ @@ -345,7 +331,7 @@ public static function OnPageStartHandler() 'MESSAGE' => GetMessage( 'CLEANTALK_TRIAL_NOTIFY' ), 'TAG' => 'trial_notify', 'MODULE_ID' => 'main', - 'ENABLE_CLOSE' => 'Y')); + 'ENABLE_CLOSE' => 'Y')); } else { CAdminNotify::DeleteByTag('trial_notify'); } @@ -354,7 +340,7 @@ public static function OnPageStartHandler() 'MESSAGE' => GetMessage( 'CLEANTALK_RENEW_NOTIFY' ), 'TAG' => 'renew_notify', 'MODULE_ID' => 'main', - 'ENABLE_CLOSE' => 'Y')); + 'ENABLE_CLOSE' => 'Y')); } else { CAdminNotify::DeleteByTag('renew_notify'); } @@ -374,32 +360,32 @@ public static function OnPageStartHandler() { $review_mess = "Like Anti-spam by CleanTalk? Help others learn about CleanTalk! Leave a review at the Bitrix.Marketplace"; } - CAdminNotify::Add(array( - 'MESSAGE' => $review_mess, - 'TAG' => 'review_notify', - 'MODULE_ID' => 'main', - 'ENABLE_CLOSE' => 'Y')); + CAdminNotify::Add(array( + 'MESSAGE' => $review_mess, + 'TAG' => 'review_notify', + 'MODULE_ID' => 'main', + 'ENABLE_CLOSE' => 'Y')); } } } - + COption::SetOptionInt( 'cleantalk.antispam', 'last_checked', $new_checked ); - } + } } - } + } } - + /** * *** Sale section *** */ - + /** * Checking Order forms for spam * @param &array Comment fields to check * @return null|boolean NULL when success or FALSE when spam detected */ - - function OnBeforeOrderAddHandler(&$arFields) + + static function OnBeforeOrderAddHandler(&$arFields) { global $APPLICATION, $USER; $ct_status = COption::GetOptionInt('cleantalk.antispam', 'status', 0); @@ -423,14 +409,14 @@ function OnBeforeOrderAddHandler(&$arFields) } } $message[] = $_POST['ORDER_DESCRIPTION']; - + $arUser = array(); $arUser["type"] = "order"; $arUser["sender_email"] = $sender_email; $arUser["sender_nickname"] = ''; $arUser["subject"] = ""; $arUser["message"] = $message; - + $aResult = CleantalkAntispam::CheckAllBefore($arUser,FALSE); if(isset($aResult) && is_array($aResult)) { @@ -450,53 +436,40 @@ function OnBeforeOrderAddHandler(&$arFields) } } } - + /** * *** Web forms section *** */ - - /** + + /** * Checking web forms * @param $WEB_FORM_ID, &$arFields, &$arrVALUES Comment fields to check * @return null|boolean NULL when success or FALSE when spam detected */ - - function OnBeforeResultAddHandler($WEB_FORM_ID, &$arFields, &$arrVALUES) + + static function OnBeforeResultAddHandler($WEB_FORM_ID, &$arFields, &$arrVALUES) { global $APPLICATION; - + + if ( self::urlIsExclusion() ){ + return; + } + $ct_status = COption::GetOptionInt('cleantalk.antispam', 'status', 0); $ct_webform= COption::GetOptionInt('cleantalk.antispam', 'web_form', 0); $webforms_id_checking = COption::GetOptionString( 'cleantalk.antispam', 'form_exclusions_webform', '' ); if ($webforms_id_checking && !empty($webforms_id_checking)) { - $webforms_id_checking = explode(',', $webforms_id_checking); - if (in_array($WEB_FORM_ID, $webforms_id_checking)) - return; - } - - // Set exclusions to the class - $cleantalk_url_exclusions = COption::GetOptionString( 'cleantalk.antispam', 'form_exclusions_url', '' ); - if (!empty($cleantalk_url_exclusions)) { - $cleantalk_url_exclusions = explode(',', $cleantalk_url_exclusions); - foreach ($cleantalk_url_exclusions as $key => $exclusion) { - if ( - ( - COption::GetOptionInt( 'cleantalk.antispam', 'form_exclusions_url__regexp', 0 ) && - preg_match('@' . stripslashes($exclusion) . '@', $_SERVER['REQUEST_URI']) === 1 - ) || - stripos($_SERVER['REQUEST_URI'], $exclusion) !== false - ) { - return; - } - } + $webforms_id_checking = explode(',', $webforms_id_checking); + if (in_array($WEB_FORM_ID, $webforms_id_checking)) + return; } if ($ct_status == 1 && $ct_webform == 1){ - + $sender_email = null; $message = array(); - + $skip_keys = array( 'WEB_FORM_ID', 'RESULT_ID', @@ -513,34 +486,34 @@ function OnBeforeResultAddHandler($WEB_FORM_ID, &$arFields, &$arrVALUES) $excluded_fields = explode(',', $fields_exclusions); $skip_keys = array_merge($skip_keys, $excluded_fields); } - + foreach ($arrVALUES as $key => $value){ - + // Skipping keys foreach($skip_keys as $skip){ if(strpos($key, $skip) !== false) continue 2; } - - if ($sender_email === null && preg_match("/^\S+@\S+\.\S+$/", $value)) + + if ($sender_email === null && is_string($value) && preg_match("/^\S+@\S+\.\S+$/", $value)) $sender_email = $value; else $message[] = $value; } - + $arUser = array(); $arUser["type"] = "webform"; $arUser["sender_email"] = $sender_email; $arUser["sender_nickname"] = ''; $arUser["subject"] = ""; $arUser["message"] = $message; - + $aResult = CleantalkAntispam::CheckAllBefore($arUser,FALSE); if(isset($aResult) && is_array($aResult)){ - + if($aResult['errno'] == 0){ - + if($aResult['allow'] == 1){ return; //Not spammer - just return; }else{ @@ -551,19 +524,19 @@ function OnBeforeResultAddHandler($WEB_FORM_ID, &$arFields, &$arrVALUES) } } } - + /** * *** TreeLike comments section *** */ - + /** * Checking treelike comment for spam * @param &array Comment fields to check * @return null|boolean NULL when success or FALSE when spam detected */ - function OnBeforePrmediaCommentAddHandler(&$arFields) { + static function OnBeforePrmediaCommentAddHandler(&$arFields) { global $APPLICATION, $USER; - + $ct_status = COption::GetOptionInt('cleantalk.antispam', 'status', 0); $ct_comment_treelike = COption::GetOptionInt('cleantalk.antispam', 'form_comment_treelike', 0); if ($ct_status == 1 && $ct_comment_treelike == 1) { @@ -616,7 +589,7 @@ function OnBeforePrmediaCommentAddHandler(&$arFields) { // Not spammer - just return; return; }else{ - + if (preg_match('//u', $aResult['ct_result_comment'])){ $err_str = preg_replace('/^[^\*]*?\*\*\*|\*\*\*[^\*]*?$/iu', '', $aResult['ct_result_comment']); $err_str = preg_replace('/<[^<>]*>/iu', '', $err_str); @@ -624,29 +597,29 @@ function OnBeforePrmediaCommentAddHandler(&$arFields) { $err_str = preg_replace('/^[^\*]*?\*\*\*|\*\*\*[^\*]*?$/i', '', $aResult['ct_result_comment']); $err_str = preg_replace('/<[^<>]*>/i', '', $err_str); } - + if($aResult['stop_queue'] == 1){ // Spammer and stop_queue - die CleantalkAntispam::CleantalkDie($err_str); }else{ // if($aResult['stop_words']){ - // $APPLICATION->ThrowException($err_str); - // return FALSE; + // $APPLICATION->ThrowException($err_str); + // return FALSE; // }else{ - CleantalkAntispam::CleantalkDie($err_str); + CleantalkAntispam::CleantalkDie($err_str); // } -/* if - // Spammer and NOT stop_queue - to manual approvement - // ACTIVATED = 0 - // doesn't work - TreeLike Comments uses - // deprecated ExecuteModuleEvent - // instead of ExecuteModuleEventEx - // $arFields are not passwd by ref - // (See source - $args[] = func_get_arg($i)) - // so I cannot change 'ACTIVATED' - $arFields['ACTIVATED'] = 0; - return; -//*/ + /* if + // Spammer and NOT stop_queue - to manual approvement + // ACTIVATED = 0 + // doesn't work - TreeLike Comments uses + // deprecated ExecuteModuleEvent + // instead of ExecuteModuleEventEx + // $arFields are not passwd by ref + // (See source - $args[] = func_get_arg($i)) + // so I cannot change 'ACTIVATED' + $arFields['ACTIVATED'] = 0; + return; + //*/ } } } @@ -657,13 +630,13 @@ function OnBeforePrmediaCommentAddHandler(&$arFields) { /** * *** Blog section *** */ - + /** * Checking blog comment for spam * @param &array Comment fields to check * @return null|boolean NULL when success or FALSE when spam detected */ - function OnBeforeCommentAddHandler(&$arFields) { + static function OnBeforeCommentAddHandler(&$arFields) { global $APPLICATION, $USER; $ct_status = COption::GetOptionInt('cleantalk.antispam', 'status', 0); @@ -703,19 +676,19 @@ function OnBeforeCommentAddHandler(&$arFields) { if(COption::GetOptionInt('cleantalk.antispam', 'form_send_example', 0) == 1){ $arPost = CBlogPost::GetByID($arFields['POST_ID']); if(is_array($arPost)){ - $aComment['example']['title'] = $arPost['TITLE']; - $aComment['example']['body'] = $arPost['DETAIL_TEXT']; - // Find last 10 approved comments - $db_res = CBlogComment::GetList( + $aComment['example']['title'] = $arPost['TITLE']; + $aComment['example']['body'] = $arPost['DETAIL_TEXT']; + // Find last 10 approved comments + $db_res = CBlogComment::GetList( array('DATE_CREATE' => 'DESC'), array('POST_ID'=> $arFields['POST_ID'], 'PUBLISH_STATUS' => BLOG_PUBLISH_STATUS_PUBLISH), false, array('nTopCount' => 10), array('POST_TEXT') - ); - while($ar_res = $db_res->Fetch()) + ); + while($ar_res = $db_res->Fetch()) $aComment['example']['comments'] .= $ar_res['TITLE'] . "\n\n" . $ar_res['POST_TEXT'] . "\n\n"; - $aComment['example']['comments'] = json_encode($aComment['example']['comments']); + $aComment['example']['comments'] = json_encode($aComment['example']['comments']); } } @@ -729,13 +702,13 @@ function OnBeforeCommentAddHandler(&$arFields) { }else{ if($aResult['stop_queue'] == 1){ // Spammer and stop_queue - return false and throw - if (preg_match('//u', $aResult['ct_result_comment'])){ + if (preg_match('//u', $aResult['ct_result_comment'])){ $err_str = preg_replace('/^[^\*]*?\*\*\*|\*\*\*[^\*]*?$/iu', '', $aResult['ct_result_comment']); $err_str = preg_replace('/<[^<>]*>/iu', '', $err_str); - }else{ + }else{ $err_str = preg_replace('/^[^\*]*?\*\*\*|\*\*\*[^\*]*?$/i', '', $aResult['ct_result_comment']); $err_str = preg_replace('/<[^<>]*>/i', '', $err_str); - } + } $APPLICATION->ThrowException($err_str); return FALSE; }else{ @@ -751,14 +724,14 @@ function OnBeforeCommentAddHandler(&$arFields) { // Status setting in OnCommentAddHandler still results in endless 'Loading' AJAX message :( //$GLOBALS['ct_after_CommentAdd_status'] = BLOG_PUBLISH_STATUS_READY; //return; - - if (preg_match('//u', $aResult['ct_result_comment'])){ + + if (preg_match('//u', $aResult['ct_result_comment'])){ $err_str = preg_replace('/^[^\*]*?\*\*\*|\*\*\*[^\*]*?$/iu', '', $aResult['ct_result_comment']); $err_str = preg_replace('/<[^<>]*>/iu', '', $err_str); - }else{ + }else{ $err_str = preg_replace('/^[^\*]*?\*\*\*|\*\*\*[^\*]*?$/i', '', $aResult['ct_result_comment']); $err_str = preg_replace('/<[^<>]*>/i', '', $err_str); - } + } $APPLICATION->ThrowException($err_str); return FALSE; } @@ -777,7 +750,7 @@ function OnBeforeCommentAddHandler(&$arFields) { * @param &array Comment fields to check * @return null|boolean NULL when success or FALSE when spam detected */ - function OnBeforeMessageAddHandler(&$arFields) { + static function OnBeforeMessageAddHandler(&$arFields) { // works global $APPLICATION, $USER; $ct_status = COption::GetOptionInt('cleantalk.antispam', 'status', 0); @@ -805,36 +778,36 @@ function OnBeforeMessageAddHandler(&$arFields) { $aComment['subject'] = ''; $aComment['message'] = isset($arFields['POST_MESSAGE']) ? array($arFields['POST_MESSAGE']) : array(); $aComment['example'] = array(); - - if(COption::GetOptionInt('cleantalk.antispam', 'form_send_example', 0) == 1){ - $arTopic = CForumTopic::GetByID($arFields['TOPIC_ID']); - if(is_array($arTopic)){ + + if(COption::GetOptionInt('cleantalk.antispam', 'form_send_example', 0) == 1){ + $arTopic = CForumTopic::GetByID($arFields['TOPIC_ID']); + if(is_array($arTopic)){ $aComment['example']['title'] = $arTopic['TITLE']; // Messages contains both topic bodies and comment bodies // First find topic body $db_res = CForumMessage::GetList( - array('ID'=>'ASC'), - array('TOPIC_ID'=>$arFields['TOPIC_ID'], 'NEW_TOPIC'=>'Y', 'APPROVED'=>'Y'), - FALSE, - 1 + array('ID'=>'ASC'), + array('TOPIC_ID'=>$arFields['TOPIC_ID'], 'NEW_TOPIC'=>'Y', 'APPROVED'=>'Y'), + FALSE, + 1 ); $ar_res = $db_res->Fetch(); if($ar_res) - $aComment['example']['body'] = $ar_res['POST_MESSAGE']; + $aComment['example']['body'] = $ar_res['POST_MESSAGE']; // Second find last 10 approved comment bodies $comments = array(); $db_res = CForumMessage::GetList( - array('POST_DATE'=>'DESC'), - array('TOPIC_ID'=>$arFields['TOPIC_ID'], 'NEW_TOPIC'=>'N', 'APPROVED'=>'Y'), - FALSE, - 10 + array('POST_DATE'=>'DESC'), + array('TOPIC_ID'=>$arFields['TOPIC_ID'], 'NEW_TOPIC'=>'N', 'APPROVED'=>'Y'), + FALSE, + 10 ); while($ar_res = $db_res->Fetch()) - $aComment['example']['comments'] .= $ar_res['POST_MESSAGE'] . "\n\n"; + $aComment['example']['comments'] .= $ar_res['POST_MESSAGE'] . "\n\n"; $aComment['example']['comments'] = json_encode($aComment['example']['comments']); - } + } } $aResult = self::CheckAllBefore($aComment, TRUE); @@ -872,7 +845,7 @@ function OnBeforeMessageAddHandler(&$arFields) { * @param int ID of added comment * @param array Comment fields */ - function OnAfterMessageAddHandler($id, $arFields) { + static function OnAfterMessageAddHandler($id, $arFields) { // works $ct_status = COption::GetOptionInt('cleantalk.antispam', 'status', 0); $ct_comment_forum = COption::GetOptionInt('cleantalk.antispam', 'form_comment_forum', 0); @@ -880,14 +853,14 @@ function OnAfterMessageAddHandler($id, $arFields) { self::CheckCommentAfter('forum', $id, GetMessage('CLEANTALK_MESSAGE') . ' ID=' . $id); } } - + /** * Sending admin's decision (show or hide comment) to CleanTalk server * @param int ID of added comment * @param string Type of action - must be 'SHOW' or 'HIDE' only * @param array Comment fields */ - function OnMessageModerateHandler( $id, $type, $arFields){ + static function OnMessageModerateHandler( $id, $type, $arFields){ // works $ct_status = COption::GetOptionInt('cleantalk.antispam', 'status', 0); $ct_comment_forum = COption::GetOptionInt('cleantalk.antispam', 'form_comment_forum', 0); @@ -907,7 +880,7 @@ function OnMessageModerateHandler( $id, $type, $arFields){ * @param int ID of added comment * @param array Comment fields */ - function OnBeforeMessageDeleteHandler($id, $arFields) { + static function OnBeforeMessageDeleteHandler($id, $arFields) { // works $ct_status = COption::GetOptionInt('cleantalk.antispam', 'status', 0); $ct_comment_forum = COption::GetOptionInt('cleantalk.antispam', 'form_comment_forum', 0); @@ -916,13 +889,13 @@ function OnBeforeMessageDeleteHandler($id, $arFields) { self::SendFeedback('forum', $id, 'N'); } } - + /** * Check forum private messages * @param array Comment fields */ - function onBeforePMSendHandler($arFields) { - + static function onBeforePMSendHandler($arFields) { + global $APPLICATION, $USER; $ct_status = COption::GetOptionInt('cleantalk.antispam', 'status', 0); $ct_forum_private_messages = COption::GetOptionInt('cleantalk.antispam', 'form_forum_private_messages', 0); @@ -937,9 +910,9 @@ function onBeforePMSendHandler($arFields) { $aComment['example'] = array(); if ($aComment['subject'] != '') - $aComment['message']['subject'] = $aComment['subject']; + $aComment['message']['subject'] = $aComment['subject']; $aResult = self::CheckAllBefore($aComment, TRUE); - + if(isset($aResult) && is_array($aResult)){ if($aResult['errno'] == 0){ if($aResult['allow'] == 1){ @@ -959,7 +932,7 @@ function onBeforePMSendHandler($arFields) { } } } - + /** * *** User registration section *** */ @@ -969,19 +942,19 @@ function onBeforePMSendHandler($arFields) { * @param &array New user fields to check * @return null|boolean NULL when success or FALSE when spammer/bot detected */ - function OnBeforeUserRegisterHandler(&$arFields) { + static function OnBeforeUserRegisterHandler(&$arFields) { global $APPLICATION; - + $ct_status = COption::GetOptionInt('cleantalk.antispam', 'status', 0); $ct_new_user = COption::GetOptionInt('cleantalk.antispam', 'form_new_user', 0); if ( isset( $_SERVER['USER_AGENT'] ) && strpos( $_SERVER['USER_AGENT'], 'Bitrix SQS Server' ) !== false ) { - return; + return; } if ($ct_status == 1 && $ct_new_user == 1) { $aUser = array(); $aUser['type'] = 'register'; $aUser['sender_email'] = isset($arFields['EMAIL']) ? $arFields['EMAIL'] : ''; - + if (isset($arFields['NAME']) && isset($arFields['LAST_NAME']) && !empty($arFields['NAME']) && !empty($arFields['LAST_NAME'])) { $aUser['sender_nickname'] = $arFields['NAME'] . ' ' . $arFields['LAST_NAME']; } elseif (isset($arFields['USER_NAME']) && isset($arFields['USER_LAST_NAME']) && !empty($arFields['USER_NAME']) && !empty($arFields['USER_LAST_NAME'])) { @@ -991,7 +964,7 @@ function OnBeforeUserRegisterHandler(&$arFields) { } else { $aUser['sender_nickname'] = ''; } - + if (empty($arFields['LOGIN'])) $form_errors[] = 'Логин должен быть не менее 3 символов'; @@ -1026,7 +999,7 @@ function OnBeforeUserRegisterHandler(&$arFields) { return false; } } - } + } } } @@ -1035,22 +1008,22 @@ function OnBeforeUserRegisterHandler(&$arFields) { /** * *** Common section *** */ - + /** * CleanTalk additions to logging types */ - function OnEventLogGetAuditTypesHandler(){ + static function OnEventLogGetAuditTypesHandler(){ return array( 'CLEANTALK_EVENT' => '[CLEANTALK_EVENT] ' . GetMessage('CLEANTALK_EVENT'), 'CLEANTALK_E_SERVER' => '[CLEANTALK_E_SERVER] ' . GetMessage('CLEANTALK_E_SERVER'), 'CLEANTALK_E_INTERNAL' => '[CLEANTALK_E_INTERNAL] ' . GetMessage('CLEANTALK_E_INTERNAL') ); } - + /** * *** Universal methods section - for using in other modules *** */ - + /** * Content modification - adding JavaScript code to final content * @@ -1058,7 +1031,7 @@ function OnEventLogGetAuditTypesHandler(){ */ public static function OnEndBufferContentHandler( &$content ) { global $USER, $APPLICATION; - + if( ! $USER->IsAdmin() && ! defined( "ADMIN_SECTION" ) && @@ -1076,24 +1049,18 @@ public static function OnEndBufferContentHandler( &$content ) { static function FormAddon() { if(!defined("ADMIN_SECTION") && COption::GetOptionInt( 'cleantalk.antispam', 'status', 0 ) == 1 ) - { - $cleantalk_site_exclusions = COption::GetOptionString('cleantalk.antispam', 'site_exclusions', ''); + { + if ( self::siteIsExclusion() || self::urlIsExclusion() ){ + return; + } - if (!empty($cleantalk_site_exclusions)) { - $context = \Bitrix\Main\Application::getInstance()->getContext(); - $siteId = $context->getSite(); - $cleantalk_site_exclusions = explode(',', $cleantalk_site_exclusions); - if (in_array($siteId, $cleantalk_site_exclusions)) { - return; - } - } - $field_name = 'ct_checkjs'; - $ct_check_def = '0'; - if (!isset($_COOKIE[$field_name])) setcookie($field_name, $ct_check_def, 0, '/'); - - $ct_check_values = self::SetCheckJSValues(); - - $js_template = ""; - return $js_template; - } - else return ''; + return $js_template; + } + else return ''; } /** @@ -1315,11 +1282,11 @@ static function CheckAllBefore(&$arEntity, $bSendEmail = FALSE, $form_errors = n $executed_check = false; if (class_exists('Bitrix\Main\Context')) { - $isAdminSection = \Bitrix\Main\Context::getCurrent()->getRequest()->isAdminSection(); + $isAdminSection = \Bitrix\Main\Context::getCurrent()->getRequest()->isAdminSection(); } else { $isAdminSection = (strpos($_SERVER['REQUEST_URI'], 'bitrix/admin') !== false) ? true : false; } - + if ($USER->IsAdmin() || $isAdminSection) return; @@ -1346,25 +1313,9 @@ static function CheckAllBefore(&$arEntity, $bSendEmail = FALSE, $form_errors = n if (isset($arEntity['sender_email']) && empty($arEntity['sender_email']) && COption::GetOptionInt('cleantalk.antispam', 'form_global_check_without_email', 0) != 1) { return; } - $cleantalk_site_exclusions = COption::GetOptionString('cleantalk.antispam', 'site_exclusions', ''); - - if (!empty($cleantalk_site_exclusions)) { - $context = \Bitrix\Main\Application::getInstance()->getContext(); - $siteId = $context->getSite(); - - $cleantalk_site_exclusions = explode(',', $cleantalk_site_exclusions); - if (in_array($siteId, $cleantalk_site_exclusions)) { - return; - } - } - $url_exclusion = COption::GetOptionString( 'cleantalk.antispam', 'form_exclusions_url', '' ); - if (!empty($url_exclusion)) - { - $url_exclusion = explode(',', $url_exclusion); - foreach ($url_exclusion as $key=>$value) - if (strpos($_SERVER['REQUEST_URI'],$value) !== false) - return; + if ( self::siteIsExclusion() || self::urlIsExclusion() ){ + return; } $ct_key = COption::GetOptionString('cleantalk.antispam', 'key', ''); @@ -1376,7 +1327,7 @@ static function CheckAllBefore(&$arEntity, $bSendEmail = FALSE, $form_errors = n $checkjs = 1; else $checkjs = 0; - + $pointer_data = (isset($_COOKIE['ct_pointer_data']) ? json_decode($_COOKIE['ct_pointer_data']) : ''); $js_timezone = (isset($_COOKIE['ct_timezone']) ? $_COOKIE['ct_timezone'] : 'none'); $first_key_timestamp = (isset($_COOKIE['ct_fkp_timestamp']) ? $_COOKIE['ct_fkp_timestamp'] : 0); @@ -1445,17 +1396,17 @@ static function CheckAllBefore(&$arEntity, $bSendEmail = FALSE, $form_errors = n $ct->data_codepage = $logicalEncoding == 'utf-8' ? NULL : $logicalEncoding; $request_params = array( - 'auth_key' => $ct_key, - 'sender_email' => isset($arEntity['sender_email']) ? $arEntity['sender_email'] : '', - 'sender_nickname' => isset($arEntity['sender_nickname']) ? $arEntity['sender_nickname'] : '', - 'sender_ip' => CleantalkHelper::ip__get(array('real'), false), - 'x_forwarded_for' => CleantalkHelper::ip__get(array('x_forwarded_for'), false), - 'x_real_ip' => CleantalkHelper::ip__get(array('x_real_ip'), false), - 'agent' => CLEANTALK_USER_AGENT, - 'response_lang' => 'ru', - 'js_on' => $checkjs, - 'sender_info' => $sender_info, - 'submit_time' => self::ct_cookies_test() == 1 ? time() - (int)$_COOKIE['ct_timestamp'] : null, + 'auth_key' => $ct_key, + 'sender_email' => isset($arEntity['sender_email']) ? $arEntity['sender_email'] : '', + 'sender_nickname' => isset($arEntity['sender_nickname']) ? $arEntity['sender_nickname'] : '', + 'sender_ip' => CleantalkHelper::ip__get(array('real'), false), + 'x_forwarded_for' => CleantalkHelper::ip__get(array('x_forwarded_for'), false), + 'x_real_ip' => CleantalkHelper::ip__get(array('x_real_ip'), false), + 'agent' => CLEANTALK_USER_AGENT, + 'response_lang' => 'ru', + 'js_on' => $checkjs, + 'sender_info' => $sender_info, + 'submit_time' => self::ct_cookies_test() == 1 ? time() - (int)$_COOKIE['ct_timestamp'] : null, ); switch ($type) { @@ -1475,8 +1426,8 @@ static function CheckAllBefore(&$arEntity, $bSendEmail = FALSE, $form_errors = n $ct_result = $ct->isAllowMessage($ct_request); break; - - case 'order': + + case 'order': $timelabels_key = 'mail_error_comment'; if (is_array($arEntity['message'])) { $arEntity['message'] = json_encode($arEntity['message']); @@ -1486,15 +1437,15 @@ static function CheckAllBefore(&$arEntity, $bSendEmail = FALSE, $form_errors = n $ct_request = new CleantalkRequest($request_params); $ct_result = $ct->isAllowMessage($ct_request); break; - + case 'feedback_general_contact_form': - + $timelabels_key = 'mail_error_comment'; if (is_array($arEntity['message'])) { $arEntity['message'] = json_encode($arEntity['message']); } $request_params['message'] = $arEntity['message']; - + $request_params['post_info']['comment_type'] = 'feedback_general_contact_form'; $ct_request = new CleantalkRequest($request_params); @@ -1503,7 +1454,7 @@ static function CheckAllBefore(&$arEntity, $bSendEmail = FALSE, $form_errors = n break; case strpos($type, 'contact_form_bitrix') !== false: - + $timelabels_key = 'mail_error_comment'; if (is_array($arEntity['message'])) { $arEntity['message'] = json_encode($arEntity['message']); @@ -1514,9 +1465,9 @@ static function CheckAllBefore(&$arEntity, $bSendEmail = FALSE, $form_errors = n $ct_request = new CleantalkRequest($request_params); $ct_result = $ct->isAllowMessage($ct_request); break; - + case 'webform': - + $timelabels_key = 'mail_error_comment'; if (is_array($arEntity['message'])) { $arEntity['message'] = json_encode($arEntity['message']); @@ -1527,16 +1478,16 @@ static function CheckAllBefore(&$arEntity, $bSendEmail = FALSE, $form_errors = n $ct_request = new CleantalkRequest($request_params); $ct_result = $ct->isAllowMessage($ct_request); break; - + case 'register': - + $timelabels_key = 'mail_error_reg'; $request_params['tz'] = isset($arEntity['user_timezone']) ? $arEntity['user_timezone'] : NULL; $ct_request = new CleantalkRequest($request_params); $ct_result = $ct->isAllowUser($ct_request); break; - + case 'private_message': $timelabels_key = 'mail_error_comment'; @@ -1564,28 +1515,28 @@ static function CheckAllBefore(&$arEntity, $bSendEmail = FALSE, $form_errors = n $ret_val['errno'] = 1; // Just inform admin. $err_title = 'CleanTalk module error'; - + if(isset($ct_result->inactive) && intval($ct_result->inactive) == 1) COption::SetOptionInt( 'cleantalk.antispam', 'key_is_ok', 0); - + if(!empty($ct_result->errstr)){ - + if (preg_match('//u', $ct_result->errstr)) $err_str = preg_replace('/^[^\*]*?\*\*\*|\*\*\*[^\*]*?$/iu', '', $ct_result->errstr); else $err_str = preg_replace('/^[^\*]*?\*\*\*|\*\*\*[^\*]*?$/i', '', $ct_result->errstr); - + }else{ - + if (preg_match('//u', $ct_result->comment)) $err_str = preg_replace('/^[^\*]*?\*\*\*|\*\*\*[^\*]*?$/iu', '', $ct_result->comment); else $err_str = preg_replace('/^[^\*]*?\*\*\*|\*\*\*[^\*]*?$/i', '', $ct_result->comment); - + } $ret_val['errstr'] = $err_str; - + if(!empty($ct_result->errstr)){ if($request_params['js_on'] == 1){ $ct_result->allow = 0; @@ -1593,7 +1544,7 @@ static function CheckAllBefore(&$arEntity, $bSendEmail = FALSE, $form_errors = n }else $ct_result->allow = 1; } - + CEventLog::Add(array( 'SEVERITY' => 'SECURITY', 'AUDIT_TYPE_ID' => 'CLEANTALK_E_SERVER', @@ -1651,7 +1602,7 @@ static function CheckAllBefore(&$arEntity, $bSendEmail = FALSE, $form_errors = n $ret_val['stop_queue'] = 1; } } - return $ret_val; + return $ret_val; } return false; @@ -1660,7 +1611,7 @@ static function CheckAllBefore(&$arEntity, $bSendEmail = FALSE, $form_errors = n /** * Addon to CheckAllBefore method after comments/messages checking * It fills special CleanTalk tables according to CleanTalk result - * for better spam accounting + * for better spam accounting * and logs CleanTalk events * Use it in your modules * You must call it from OnAfter* events in comment/messages checking @@ -1711,22 +1662,22 @@ static function CheckCommentAfter($module, $cid, $log_event = '') { */ private static function ct_visibile_fields__process($visible_fields) { if(strpos($visible_fields, 'wpforms') !== false){ - $visible_fields = preg_replace( - array('/\[/', '/\]/'), - '', - str_replace( - '][', - '_', - str_replace( - 'wpforms[fields]', - '', - $visible_fields - ) - ) - ); - } - - return $visible_fields; + $visible_fields = preg_replace( + array('/\[/', '/\]/'), + '', + str_replace( + '][', + '_', + str_replace( + 'wpforms[fields]', + '', + $visible_fields + ) + ) + ); + } + + return $visible_fields; } /** * Sending of manual moderation result to CleanTalk server @@ -1758,17 +1709,17 @@ static function SendFeedback($module, $id, $feedback) { $ct->server_ttl = $ct_ws['server_ttl']; $ct->server_changed = $ct_ws['server_changed']; $request_params = array ( - 'auth_key' => $ct_key, - 'agent' => CLEANTALK_USER_AGENT, - 'sender_ip' => CleantalkHelper::ip__get(array('real'), false), - 'feedback' => $request_id . ':' . ($feedback == 'Y' ? '1' : '0'), + 'auth_key' => $ct_key, + 'agent' => CLEANTALK_USER_AGENT, + 'sender_ip' => CleantalkHelper::ip__get(array('real'), false), + 'feedback' => $request_id . ':' . ($feedback == 'Y' ? '1' : '0'), ); $ct_request = new CleantalkRequest($request_params); $ct->sendFeedback($ct_request); } } - + /** * Gets CleanTalk resume for spam detection by id * Use it in your modules/templates, see example @@ -1786,7 +1737,7 @@ static function GetCleanTalkResume($module, $id) { $ret_val = $DB->Query('SELECT ct_request_id, ct_result_comment FROM cleantalk_cids WHERE module=\''. $module .'\' AND cid=' . $id)->Fetch(); return $ret_val; } - + /** * *** Inner methods section *** */ @@ -1815,7 +1766,7 @@ private static function GetWorkServer() { /** * CleanTalk inner function - check for exceptions. - */ + */ private static function ExceptionList($value = null) { if ($value && is_array($value)) @@ -1823,7 +1774,7 @@ private static function ExceptionList($value = null) if (isset($value['sender_email'])) { if (preg_match('^user-\d+@shop\.kalyan-hut\.ru^', $value['sender_email'])) - return true; + return true; } } @@ -1868,41 +1819,41 @@ private static function SetWorkServer($work_url = 'http://moderate.cleantalk.org */ private static function SetCheckJSValues() { global $DB; - $current_time_range = date('H'); // time range key is current hour + $current_time_range = date('H'); // time range key is current hour - $flag_update = FALSE; + $flag_update = FALSE; $db_result = $DB->Query('SELECT time_range,js_values FROM cleantalk_checkjs LIMIT 1')->Fetch(); if($db_result !== FALSE){ - $db_time_range = $db_result['time_range']; - $db_js_values = array_slice(explode(' ', $db_result['js_values'], self::KEYS_NUM+1), 0, self::KEYS_NUM); - if($db_time_range == $current_time_range){ - return $db_js_values; + $db_time_range = $db_result['time_range']; + $db_js_values = array_slice(explode(' ', $db_result['js_values'], self::KEYS_NUM+1), 0, self::KEYS_NUM); + if($db_time_range == $current_time_range){ + return $db_js_values; + }else{ + $flag_update = TRUE; + } }else{ - $flag_update = TRUE; + $db_js_values = array(); } - }else{ - $db_js_values = array(); - } $arFields = array( 'time_range' => $current_time_range, 'js_values' => implode(' ', array_merge( array(md5(date(DATE_RSS).'+'.(string)rand())), array_slice($db_js_values,0,self::KEYS_NUM-1) )) ); - if($flag_update){ + if($flag_update){ $strUpdate = $DB->PrepareUpdate( 'cleantalk_checkjs', $arFields ); $strSql = 'UPDATE cleantalk_checkjs SET '.$strUpdate . " WHERE time_range='" . $DB->ForSql($db_time_range)."'"; - }else{ + }else{ $arInsert = $DB->PrepareInsert( 'cleantalk_checkjs', $arFields ); $strSql = 'INSERT INTO cleantalk_checkjs('.$arInsert[0].') VALUES ('.$arInsert[1].')'; - } + } $res = $DB->Query($strSql, TRUE); - return self::GetCheckJSValues(); + return self::GetCheckJSValues(); } /** * CleanTalk inner function - gets current JavaScript checking values. @@ -1922,7 +1873,7 @@ private static function GetCheckJSValues() { * Sets test cookie with all other cookies */ private static function ct_cookie(){ - + // Cookie names to validate $cookie_test_value = array( 'cookies_names' => array(), @@ -1940,27 +1891,27 @@ private static function ct_cookie(){ setcookie('ct_prev_referer', $_SERVER['HTTP_REFERER'], 0, '/'); $cookie_test_value['cookies_names'][] = 'ct_prev_referer'; $cookie_test_value['check_value'] .= $_SERVER['HTTP_REFERER']; - } + } // Cookies test $cookie_test_value['check_value'] = md5($cookie_test_value['check_value']); setcookie('ct_cookies_test', json_encode($cookie_test_value), 0, '/'); - } + } /** - * Cookies test for sender + * Cookies test for sender * Also checks for valid timestamp in $_COOKIE['apbct_timestamp'] and other apbct_ COOKIES * @return null|0|1; */ private static function ct_cookies_test() - { + { if(isset($_COOKIE['ct_cookies_test'])){ - + $cookie_test = json_decode(stripslashes($_COOKIE['ct_cookies_test']), true); - + $check_srting = COption::GetOptionString('cleantalk.antispam', 'key', ''); foreach($cookie_test['cookies_names'] as $cookie_name){ $check_srting .= isset($_COOKIE[$cookie_name]) ? $_COOKIE[$cookie_name] : ''; } unset($cokie_name); - + if($cookie_test['check_value'] == md5($check_srting)){ return 1; }else{ @@ -1970,93 +1921,130 @@ private static function ct_cookies_test() return null; } } -} -function apbct__filter_form_data($form_data) -{ - // It is a service field. Need to be deleted before the processing. - if ( isset($form_data['apbct_visible_fields']) ) { - unset($form_data['apbct_visible_fields']); - } - $exclusions = COption::GetOptionString( 'cleantalk.antispam', 'form_exclusions_fields', '' ); + private static function apbct__filter_form_data($form_data) + { + // It is a service field. Need to be deleted before the processing. + if ( isset($form_data['apbct_visible_fields']) ) { + unset($form_data['apbct_visible_fields']); + } + + $exclusions = COption::GetOptionString( 'cleantalk.antispam', 'form_exclusions_fields', '' ); - if ( $exclusions ) { + if ( $exclusions ) { - $excluded_fields = explode(',', $exclusions); + $excluded_fields = explode(',', $exclusions); - // regular expression exception - if (COption::GetOptionInt( 'cleantalk.antispam', 'form_exclusions_fields__regexp', 0 )) { + // regular expression exception + if (COption::GetOptionInt( 'cleantalk.antispam', 'form_exclusions_fields__regexp', 0 )) { - foreach (array_keys($form_data) as $key) { - foreach ($excluded_fields as $exclusion_regexp) { - if (preg_match('/' . $exclusion_regexp . '/', $key) === 1) { - unset($form_data[$key]); + foreach (array_keys($form_data) as $key) { + foreach ($excluded_fields as $exclusion_regexp) { + if (preg_match('/' . $exclusion_regexp . '/', $key) === 1) { + unset($form_data[$key]); + } } } - } - return $form_data; - } + return $form_data; + } - foreach ($excluded_fields as $excluded_field) { - preg_match_all('/\[(\S*?)\]/', $excluded_field, $matches); + foreach ($excluded_fields as $excluded_field) { + preg_match_all('/\[(\S*?)\]/', $excluded_field, $matches); - if (!empty($matches[1])) { - $excluded_matches = $matches[1]; - $first_el = strstr($excluded_field, '[', true); - array_unshift($excluded_matches, $first_el); - foreach ($excluded_matches as $k => $v) { - if ($v === '') { - unset($excluded_matches[$k]); + if (!empty($matches[1])) { + $excluded_matches = $matches[1]; + $first_el = strstr($excluded_field, '[', true); + array_unshift($excluded_matches, $first_el); + foreach ($excluded_matches as $k => $v) { + if ($v === '') { + unset($excluded_matches[$k]); + } } - } - $form_data = apbct__filter_array_recursive($form_data, $excluded_matches); - } else { - $form_data = apbct__filter_array_recursive($form_data, array($excluded_field)); + $form_data = self::apbct__filter_array_recursive($form_data, $excluded_matches); + } else { + $form_data = self::apbct__filter_array_recursive($form_data, array($excluded_field)); + } } } - } - return $form_data; -} - -/** - * Filtering array to exclude another array - * Example: delete fields from $_POST - * - * @param $array - * @param array $excluded_matches - * @param int $level - * - * @return array|mixed - */ -function apbct__filter_array_recursive(&$array, $excluded_matches, $level = 0) -{ - if (! is_array($array) || empty($array)) { - return $array; + return $form_data; } - foreach ($array as $key => $value) { - if ((string) $key !== (string) $excluded_matches[$level]) { - continue; + /** + * Filtering array to exclude another array + * Example: delete fields from $_POST + * + * @param $array + * @param array $excluded_matches + * @param int $level + * + * @return array|mixed + */ + private static function apbct__filter_array_recursive(&$array, $excluded_matches, $level = 0) + { + if (! is_array($array) || empty($array)) { + return $array; } - if (is_array($value)) { - $level++; + foreach ($array as $key => $value) { + if ((string) $key !== (string) $excluded_matches[$level]) { + continue; + } + + if (is_array($value)) { + $level++; + + if ($level === count($excluded_matches)) { + unset($array[$key]); + return $array; + } - if ($level === count($excluded_matches)) { + $array[$key] = self::apbct__filter_array_recursive($value, $excluded_matches, $level); + } else { unset($array[$key]); return $array; } + } - $array[$key] = apbct__filter_array_recursive($value, $excluded_matches, $level); - } else { - unset($array[$key]); - return $array; + return $array; + } + + private static function siteIsExclusion(){ + $cleantalk_site_exclusions = COption::GetOptionString('cleantalk.antispam', 'site_exclusions', ''); + if (!empty($cleantalk_site_exclusions)) { + $context = \Bitrix\Main\Application::getInstance()->getContext(); + $siteId = $context->getSite(); + + $cleantalk_site_exclusions = explode(',', $cleantalk_site_exclusions); + if (in_array($siteId, $cleantalk_site_exclusions)) { + return true; + } } + return false; } - return $array; + private static function urlIsExclusion(){ + $url_exclusion = COption::GetOptionString( 'cleantalk.antispam', 'form_exclusions_url', '' ); + if (!empty($url_exclusion)) + { + $url_exclusion = explode(',', $url_exclusion); + foreach ($url_exclusion as $key=>$value){ + + if ( + stripos($_SERVER['REQUEST_URI'], $value) !== false + || + (//regexp check + COption::GetOptionInt( 'cleantalk.antispam', 'form_exclusions_url__regexp', 0 ) && + preg_match('@' . stripslashes($value) . '@', $_SERVER['REQUEST_URI']) === 1 + ) + ) { + return true; + } + } + } + return false; + } } diff --git a/cleantalk.antispam/install/index.php b/cleantalk.antispam/install/index.php index 7dbaecd..8564307 100644 --- a/cleantalk.antispam/install/index.php +++ b/cleantalk.antispam/install/index.php @@ -6,6 +6,7 @@ require_once(dirname(__FILE__) . '/../lib/autoload.php'); use Cleantalk\Common\API as CleantalkAPI; +use Bitrix\Main\Config\Option; /** * Installer for CleanTalk module @@ -104,10 +105,31 @@ function DoInstall() { RegisterModuleDependences('form', 'OnBeforeResultAdd', 'cleantalk.antispam', 'CleantalkAntispam', 'OnBeforeResultAddHandler'); } } - - //Checking API key if already set + + //init default options if no options set + $is_empty_options = true; + $set_of_default_keys = array_keys(Option::getDefaults('cleantalk.antispam')); + $current_options = Option::getForModule('cleantalk.antispam'); + + if ( ! empty ($current_options) ) { + foreach ($current_options as $key) { + if (in_array($key, $set_of_default_keys, false)) { + $is_empty_options = false; + break; + } + } + } + + if ( $is_empty_options ) { + $default_options = Option::getDefaults('cleantalk.antispam'); + foreach ($default_options as $option => $value) { + Option::set('cleantalk.antispam', $option, $value); + } + } + + //Checking API key if already set $api_key = COption::GetOptionString( 'cleantalk.antispam', 'key', ''); - $form_sfw = COption::GetOptionInt( 'cleantalk.antispam', 'form_sfw', 0 ); + $form_sfw = COption::GetOptionInt( 'cleantalk.antispam', 'form_sfw', 0 ); //TODO For what is it? $result = CleantalkAPI::method__notice_paid_till($api_key, preg_replace('/http[s]?:\/\//', '', $_SERVER['HTTP_HOST'], 1)); COption::SetOptionInt( 'cleantalk.antispam', 'key_is_ok', isset($result['valid']) && $result['valid'] == '1' ? 1 : 0); @@ -125,6 +147,11 @@ function DoInstall() { function DoUninstall() { global $DOCUMENT_ROOT, $APPLICATION; + //Complete deactivation removes all the options + if ( Option::get( 'cleantalk.antispam', 'complete_deactivation') == 1 ) { + $ct_option_names = array_keys(Option::getForModule('cleantalk.antispam')); + Option::delete('cleantalk.antispam',$ct_option_names); + } if (IsModuleInstalled('blog')){ UnRegisterModuleDependences('blog', 'OnBeforeCommentAdd', 'cleantalk.antispam', 'CleantalkAntispam', 'OnBeforeCommentAddHandler'); @@ -158,9 +185,6 @@ function DoUninstall() { $GLOBALS["errors"] = $this->errors; $GLOBALS["messages"] = $this->messages; $APPLICATION->IncludeAdminFile(GetMessage('CLEANTALK_UNINSTALL_TITLE'), $DOCUMENT_ROOT.'/bitrix/modules/cleantalk.antispam/install/unstep.php'); - if ( COption::GetOptionInt( 'cleantalk.antispam', 'complete_deactivation', 0 ) == 1 ) { - COption::RemoveOption('cleantalk.antispam'); - } } function InstallFiles() { diff --git a/cleantalk.antispam/install/version.php b/cleantalk.antispam/install/version.php index f4ba4b7..d6402de 100644 --- a/cleantalk.antispam/install/version.php +++ b/cleantalk.antispam/install/version.php @@ -1,5 +1,5 @@ "3.11.19", - "VERSION_DATE" => "2022-02-08 10:00:00" + "VERSION" => "3.12.0", + "VERSION_DATE" => "2023-19-10 10:00:00" ); diff --git a/cleantalk.antispam/lang/en/options.php b/cleantalk.antispam/lang/en/options.php index d2a998d..b5591f1 100644 --- a/cleantalk.antispam/lang/en/options.php +++ b/cleantalk.antispam/lang/en/options.php @@ -29,6 +29,7 @@ $MESS['CLEANTALK_EXCLUSIONS'] = 'Exclusions'; $MESS['CLEANTALK_EXCLUSIONS_URL'] = 'URL exclusions'; $MESS['CLEANTALK_EXCLUSIONS_URL_DESCRIPTION'] = 'Exclude urls from spam check. List them separated by commas.'; +$MESS['CLEANTALK_EXCLUSIONS_URLS_REGEXP_DESCRIPTION'] = 'Use Regular Expression in URLs Exclusions'; $MESS['CLEANTALK_EXCLUSIONS_FIELDS'] = 'Fields exclusions'; $MESS['CLEANTALK_EXCLUSIONS_FIELDS_DESCRIPTION'] = 'Exclude fields from spam check. List them separated by commas. Works on forms except for registration and comment forms.'; $MESS['CLEANTALK_EXCLUSIONS_FIELDS_REGEXP_DESCRIPTION'] = 'Use Regular Expression in Field Exclusions'; @@ -40,4 +41,7 @@ $MESS['CLEANTALK_RENEW_NOTIFY']= "Please, renew your anti-spam license for Anti-spam by CleanTalk!"; $MESS['CLEANTALK_MISC'] = 'Miscellaneous'; $MESS['CLEANTALK_LABEL_COMPLETE_DEACTIVATION'] = 'Complete deactivation'; -$MESS['CLEANTALK_WRONG_REGEXP_NOTIFY'] = 'Field Exclusions is not a valid regular expression.'; \ No newline at end of file +$MESS['CLEANTALK_WRONG_REGEXP_NOTIFY'] = 'Field Exclusions is not a valid regular expression.'; +$MESS['CLEANTALK_WRONG_DEFAULT_SETTINGS'] = 'Can not load default options. Module name is incorrect.'; +$MESS['CLEANTALK_WRONG_CURRENT_SETTINGS'] = 'Can not load current options.'; +$MESS['CLEANTALK_RESET_OPTIONS_FAILED'] = 'Can not reset options to defaults.'; \ No newline at end of file diff --git a/cleantalk.antispam/lang/ru/options.php b/cleantalk.antispam/lang/ru/options.php index 35aee2a..a6252dd 100644 --- a/cleantalk.antispam/lang/ru/options.php +++ b/cleantalk.antispam/lang/ru/options.php @@ -29,6 +29,7 @@ $MESS['CLEANTALK_EXCLUSIONS'] = 'Исключения'; $MESS['CLEANTALK_EXCLUSIONS_URL'] = 'URL исключения'; $MESS['CLEANTALK_EXCLUSIONS_URL_DESCRIPTION'] = 'Исключение URL из спам-проверки. Перечислите через запятую.'; +$MESS['CLEANTALK_EXCLUSIONS_URLS_REGEXP_DESCRIPTION'] = 'Использовать регулярные выражения в исключении по URL'; $MESS['CLEANTALK_EXCLUSIONS_FIELDS'] = 'Исключение полей форм'; $MESS['CLEANTALK_EXCLUSIONS_FIELDS_DESCRIPTION'] = 'Исключение полей форм из спам-проверки. Перечислите через запятую. Это работает на формах, кроме форм регистрации и комментирования.'; $MESS['CLEANTALK_EXCLUSIONS_FIELDS_REGEXP_DESCRIPTION'] = 'Использовать регулярные выражения в исключении полей'; @@ -40,4 +41,7 @@ $MESS['CLEANTALK_RENEW_NOTIFY']= "Пожалуйста, обновите вашу анти-спам лицензию для Антиспам без CAPTCHA от CleanTalk!"; $MESS['CLEANTALK_MISC'] = 'Прочее'; $MESS['CLEANTALK_LABEL_COMPLETE_DEACTIVATION'] = 'Полная деактивация'; -$MESS['CLEANTALK_WRONG_REGEXP_NOTIFY'] = 'Исключение полей форм является не корректным регулярным выражением.'; \ No newline at end of file +$MESS['CLEANTALK_WRONG_REGEXP_NOTIFY'] = 'Исключение полей форм является не корректным регулярным выражением.'; +$MESS['CLEANTALK_WRONG_DEFAULT_SETTINGS'] = 'Невоможно загрузить опции по умолчанию. Ошибка в имени модуля.'; +$MESS['CLEANTALK_WRONG_CURRENT_SETTINGS'] = 'Невоможно загрузить текущие опции.'; +$MESS['CLEANTALK_RESET_OPTIONS_FAILED'] = 'Невоможно сбросить опции.'; \ No newline at end of file diff --git a/cleantalk.antispam/lib/Cleantalk/Common/Firewall/Firewall.php b/cleantalk.antispam/lib/Cleantalk/Common/Firewall/Firewall.php index ffa5f94..a3db3ee 100644 --- a/cleantalk.antispam/lib/Cleantalk/Common/Firewall/Firewall.php +++ b/cleantalk.antispam/lib/Cleantalk/Common/Firewall/Firewall.php @@ -213,7 +213,7 @@ public function run() if( in_array( $result['status'], array( 'PASS_SFW__BY_WHITELIST', 'PASS_SFW', 'PASS_ANTIFLOOD', 'PASS_ANTICRAWLER', 'PASS_ANTICRAWLER_UA' ) ) ){ continue; } - $module->update_log( $result['ip'], $result['status'] ); + $module->update_log( $result['ip'], $result['status'], $result['is_personal'] ); } } } @@ -343,9 +343,11 @@ public function sendLogs() { $value['status'] = $value['status'] === 'DENY_ANTIFLOOD' ? 'FLOOD_PROTECTION' : $value['status']; $value['status'] = $value['status'] === 'PASS_ANTIFLOOD' ? 'FLOOD_PROTECTION' : $value['status']; - $value['status'] = $value['status'] === 'PASS_SFW__BY_COOKIE' ? null : $value['status']; - $value['status'] = $value['status'] === 'PASS_SFW' ? null : $value['status']; - $value['status'] = $value['status'] === 'DENY_SFW' ? null : $value['status']; + $value['status'] = $value['status'] === 'PASS_SFW__BY_COOKIE' ? 'DB_MATCH' : $value['status']; + $value['status'] = $value['status'] === 'PASS_SFW' ? 'DB_MATCH' : $value['status']; + $value['status'] = $value['status'] === 'DENY_SFW' ? 'DB_MATCH' : $value['status']; + + $value['status'] = $value['source'] ? 'PERSONAL_LIST_MATCH' : $value['status']; $data[] = array( trim( $value['ip'] ), // IP @@ -367,6 +369,11 @@ public function sendLogs() { //Checking answer and deleting all lines from the table if( empty( $result['error'] ) ){ if( $result['rows'] == count( $data ) ){ + $is_source_column_exist = $this->db->fetch( 'SHOW COLUMNS FROM `' . $this->log_table_name . '` LIKE "source";' ); + if( ! $is_source_column_exist ) { + $sql = 'ALTER TABLE `' . $this->log_table_name . '` ADD `source` TINYINT NULL DEFAULT NULL AFTER `ua_name`;'; + $this->db->execute( $sql ); + } $this->db->execute( "TRUNCATE TABLE " . $this->log_table_name . ";" ); return $result; } diff --git a/cleantalk.antispam/lib/Cleantalk/Common/Firewall/FirewallUpdater.php b/cleantalk.antispam/lib/Cleantalk/Common/Firewall/FirewallUpdater.php index 381354d..26d6f94 100644 --- a/cleantalk.antispam/lib/Cleantalk/Common/Firewall/FirewallUpdater.php +++ b/cleantalk.antispam/lib/Cleantalk/Common/Firewall/FirewallUpdater.php @@ -94,9 +94,11 @@ public function update() } // Check if the update performs right now. Blocks remote calls with different ID - if( Get::get('spbc_remote_call_action') == 'sfw_update__write_base' && + if( + Get::get('spbc_remote_call_action') == 'sfw_update__write_base' && Get::get('firewall_updating_id') && - Get::get('firewall_updating_id') !== $fw_stats['firewall_updating_id'] + Get::get('firewall_updating_id') !== $fw_stats['firewall_updating_id'] && + time() - $fw_stats['firewall_updating_last_start'] < 8600 ) { return array( 'error' => 'FIREWALL_IS_UPDATING' ); } @@ -168,7 +170,7 @@ public function update() // Do writing to the DB reset( $lines ); for( $count_result = 0; current($lines) !== false; ) { - $query = "INSERT INTO ".$this->fw_data_table_name."_temp (network, mask, status) VALUES "; + $query = "INSERT INTO ".$this->fw_data_table_name."_temp (network, mask, status, source) VALUES "; for( $i = 0, $values = array(); self::WRITE_LIMIT !== $i && current( $lines ) !== false; $i ++, $count_result ++, next( $lines ) ){ $entry = current($lines); if(empty($entry)) { @@ -179,8 +181,9 @@ public function update() $ip = preg_replace('/[^\d]*/', '', $entry[0]); $mask = preg_replace('/[^\d]*/', '', $entry[1]); $private = isset($entry[2]) ? $entry[2] : 0; + $source = isset($entry[3]) ? $entry[3] : 0; } - $values[] = '('. $ip .','. $mask .','. $private .')'; + $values[] = '('. $ip .','. $mask .','. $private .','. $source .')'; } if( ! empty( $values ) ){ $query = $query . implode( ',', $values ) . ';'; @@ -359,6 +362,12 @@ private function createTempTables() $sql = sprintf( Schema::getSchema('sfw'), $this->db->prefix ); $this->db->execute( $sql ); } + $is_source_column_exist = $this->db->fetch( 'SHOW COLUMNS FROM `' . APBCT_TBL_FIREWALL_DATA . '` LIKE "source";' ); + if( ! $is_source_column_exist ) { + $sql = 'ALTER TABLE `' . APBCT_TBL_FIREWALL_DATA . '` ADD `source` TINYINT NULL DEFAULT NULL AFTER `status`;'; + $this->db->execute( $sql ); + } + $this->db->execute( 'CREATE TABLE IF NOT EXISTS `' . APBCT_TBL_FIREWALL_DATA . '_temp` LIKE `' . APBCT_TBL_FIREWALL_DATA . '`;' ); $this->db->execute( 'TRUNCATE TABLE `' . APBCT_TBL_FIREWALL_DATA . '_temp`;' ); } diff --git a/cleantalk.antispam/lib/Cleantalk/Common/Firewall/Modules/SFW.php b/cleantalk.antispam/lib/Cleantalk/Common/Firewall/Modules/SFW.php index 67f3e34..7d59252 100644 --- a/cleantalk.antispam/lib/Cleantalk/Common/Firewall/Modules/SFW.php +++ b/cleantalk.antispam/lib/Cleantalk/Common/Firewall/Modules/SFW.php @@ -43,11 +43,19 @@ public function check() { $results = array(); $status = 0; + + if ( $this->test ) { + unset($_COOKIE['ct_sfw_pass_key']); + \Cleantalk\Common\Helper::apbct_cookie__set('ct_sfw_pass_key', '0'); + $ct_sfw_pass_key = $_COOKIE[ 'ct_sfw_pass_key']; + } else { + $ct_sfw_pass_key = Cookie::get( 'ct_sfw_pass_key'); + } // Skip by cookie foreach( $this->ip_array as $current_ip ){ - if( substr( Cookie::get( 'ct_sfw_pass_key' ), 0, 32 ) == md5( $current_ip . $this->api_key ) ){ + if( substr( $ct_sfw_pass_key, 0, 32 ) == md5( $current_ip . $this->api_key ) ){ if( Cookie::get( 'ct_sfw_passed' ) ){ @@ -66,7 +74,7 @@ public function check() } - if( strlen( Cookie::get( 'ct_sfw_pass_key' ) ) > 32 ) { + if( strlen($ct_sfw_pass_key) > 32 ) { $status = substr( Cookie::get( 'ct_sfw_pass_key' ), -1 ); } @@ -89,33 +97,33 @@ public function check() } $needles = array_unique( $needles ); - $db_results = $this->db->fetch_all("SELECT - network, mask, status - FROM " . $this->db_data_table_name . " + $db_results = $this->db->fetch_all("SELECT * FROM " . $this->db_data_table_name . " WHERE network IN (". implode( ',', $needles ) .") AND network = " . $current_ip_v4 . " & mask AND " . rand( 1, 100000 ) . " ORDER BY status DESC"); - if( ! empty( $db_results ) ){ + if ( ! empty( $db_results ) ) { foreach( $db_results as $db_result ){ - - if( $db_result['status'] == 1 ) { - $results[] = array('ip' => $current_ip, 'is_personal' => false, 'status' => 'PASS_SFW__BY_WHITELIST',); + $is_personal = isset($db_result['source']) && $db_result['source'] == 1 ? true : false; + if ( $db_result['status'] == 1 ) { + $results[] = array('ip' => $current_ip, 'is_personal' => $is_personal, 'status' => 'PASS_SFW__BY_WHITELIST',); break; + } else { + $results[] = array('ip' => $current_ip, 'is_personal' => $is_personal, 'status' => 'DENY_SFW',); + if ($this->test){ + $test_data = array('ip' => $current_ip, 'is_personal' => $is_personal, 'status' => 'DENY_SFW'); + } } - else - $results[] = array('ip' => $current_ip, 'is_personal' => false, 'status' => 'DENY_SFW',); } - - }else{ - + } else { $results[] = array( 'ip' => $current_ip, 'is_personal' => false, 'status' => 'PASS_SFW' ); - } } - + if ($this->test && isset($test_data)){ + return array($test_data); + } return $results; } @@ -126,7 +134,7 @@ public function check() * @param string $ip * @param string $status */ - public function update_log( $ip, $status ) + public function update_log( $ip, $status, $is_personal ) { $id = md5( $ip . $this->module_name ); @@ -140,14 +148,21 @@ public function update_log( $ip, $status ) all_entries = 1, blocked_entries = " . ( strpos( $status, 'DENY' ) !== false ? 1 : 0 ) . ", entries_timestamp = '" . $time . "', - ua_name = '" . addslashes(Server::get('HTTP_USER_AGENT')) . "' + ua_name = '" . addslashes(Server::get('HTTP_USER_AGENT')) . "'%s ON DUPLICATE KEY UPDATE status = '$status', all_entries = all_entries + 1, blocked_entries = blocked_entries" . ( strpos( $status, 'DENY' ) !== false ? ' + 1' : '' ) . ", entries_timestamp = '" . intval( $time ) . "', - ua_name = '" . addslashes(Server::get('HTTP_USER_AGENT')) . "'"; + ua_name = '" . addslashes(Server::get('HTTP_USER_AGENT')) . "'%s"; + + if ( $is_personal ) { + $is_personal_sql = ", source = '" . $is_personal . "'"; + $query = sprintf( $query, $is_personal_sql, $is_personal_sql); + } else { + $query = sprintf( $query, '', ''); + } $this->db->execute( $query ); } diff --git a/cleantalk.antispam/lib/Cleantalk/Common/Helper.php b/cleantalk.antispam/lib/Cleantalk/Common/Helper.php index bdabd58..aced3f5 100644 --- a/cleantalk.antispam/lib/Cleantalk/Common/Helper.php +++ b/cleantalk.antispam/lib/Cleantalk/Common/Helper.php @@ -675,10 +675,9 @@ static public function get_fields_any($arr, $fields_exclusions = '', $message = } unset($needle); - + $value_for_email = trim( $value ); // Removes shortcodes to do better spam filtration on server side. // Removes whitespaces $value = urldecode( trim( $value ) ); // Fully cleaned message - $value_for_email = trim( $value ); // Removes shortcodes to do better spam filtration on server side. // Email if ( ! $email && preg_match( "/^\S+@\S+\.\S+$/", $value_for_email ) ) { diff --git a/cleantalk.antispam/lib/Cleantalk/Common/Schema.php b/cleantalk.antispam/lib/Cleantalk/Common/Schema.php index 5a8a473..47ca9ca 100644 --- a/cleantalk.antispam/lib/Cleantalk/Common/Schema.php +++ b/cleantalk.antispam/lib/Cleantalk/Common/Schema.php @@ -13,6 +13,7 @@ class Schema `network` int(11) unsigned NOT NULL, `mask` int(11) unsigned NOT NULL, `status` TINYINT(1) NOT NULL DEFAULT 0, + `source` => TINYINT NULL DEFAULT NULL, PRIMARY KEY (`id`), INDEX ( `network` , `mask` ) );', @@ -32,6 +33,7 @@ class Schema `entries_timestamp` INT NOT NULL, `ua_id` INT(11) NULL DEFAULT NULL, `ua_name` VARCHAR(1024) NOT NULL, + `source` => TINYINT NULL DEFAULT NULL, PRIMARY KEY (`id`));', 'ac_logs' => 'CREATE TABLE IF NOT EXISTS `%scleantalk_ac_log` ( `id` VARCHAR(40) NOT NULL, diff --git a/cleantalk.antispam/options.php b/cleantalk.antispam/options.php index 285bc15..f301dc4 100644 --- a/cleantalk.antispam/options.php +++ b/cleantalk.antispam/options.php @@ -13,47 +13,31 @@ global $MESS; IncludeModuleLangFile( __FILE__ ); +use Bitrix\Main\Config\Option; use Cleantalk\Common\API as CleantalkAPI; use Cleantalk\Common\Helper as CleantalkHelper; -$cleantalk_antispam_default_settings = array( - 'status' => 1, - 'form_new_user' => 1, - 'form_comment_blog' => 1, - 'form_comment_forum' => 1, - 'form_forum_private_messages' => 1, - 'form_comment_treelike' => 1, - 'form_send_example' => 1, - 'form_order' => 1, - 'web_form' => 1, - 'form_global_check' => 0, - 'form_global_check_without_email' => 0, - 'form_sfw' => 1, - 'site_exclusions' => '', - 'form_exclusions_url' => '', - 'form_exclusions_url__regexp' => 0, - 'form_exclusions_fields' => '', - 'form_exclusions_fields__regexp' => 0, - 'form_exclusions_webform' => '', - 'complete_deactivation' => 0, -); - $cleantalk_is_wrong_regexp = false; $cleantalk_is_wrong_url_regexp = false; -if( $REQUEST_METHOD == 'POST' && $_POST['Update'] == 'Y' ) { +if ( ! empty($REQUEST_METHOD) && $REQUEST_METHOD == 'POST' && $_POST['Update'] == 'Y' ) { + //try to get default options + $default_options = ct_get_default_options($sModuleId); + if ( ! $default_options ){ + //if failed - get current instead + $default_options = ct_get_options($sModuleId); + } + + //reset options to defaults if reset in post if ( isset($_POST['reset']) ) { - foreach ( $cleantalk_antispam_default_settings as $setting => $value ) { - if ( is_string( $value ) ) { - COption::SetOptionString($sModuleId, $setting, $value); - } - if ( is_int( $value ) ) { - COption::SetOptionInt($sModuleId, $setting, $value); - } - } + //try to reset options to defaults + ct_reset_options($sModuleId); + // if failed anyway it will be rewrote by current options + $current_options = ct_get_options($sModuleId); } else { - $old_key = COption::GetOptionString( $sModuleId, 'key', '' ); + //save current key + $old_key = Option::get($sModuleId,'key'); //Getting key automatically if(isset($_POST['getautokey'])){ @@ -63,11 +47,11 @@ if (empty($result['error'])){ if(isset($result['user_token'])){ - COption::SetOptionString( $sModuleId, 'user_token', $result['user_token']); + Option::set( $sModuleId, 'user_token', $result['user_token']); } if(isset($result['auth_key'])){ - COption::SetOptionString( $sModuleId, 'key', $result['auth_key']); + Option::set( $sModuleId, 'key', $result['auth_key']); $new_key = $result['auth_key']; } } @@ -77,6 +61,7 @@ } // Send empty feedback for version comparison in Dashboard + $new_key = isset( $new_key ) ? $new_key : $old_key; $result = CleantalkAPI::method__send_empty_feedback($new_key, CLEANTALK_USER_AGENT); /** @@ -86,12 +71,12 @@ if (CleantalkHelper::key_is_correct($new_key)) { $result = CleantalkAPI::method__notice_paid_till($new_key, preg_replace('/http[s]?:\/\//', '', $_SERVER['HTTP_HOST'], 1)); - COption::SetOptionInt($sModuleId, 'key_is_ok', (empty($result['error']) && isset($result['valid']) && $result['valid'] == 1) ? 1 : 0); - COption::SetOptionString($sModuleId, 'user_token', (empty($result['error']) && isset($result['user_token'])) ? $result['user_token'] : ''); - COption::SetOptionInt($sModuleId, 'moderate_ip', (empty($result['error']) && isset($result['moderate_ip']) && $result['moderate_ip'] == 1) ? 1 : 0); - COption::SetOptionInt($sModuleId, 'ip_license', (empty($result['error']) && isset($result['moderate_ip'], $result['ip_license']) && $result['moderate_ip'] == 1) ? $result['ip_license'] : 0); + Option::set($sModuleId, 'key_is_ok', (empty($result['error']) && isset($result['valid']) && $result['valid'] == 1) ? 1 : 0); + Option::set($sModuleId, 'user_token', (empty($result['error']) && isset($result['user_token'])) ? $result['user_token'] : ''); + Option::set($sModuleId, 'moderate_ip', (empty($result['error']) && isset($result['moderate_ip']) && $result['moderate_ip'] == 1) ? 1 : 0); + Option::set($sModuleId, 'ip_license', (empty($result['error']) && isset($result['moderate_ip'], $result['ip_license']) && $result['moderate_ip'] == 1) ? $result['ip_license'] : 0); - if (empty($result['error'])) { + if ( empty($result['error']) ) { if (isset($result['show_notice'], $result['trial']) && $result['show_notice'] == 1 && $result['trial'] == 1) { CAdminNotify::Add(array( 'MESSAGE' => GetMessage( 'CLEANTALK_TRIAL_NOTIFY' ), @@ -112,73 +97,72 @@ } } } else { - COption::SetOptionInt($sModuleId, 'key_is_ok', 0); - COption::SetOptionString($sModuleId, 'user_token',''); - COption::SetOptionInt($sModuleId, 'moderate_ip', 0); - COption::SetOptionInt($sModuleId, 'ip_license', 0); + Option::set($sModuleId, 'key_is_ok', 0); + Option::set($sModuleId, 'user_token',''); + Option::set($sModuleId, 'moderate_ip', 0); + Option::set($sModuleId, 'ip_license', 0); } - - COption::SetOptionInt( $sModuleId, 'status', $_POST['status'] == '1' ? 1 : 0 ); - COption::SetOptionInt( $sModuleId, 'form_new_user', $_POST['form_new_user'] == '1' ? 1 : 0 ); - COption::SetOptionInt( $sModuleId, 'form_comment_blog', $_POST['form_comment_blog'] == '1' ? 1 : 0 ); - COption::SetOptionInt( $sModuleId, 'form_comment_forum', $_POST['form_comment_forum'] == '1' ? 1 : 0 ); - COption::SetOptionInt( $sModuleId, 'form_forum_private_messages', $_POST['form_forum_private_messages'] == '1' ? 1 : 0 ); - COption::SetOptionInt( $sModuleId, 'form_comment_treelike', $_POST['form_comment_treelike'] == '1' ? 1 : 0 ); - COption::SetOptionInt( $sModuleId, 'form_send_example', $_POST['form_send_example'] == '1' ? 1 : 0 ); - COption::SetOptionInt( $sModuleId, 'form_order', $_POST['form_order'] == '1' ? 1 : 0 ); - COption::SetOptionInt( $sModuleId, 'web_form', $_POST['web_form'] == '1' ? 1 : 0 ); - COption::SetOptionInt( $sModuleId, 'is_paid', $_POST['is_paid'] == '1' ? 1 : 0 ); - COption::SetOptionInt( $sModuleId, 'last_checked', $_POST['last_checked'] == '1' ? 1 : 0 ); - COption::SetOptionInt( $sModuleId, 'form_global_check', $_POST['form_global_check'] == '1' ? 1 : 0 ); - COption::SetOptionInt( $sModuleId, 'form_global_check_without_email', $_POST['form_global_check_without_email'] == '1' ? 1 : 0 ); - COption::SetOptionInt( $sModuleId, 'form_sfw', $_POST['form_sfw'] == '1' ? 1 : 0 ); + //set non-key options + Option::set( $sModuleId, 'status', $_POST['status'] == '1' ? 1 : 0 ); + Option::set( $sModuleId, 'form_new_user', $_POST['form_new_user'] == '1' ? 1 : 0 ); + Option::set( $sModuleId, 'form_comment_blog', $_POST['form_comment_blog'] == '1' ? 1 : 0 ); + Option::set( $sModuleId, 'form_comment_forum', $_POST['form_comment_forum'] == '1' ? 1 : 0 ); + Option::set( $sModuleId, 'form_forum_private_messages', $_POST['form_forum_private_messages'] == '1' ? 1 : 0 ); + Option::set( $sModuleId, 'form_comment_treelike', $_POST['form_comment_treelike'] == '1' ? 1 : 0 ); + Option::set( $sModuleId, 'form_send_example', $_POST['form_send_example'] == '1' ? 1 : 0 ); + Option::set( $sModuleId, 'form_order', $_POST['form_order'] == '1' ? 1 : 0 ); + Option::set( $sModuleId, 'web_form', $_POST['web_form'] == '1' ? 1 : 0 ); + Option::set( $sModuleId, 'is_paid', $_POST['is_paid'] == '1' ? 1 : 0 ); + Option::set( $sModuleId, 'last_checked', $_POST['last_checked'] == '1' ? 1 : 0 ); + Option::set( $sModuleId, 'form_global_check', $_POST['form_global_check'] == '1' ? 1 : 0 ); + Option::set( $sModuleId, 'form_global_check_without_email', $_POST['form_global_check_without_email'] == '1' ? 1 : 0 ); + Option::set( $sModuleId, 'form_sfw', $_POST['form_sfw'] == '1' ? 1 : 0 ); + Option::set( $sModuleId, 'complete_deactivation', $_POST['complete_deactivation'] == '1' ? 1 : 0 ); if (isset($_POST['form_exclusions_sites']) && is_array($_POST['form_exclusions_sites'])) { $exclusion_sites = array(); foreach ($_POST['form_exclusions_sites'] as $value) { $exclusion_sites[] = $value; } - COption::SetOptionString( $sModuleId, 'site_exclusions', implode(',', $exclusion_sites)); + Option::set( $sModuleId, 'site_exclusions', implode(',', $exclusion_sites)); } else { - COption::SetOptionString( $sModuleId, 'site_exclusions', $cleantalk_antispam_default_settings['site_exclusions']); + Option::set( $sModuleId, 'site_exclusions', $default_options['site_exclusions']); } - COption::SetOptionString( $sModuleId, 'form_exclusions_url', isset($_POST['form_exclusions_url']) ? $_POST['form_exclusions_url'] : $cleantalk_antispam_default_settings['form_exclusions_url'] ); + Option::set( $sModuleId, 'form_exclusions_url', isset($_POST['form_exclusions_url']) ? $_POST['form_exclusions_url'] : $default_options['form_exclusions_url'] ); if ( - isset($_POST['form_exclusions_url']) && + isset($_POST['form_exclusions_url'], $_POST['form_exclusions_url__regexp']) && ! empty($_POST['form_exclusions_url']) && - isset($_POST['form_exclusions_url__regexp']) && ct_is_valid_regexp($_POST['form_exclusions_url']) ) { - COption::SetOptionInt( $sModuleId, 'form_exclusions_url__regexp', isset($_POST['form_exclusions_url__regexp']) ? $_POST['form_exclusions_url__regexp'] : $cleantalk_antispam_default_settings['form_exclusions_url__regexp'] ); + Option::set( $sModuleId, 'form_exclusions_url__regexp', isset($_POST['form_exclusions_url__regexp']) ? $_POST['form_exclusions_url__regexp'] : $default_options['form_exclusions_url__regexp'] ); } else { if ( ! empty($_POST['form_exclusions_url']) && isset($_POST['form_exclusions_url__regexp']) ) { $cleantalk_is_wrong_url_regexp = true; } - COption::SetOptionInt( $sModuleId, 'form_exclusions_url__regexp', 0 ); + Option::set( $sModuleId, 'form_exclusions_url__regexp', 0 ); } - COption::SetOptionString( $sModuleId, 'form_exclusions_fields', isset($_POST['form_exclusions_fields']) ? $_POST['form_exclusions_fields'] : $cleantalk_antispam_default_settings['form_exclusions_fields'] ); + Option::set( $sModuleId, 'form_exclusions_fields', isset($_POST['form_exclusions_fields']) ? $_POST['form_exclusions_fields'] : $default_options['form_exclusions_fields'] ); if ( - isset($_POST['form_exclusions_fields']) && + isset($_POST['form_exclusions_fields'], $_POST['form_exclusions_fields__regexp']) && ! empty($_POST['form_exclusions_fields']) && - isset($_POST['form_exclusions_fields__regexp']) && ct_is_valid_regexp($_POST['form_exclusions_fields']) ) { - COption::SetOptionInt( $sModuleId, 'form_exclusions_fields__regexp', isset($_POST['form_exclusions_fields__regexp']) ? $_POST['form_exclusions_fields__regexp'] : $cleantalk_antispam_default_settings['form_exclusions_fields__regexp'] ); + Option::set( $sModuleId, 'form_exclusions_fields__regexp', isset($_POST['form_exclusions_fields__regexp']) ? $_POST['form_exclusions_fields__regexp'] : $default_options['form_exclusions_fields__regexp'] ); } else { if ( ! empty($_POST['form_exclusions_fields']) && isset($_POST['form_exclusions_fields__regexp']) ) { $cleantalk_is_wrong_regexp = true; } - COption::SetOptionInt( $sModuleId, 'form_exclusions_fields__regexp', 0 ); + Option::set( $sModuleId, 'form_exclusions_fields__regexp', 0 ); } - COption::SetOptionString( $sModuleId, 'form_exclusions_webform', isset($_POST['form_exclusions_webform']) ? $_POST['form_exclusions_webform'] : $cleantalk_antispam_default_settings['form_exclusions_webform'] ); + Option::set( $sModuleId, 'form_exclusions_webform', isset($_POST['form_exclusions_webform']) ? $_POST['form_exclusions_webform'] : $default_options['form_exclusions_webform'] ); - COption::SetOptionString( $sModuleId, 'key', $new_key ); + Option::set( $sModuleId, 'key', $new_key ); // URL host - COption::SetOptionString( $sModuleId, 'host_url', ( isset( $_SERVER['HTTPS'] ) && $_SERVER['HTTPS'] === 'on' ? "https" : "http" ) . "://" . $_SERVER['HTTP_HOST'] ); + Option::set( $sModuleId, 'host_url', ( isset( $_SERVER['HTTPS'] ) && $_SERVER['HTTPS'] === 'on' ? "https" : "http" ) . "://" . $_SERVER['HTTP_HOST'] ); // SFW scheduled actions if($_POST['form_sfw'] == 1) { @@ -219,6 +203,67 @@ function ct_is_regexp($regexp) return @preg_match('/' . $regexp . '/', '') !== false; } +/** + * Reads option set for the cleantalk module. + * + * @param $sModuleId + * + * @return array|false + */ +function ct_get_default_options($sModuleId){ + try { + return Option::getDefaults($sModuleId); + } catch (\Bitrix\Main\ArgumentOutOfRangeException $ex) { + CAdminNotify::Add(array( + 'MESSAGE' => GetMessage('CLEANTALK_WRONG_DEFAULT_SETTINGS'), + 'TAG' => 'def_options_failed', + 'MODULE_ID' => 'main', + 'ENABLE_CLOSE' => 'Y')); + } + return false; +} + +/** + * Reset cleantalk options to defaults. If some option reset fails throw admin notice + * @param $sModuleId + */ +function ct_reset_options($sModuleId){ + $default_options = ct_get_default_options($sModuleId); + if ( $default_options !== false ) { + foreach ( $default_options as $setting => $value ) { + try { + Option::set($sModuleId, $setting, $value); + } catch (\Bitrix\Main\ArgumentOutOfRangeException $ex) { + CAdminNotify::Add(array( + 'MESSAGE' => GetMessage( 'CLEANTALK_RESET_OPTIONS_FAILED' ), + 'TAG' => 'current_options_failed', + 'MODULE_ID' => 'main', + 'ENABLE_CLOSE' => 'Y')); + } + } + } +} + + +/** + * Return current cleantalk options or false if exception. + * @param $sModuleId + * @return array|false + */ +function ct_get_options($sModuleId){ + try { + $result = Option::getForModule($sModuleId); + } catch (\Bitrix\Main\ArgumentNullException $ex){ + CAdminNotify::Add(array( + 'MESSAGE' => GetMessage( 'CLEANTALK_WRONG_CURRENT_SETTINGS' ), + 'TAG' => 'cur_options_failed', + 'MODULE_ID' => 'main', + 'ENABLE_CLOSE' => 'Y')); + return false; + } + return $result; +} + /** * Describe tabs */ @@ -230,25 +275,25 @@ function ct_is_regexp($regexp) 'TITLE' => GetMessage('MAIN_TAB_TITLE_SET' ) ), ); - + /** * Init tabs */ $oTabControl = new CAdmintabControl( 'tabControl', $aTabs ); $oTabControl->Begin(); - + /** - * Settings form + * Settings form HTML */ -?>
+?> - BeginNextTab();?> -