diff --git a/cleantalk/config.php b/cleantalk/config.php index cfcf59d..8458ab9 100644 --- a/cleantalk/config.php +++ b/cleantalk/config.php @@ -1,11 +1,16 @@ - +
@@ -320,3 +320,130 @@ function apbct__cscart_js_snippet() {
%sLearn more
+
+ ';
+ $signs = '';
+ foreach ( $form_post_signs_exclusions_set as $sign) {
+ if (is_string($sign)) {
+ $signs .= $sign . "\r\n";
+ }
+ }
+
+ $style_textarea = 'word-break: break-all; padding: 1%; background: #fff; width: 100%';
+ $style_span = 'display: flex; justify-content: flex-end; margin: 1%';
+
+ return sprintf($template, $hint_text, $style_span, $link_learn_more, $style_textarea, htmlspecialchars($signs));
+}
+
+function apbct__prepare_service_field_exclusion_layout()
+{
+ global $exclusion_key;
+
+ if (!empty($exclusion_key)) {
+ $service_field = htmlspecialchars('');
+ } else {
+ $service_field = 'Error! Can not gain exclusion key.';
+ }
+
+ $hint_text = 'Regular expression. If the form contains any of these signs in POST array keys or in value of "action" key, the whole form submission is excluded from spam checking.';
+ $style = 'border: solid 1px; word-break: break-all; padding: 1%; background: #fff;';
+
+ $template = '
+ %s
+
+ %s
+
+ ';
+
+ return $exclusion_key ? sprintf($template, $hint_text, $style, $service_field) : $service_field;
+}
+/**
+ * Sanitize and validate exclusions.
+ * Explode given string by commas and trim each string.
+ * Cut first 20 entities if more than 20 given. Remove duplicates.
+ * Skip element if it's empty. Validate entity as URL. Cut first 128 chars if more than 128 given
+ *
+ * Return false if exclusion is bad
+ * Return sanitized string if all is ok
+ *
+ * @param string $exclusions
+ * @param bool $regexp
+ *
+ * @return bool|string|array
+ */
+function apbct_settings__sanitize__exclusions($exclusions, $return_array = false, $regexp = true, $urls = false)
+{
+ if ( ! is_string($exclusions) ) {
+ return false;
+ }
+
+ $result = array();
+ $type = 0;
+
+ if ( ! empty($exclusions) ) {
+ if ( strpos($exclusions, "\r\n") !== false ) {
+ $exclusions = explode("\r\n", $exclusions);
+ $type = 2;
+ } elseif ( strpos($exclusions, "\n") !== false ) {
+ $exclusions = explode("\n", $exclusions);
+ $type = 1;
+ } else {
+ $exclusions = explode(',', $exclusions);
+ }
+ //Drop duplicates first (before cut)
+ $exclusions = array_unique($exclusions);
+ //Take first 20 exclusions entities
+ $exclusions = array_slice($exclusions, 0, 20);
+ //Sanitizing
+ foreach ($exclusions as $exclusion) {
+ //Cut exclusion if more than 128 symbols gained
+ $sanitized_exclusion = substr($exclusion, 0, 128);
+ $sanitized_exclusion = trim($sanitized_exclusion);
+
+ if ( ! empty($sanitized_exclusion) ) {
+ if ( $regexp ) {
+ if ( @preg_match('/' . $exclusion . '/', '') === false) {
+ return false;
+ }
+ } elseif ( $urls ) {
+ if (
+ ( strpos($exclusion, 'http://') !== false || strpos($exclusion, 'https://') !== false ) &&
+ filter_var($exclusion, FILTER_VALIDATE_URL)
+ ) {
+ return false;
+ }
+ }
+ $result[] = $sanitized_exclusion;
+ }
+ }
+ }
+ if ($return_array) {
+ return $result;
+ }
+ switch ( $type ) {
+ case 0:
+ default:
+ return implode(',', $result);
+ case 1:
+ return implode("\n", $result);
+ case 2:
+ return implode("\r\n", $result);
+ }
+}
diff --git a/cleantalk/inc/functions.php b/cleantalk/inc/functions.php
index 498bd04..5d77e68 100644
--- a/cleantalk/inc/functions.php
+++ b/cleantalk/inc/functions.php
@@ -29,8 +29,7 @@ function apbct_spam_test($data){
$registrations_test,
$general_postdata_test,
$detected_cms,
- $exclusion_key,
- $general_post_exclusion_usage;
+ $form_post_signs_exclusions_set;
// Patch for old PHP versions.
require_once( CLEANTALK_ROOT . 'lib' . DS . 'ct_phpFix.php');
@@ -64,15 +63,6 @@ function apbct_spam_test($data){
$registration = true;
}
- //init exclusions array if general_post_exclusion_usage is enabled
- if ( isset($exclusion_key, $general_post_exclusion_usage) && $general_post_exclusion_usage ) {
- $exclusions_in_post = array(
- 'ct_service_data' => $exclusion_key,
- );
- } else {
- $exclusions_in_post = array();
- }
-
$url_exclusions = array();
if (
@@ -86,15 +76,13 @@ function apbct_spam_test($data){
);
}
-
-
// Skip check if
if ( $skip || // Skip flag set by apbct_get_fields_any()
(!$sender_email && !$general_postdata_test) || // No email detected and general post data test is disabled
($registration && !$registrations_test) || // It's registration and registration check is disabled
- (apbct_check__exclusions()) || // main exclusion function
- (apbct_check__exclusions_in_post($exclusions_in_post)) || // Has an exclusions in POST
- (apbct_check__url_exclusions($url_exclusions)) // Has an exclusions in URL
+ (apbct_check__exclusions_general()) || // main exclusion function
+ (apbct_check__url_exclusions($url_exclusions)) || // Has an exclusions in URL
+ (apbct_check__form_signs_exclusions($data, $form_post_signs_exclusions_set)) // Has an exclusions in POST fields
) {
$skip = true;
}
@@ -497,13 +485,12 @@ function apbct_check__url_exclusions( $exclusions = array() ){
global $detected_cms;
//custom login word transform ruleset
- $login_word = 'login';
if ( isset($detected_cms) ) {
switch ( $detected_cms ) {
//moodle case
case 'moodle':
{
- $login_word = 'login/index.php';
+ $exclusions[] = 'login/index.php';
break;
}
case 'OpenMage':
@@ -514,7 +501,6 @@ function apbct_check__url_exclusions( $exclusions = array() ){
}
}
}
- $exclusions[] = $login_word;
foreach ( $exclusions as $name => $exclusion ){
if( \Cleantalk\Variables\Server::has_string('REQUEST_URI', $exclusion ) ){
@@ -525,10 +511,42 @@ function apbct_check__url_exclusions( $exclusions = array() ){
return false;
}
+ /**
+ * Check POST array for the exclusion form signs. Listen for array keys or for value in case if key is "action".
+ * @param array $form_data The POST array or another filtered array of form data.
+ * @param array $exclusions
+ * @return bool True if exclusion found in the keys of array, false otherwise.
+ */
+ function apbct_check__form_signs_exclusions($form_data, $exclusions)
+ {
+ if ( is_array($exclusions) && is_array($form_data) ) {
+ foreach ( $exclusions as $exclusion ) {
+ foreach ($form_data as $key => $value) {
+ if ( !empty($value) && is_array($value) ) {
+ if ( apbct_check__form_signs_exclusions($value, $exclusions) ) {
+ return true;
+ }
+ }
+ $haystack = ($key === 'action' || $key === 'data') ? $value : $key;
+ if (
+ $haystack === $exclusion ||
+ (is_string($haystack) && stripos($haystack, $exclusion) !== false) ||
+ (is_string($haystack) && preg_match('@' . $exclusion . '@', $haystack) === 1)
+ ) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+ return false;
+ }
+
+
/**
* Another function for excluding validation based on any number of parameters
*/
- function apbct_check__exclusions() {
+ function apbct_check__exclusions_general() {
global $detected_cms;
@@ -573,6 +591,14 @@ function apbct_check__exclusions() {
return true;
}
+ //init exclusions array if service_field_in_post_exclusion is enabled
+ if ( isset($exclusion_key, $service_field_in_post_exclusion_enabled) && $service_field_in_post_exclusion_enabled ) {
+ $service_field_exclusion = array(
+ 'ct_service_data' => $exclusion_key,
+ );
+ return apbct_check__exclusions_in_post($service_field_exclusion);
+ }
+
if (\Cleantalk\Variables\Get::equal('controller', 'ajax') &&
\Cleantalk\Variables\Get::equal('do', 'passwordStrength')
) {
diff --git a/cleantalk/js/custom.js b/cleantalk/js/custom.js
index 1d45c39..2ec6d59 100644
--- a/cleantalk/js/custom.js
+++ b/cleantalk/js/custom.js
@@ -101,14 +101,23 @@ jQuery(document).ready(function($) {
});
//set the block with special tag in dependence of post_exclusion_usage statement
- $('#general_post_exclusion_usage').on('click', function(event) {
+ $('#service_field_in_post_exclusion_enabled').on('click', function(event) {
let state = 'none'
- if ($('#general_post_exclusion_usage').prop('checked')){
+ if ($('#service_field_in_post_exclusion_enabled').prop('checked')){
state = 'inherit'
}
$('#exclusions-div').css('display',state)
});
+ //show array of exclusions
+ $('#form_post_exclusions_signs_usage').on('click', function(event) {
+ let state = 'none'
+ if ($('#form_post_exclusions_signs_usage').prop('checked')){
+ state = 'inherit'
+ }
+ $('#form_signs_exclusions-div').css('display',state)
+ });
+
$('#btn-login').on('click', function(event) {
login();
@@ -290,7 +299,10 @@ jQuery(document).ready(function($) {
registrations_test: $('#check_reg').is(':checked') ? 1 : 0,
general_postdata_test: $('#check_without_email').is(':checked') ? 1 : 0,
spam_firewall: $('#enable_sfw').is(':checked') ? 1 : 0,
- general_post_exclusion_usage: $('#general_post_exclusion_usage').is(':checked') ? 1 : 0,
+ service_field_in_post_exclusion_enabled: $('#service_field_in_post_exclusion_enabled').is(':checked') ? 1 : 0,
+ // form post signs exclusion
+ form_post_exclusions_enabled: $('#form_post_exclusions_signs_usage').is(':checked') ? 1 : 0,
+ form_post_exclusions_signs_string: $('textarea#form_signs_exclusions-textarea').val(),
},
{
callback: function(result, data, params, obj) {
diff --git a/cleantalk/lib/Cleantalk/Antispam/Cleantalk.php b/cleantalk/lib/Cleantalk/Antispam/Cleantalk.php
index 3d7eed0..fb289cd 100644
--- a/cleantalk/lib/Cleantalk/Antispam/Cleantalk.php
+++ b/cleantalk/lib/Cleantalk/Antispam/Cleantalk.php
@@ -100,7 +100,7 @@ class Cleantalk {
/**
* Function checks whether it is possible to publish the message
* @param CleantalkRequest $request
- * @return type
+ * @return CleantalkResponse
*/
public function isAllowMessage(CleantalkRequest $request) {
$msg = $this->createMsg('check_message', $request);
@@ -242,7 +242,7 @@ function_exists('base64_encode')
/**
* httpRequest
* @param $msg
- * @return boolean|CleantalkResponse
+ * @return CleantalkResponse
*/
private function httpRequest($msg) {
@@ -375,8 +375,10 @@ public function get_servers_ip($host)
/**
* Send JSON request to servers
- * @param $msg
- * @return boolean|\CleantalkResponse
+ * @param $url
+ * @param $data
+ * @param $server_timeout
+ * @return boolean|CleantalkResponse
*/
private function sendRequest($url, $data, $server_timeout = 3)
{
diff --git a/cleantalk/lib/Cleantalk/Antispam/CleantalkRequest.php b/cleantalk/lib/Cleantalk/Antispam/CleantalkRequest.php
index d364954..48de280 100644
--- a/cleantalk/lib/Cleantalk/Antispam/CleantalkRequest.php
+++ b/cleantalk/lib/Cleantalk/Antispam/CleantalkRequest.php
@@ -12,25 +12,25 @@ class CleantalkRequest {
* @var string
*/
public $all_headers = null;
-
+
/**
* IP address of connection
* @var string
*/
//public $remote_addr = null;
-
+
/**
* Last error number
* @var integer
*/
public $last_error_no = null;
-
+
/**
* Last error time
* @var integer
*/
public $last_error_time = null;
-
+
/**
* Last error text
* @var string
@@ -117,8 +117,11 @@ class CleantalkRequest {
* @var int
*/
public $submit_time = null;
-
+
public $x_forwarded_for = '';
+
+ public $x_forwarded_for_last = '';
+
public $x_real_ip = '';
/**
@@ -147,22 +150,22 @@ class CleantalkRequest {
/**
* Phone number
- * @var type
+ * @var type
*/
public $phone = null;
-
+
/**
* Method name
* @var string
*/
- public $method_name = 'check_message';
+ public $method_name = 'check_message';
/**
* Fill params with constructor
* @param type $params
*/
public function __construct($params = null) {
-
+
// IPs
$this->sender_ip = isset($params['sender_ip']) ? (string)$params['sender_ip'] : null;
$this->x_forwarded_for = isset($params['x_forwarded_for']) ? (string)$params['x_forwarded_for'] : null;
@@ -178,14 +181,14 @@ public function __construct($params = null) {
$this->submit_time = isset($params['submit_time']) ? (int)$params['submit_time'] : null;
$this->post_info = isset($params['post_info']) ? (string)json_encode($params['post_info']) : null;
$this->sender_info = isset($params['sender_info']) ? (string)json_encode($params['sender_info']) : null;
-
+
// Message
$this->message = !empty($params['message']) ? serialize($params['message']) : null;
$this->example = !empty($params['example']) ? serialize($params['example']) : null;
-
+
// Feedback
$this->feedback = !empty($params['feedback']) ? $params['feedback'] : null;
-
+
}
}
diff --git a/cleantalk/lib/Cleantalk/ApbctUni/File/BTreeLeaf.php b/cleantalk/lib/Cleantalk/ApbctUni/File/BTreeLeaf.php
index 635a626..f32d319 100755
--- a/cleantalk/lib/Cleantalk/ApbctUni/File/BTreeLeaf.php
+++ b/cleantalk/lib/Cleantalk/ApbctUni/File/BTreeLeaf.php
@@ -3,7 +3,7 @@
namespace Cleantalk\ApbctUni\File;
class BTreeLeaf {
-
+
// Node structure
private $max_elems_in_node;
private $key_size;
@@ -36,26 +36,28 @@ class BTreeLeaf {
private $size;
private $stream;
-
+
+ private $root_link;
+
public function __construct( $params, $link_or_elems ) {
-
+
$this->stream = $params['stream'];
foreach ( $params as $param_name => $value ) {
$this->$param_name = $value;
}
-
+
if( is_array( $link_or_elems ) ){
$this->elements = $link_or_elems;
}else{
-
+
$this->link = $link_or_elems === '' ? $this->link_size : $link_or_elems;
// Set position to search
fseek($this->stream, $this->link );
-
+
// Read node
$raw_leaf = fread( $this->stream, $this->leaf_size );
@@ -65,7 +67,7 @@ public function __construct( $params, $link_or_elems ) {
}
public function insert( $key, $val, $link = '' ){
-
+
// Adding new element
$this->elements[] = array(
'key' => $key,
@@ -73,12 +75,12 @@ public function insert( $key, $val, $link = '' ){
'link' => $link,
);
$this->size++;
-
+
// Sorting elements by key
$keys = array_column( $this->elements, 'key' );
array_multisort( $keys, SORT_ASC, SORT_NUMERIC, $this->elements );
}
-
+
/**
* Searching for element in leaf using a key
*
@@ -106,59 +108,59 @@ public function searchForKey( $key_to_search )
// fwrite($myfile, json_encode($last_node));
// fwrite($myfile, PHP_EOL.PHP_EOL);
// fclose($myfile);
-
+
// Leaf is empty
if( $this->isEmpty() ){
$out = false;
-
+
// Leaf contains the exact key. Get all nodes with this key.
}elseif( in_array( $key_to_search, array_column( $this->elements, 'key' ) ) ){
$out = $this->getNodesByKey( $key_to_search );
-
+
// No key found in this leaf. Get link to correct child
// Check if it's on the right
}elseif( $key_to_search > $last_node->key && $last_node->link_right ){
$last_node->link = $last_node->link_right;
$out = array( $last_node );
-
+
// Check if it's on the left
}elseif( $key_to_search < $first_node->key && $this->link_left ){
$first_node->link = $this->link_left;
$out = array( $first_node );
-
+
// Get link from the middle
}else{
-
+
// Binary search
$top = $this->size - 1;
$bot = 0;
$position = 0;
while( $top >= $bot ){
-
+
$position = (int) floor( ( $top + $bot ) / 2 );
-
+
if( $this->elements[ $position ]['key'] < $key_to_search ){
$bot = $position + 1;
}elseif( $this->elements[ $position ]['key'] > $key_to_search ){
$top = $position - 1;
}
-
+
}
-
+
$node = new BTreeLeafNode( $this->elements[ $position ] );
-
+
$node->link = $node->key < $key_to_search
? $node->link_right
: $node->link_left;
-
+
$out = array( $node );
}
-
+
return isset( $out )
? $out
: false;
}
-
+
/**
* Get all elements with such key from the node
*
@@ -167,18 +169,18 @@ public function searchForKey( $key_to_search )
* @return false|array of BTreeLeafNode
*/
private function getNodesByKey( $key ){
-
+
$out = array();
-
+
foreach( $this->elements as $array_key => $element ){
if( $element['key'] == $key ){
$out[] = new BTreeLeafNode( $element );
}
}
-
+
return $out ?: false;
}
-
+
public function split(){
return array(
@@ -190,21 +192,21 @@ public function split(){
}
private function unserialize( $leaf__raw ){
-
+
if( strlen( $leaf__raw ) < $this->leaf_size )
return null;
-
+
// Get left link
$this->link_left = str_replace( "\x00", '', substr(
$leaf__raw, 0,
$this->link_size ) );
-
+
// Get left link
$this->link_parent = str_replace( "\x00", '', substr( $leaf__raw, $this->link_size, $this->link_size ) );
-
+
// Cut useless data
$leaf__raw = substr( $leaf__raw, $this->link_size * 2, strpos( $leaf__raw, $this->eod ) - $this->link_size * 2 );
-
+
// Get data from raw and write it to $this->node
$previous_link = $this->link_left;
while ( $leaf__raw )
@@ -221,7 +223,7 @@ private function unserialize( $leaf__raw ){
}
$this->size = $this->elements ? count( $this->elements ) : 0;
-
+
}
@@ -247,12 +249,12 @@ public function serialize( $raw = '' ){
return $raw;
}
-
+
public function save( $position = 0 ){
fseek( $this->stream, $this->link );
return fwrite( $this->stream, $this->serialize() );
}
-
+
public function isEmpty(){
return ! $this->elements;
}
@@ -263,5 +265,5 @@ public function isEmpty(){
public function getSize() {
return $this->size;
}
-
+
}
diff --git a/cleantalk/lib/Cleantalk/Common/File.php b/cleantalk/lib/Cleantalk/Common/File.php
index 1d76b82..c933012 100644
--- a/cleantalk/lib/Cleantalk/Common/File.php
+++ b/cleantalk/lib/Cleantalk/Common/File.php
@@ -10,7 +10,7 @@
* @package Cleantalk
*/
class File{
-
+
/**
* Removes content from file in tag
* Tags example:
@@ -29,7 +29,7 @@ public static function clean__tag( $file_path, $tag ){
? self::clean__pattern( $file_path, $pattern )
: Err::add( __CLASS__, __FUNCTION__, 'Pattern wrong', $pattern );
}
-
+
/**
* Removes variable from file
*
@@ -70,17 +70,17 @@ public static function clean__all( $file_path )
* @return bool| /Cleantalk/Err
*/
public static function clean__pattern( $file_path, $pattern ){
-
+
if( is_file( $file_path ) || is_writable( $file_path ) ){
-
+
$file_content = file_get_contents( $file_path );
-
+
if( $file_content ){
-
+
// Cleaning up
$new_content = preg_replace( '/' . $pattern . '/', '', $file_content, 1 );
$result = $new_content !== null ? true : false;
-
+
if($result){
if( file_put_contents( $file_path, $new_content, LOCK_EX ) ){
return true;
@@ -93,7 +93,7 @@ public static function clean__pattern( $file_path, $pattern ){
}else
return Err::add(__CLASS__, __FUNCTION__, 'No file'); // No template PHP file
}
-
+
public static function replace__variable( $file_path, $variable, $value, $serialized = false ){
if ($serialized) {
$value = serialize($value);
@@ -106,7 +106,14 @@ public static function replace__variable( $file_path, $variable, $value, $serial
static::replace__code( $file_path, $injection, $needle );
}
- public static function get__variable($file_path, $variable, $serialized = false)
+ /**
+ * @param $file_path
+ * @param $variable
+ * @param $serialized
+ * @return false|int|mixed|string
+ * todo use JSON to avoid serialization
+ */
+ public static function get__variable($file_path, $variable, $serialized = false)
{
if (!is_file($file_path)) {
return Err::add(__CLASS__, __FUNCTION__, 'File not found', $file_path); // No PHP file
@@ -121,9 +128,12 @@ public static function get__variable($file_path, $variable, $serialized = false)
if ($value_start === false) {
return false;
}
- $value_end = strpos($file_content, ';', $value_start);
+ $value_end = strpos($file_content, ';', $value_start);
if ($serialized) {
- $value_end = strpos($file_content, ';\n', $value_start);
+ $value_end = strpos($file_content, ";\r\n", $value_start);
+ if (!$value_end) {
+ $value_end = strpos($file_content, ";\n", $value_start);
+ }
}
$value = substr($file_content, $value_start + strlen($variable) + 4, $value_end - $value_start - strlen($variable) - 4);
$value = trim($value, " \t\n\r\0\x0B'\"\'");
@@ -138,20 +148,20 @@ public static function get__variable($file_path, $variable, $serialized = false)
return $value;
}
-
+
public static function replace__code( $file_path, $injection, $needle ){
-
+
if( is_file( $file_path ) ){
-
+
if( is_writable( $file_path ) ){
-
+
$file_content = file_get_contents( $file_path );
-
+
if( $file_content ){
-
+
$new_content = preg_replace("/$needle/", $injection, $file_content, 1);
$result = $new_content !== null ? true : false;
-
+
if($result){
if( $bytes = file_put_contents( $file_path, $new_content, LOCK_EX ) ){
return $bytes;
@@ -166,15 +176,15 @@ public static function replace__code( $file_path, $injection, $needle ){
}else
return Err::add(__CLASS__, __FUNCTION__, 'File not found', $file_path); // No PHP file
}
-
+
public static function inject__tag__start( $file_path, $tag ){
self::inject__code( $file_path, self::tag__php__start( $tag ) );
}
-
+
public static function inject__tag__end( $file_path, $tag ){
self::inject__code( $file_path, self::tag__php__end( $tag ) );
}
-
+
public static function inject__variable( $file_path, $variable, $value, $serialize = false, $compact = false ){
if ($serialize) {
$value = serialize($value);
@@ -183,21 +193,21 @@ public static function inject__variable( $file_path, $variable, $value, $seriali
$value = $compact ? preg_replace( '/\s*/', '', $value ) : $value;
self::inject__code( $file_path, "\$$variable = $value;" );
}
-
+
public static function inject__code( $file_path, $injection, $needle = '<\?php', $tag = null ){
-
+
if( is_file( $file_path ) ){
-
+
if( is_writable( $file_path ) ){
-
+
$file_content = file_get_contents( $file_path );
-
+
if( $file_content ){
-
+
$replacement = $tag
? self::tag__php__start( $tag ) . PHP_EOL . $injection . PHP_EOL . self::tag__php__end( $tag )
: $injection;
-
+
switch ($needle){
case 'start':
$new_content = $replacement . $file_content;
@@ -208,7 +218,7 @@ public static function inject__code( $file_path, $injection, $needle = '<\?php',
default:
$new_content = preg_replace("/$needle/", "$0" . PHP_EOL . $replacement, $file_content, 1);
}
-
+
$result = $new_content !== null && $new_content != $file_content ? true : false;
if($result){
if( file_put_contents( $file_path, $new_content, LOCK_EX ) ){
@@ -224,11 +234,11 @@ public static function inject__code( $file_path, $injection, $needle = '<\?php',
}else
return Err::add(__CLASS__, __FUNCTION__, 'File not found', $file_path); // No PHP file
}
-
+
public static function tag__php__start( $tag ){
return "\n//Cleantalk/$tag/start";
}
-
+
public static function tag__php__end( $tag ){
return "\n//Cleantalk/$tag/end";
}
@@ -319,4 +329,4 @@ public static function delete( $path, $exceptions = array() ){
public static function isFolderEmpty( $path ){
return ! count( glob( $path . '/*' ) );
}
-}
\ No newline at end of file
+}
diff --git a/cleantalk/lib/Cleantalk/Common/Helper.php b/cleantalk/lib/Cleantalk/Common/Helper.php
index 0b08980..c580388 100644
--- a/cleantalk/lib/Cleantalk/Common/Helper.php
+++ b/cleantalk/lib/Cleantalk/Common/Helper.php
@@ -541,11 +541,19 @@ static public function http__request($url, $data = array(), $presets = null, $op
break;
case 'get':
- $opts[ CURLOPT_URL ] .= $data ? '?' . str_replace( "&", "&", http_build_query( $data ) ) : '';
- $opts[CURLOPT_POST] = false;
- $opts[CURLOPT_POSTFIELDS] = null;
+ try {
+ $data = is_string($data) ? json_decode($data, true, 512, JSON_THROW_ON_ERROR) : $data;
+ } catch (\JsonException) {
+ $data = false;
+ }
+ if (is_array($data)) {
+ $opts[ CURLOPT_URL ] .= $data ? '?' . str_replace( "&", "&", http_build_query( $data ) ) : '';
+ $opts[CURLOPT_POST] = false;
+ $opts[CURLOPT_POSTFIELDS] = null;
+ } else {
+ return array('error' => 'CURL. Preparing GET request: data param is not valid.');
+ }
break;
-
case 'ssl':
$opts[CURLOPT_SSL_VERIFYPEER] = true;
$opts[CURLOPT_SSL_VERIFYHOST] = 2;
@@ -603,16 +611,30 @@ static public function http__request($url, $data = array(), $presets = null, $op
$result = (int) preg_replace( '/.*(\d{3}).*/', '$1', $headers[0] );
// Making common request
- }else{
- $opts = array(
- 'http' => array(
- 'method' => in_array( 'get', $presets ) ? 'GET' : 'POST',
- 'timeout' => 5,
- 'content' => str_replace( "&", "&", http_build_query( $data ) ),
- ),
- );
- $context = stream_context_create( $opts );
- $result = @file_get_contents( $url, 0, $context );
+ } else {
+ $method = in_array( 'get', $presets ) ? 'GET' : 'POST';
+ if ($method === 'GET') {
+ try {
+ $data = is_string($data) ? json_decode($data, true, 512, JSON_THROW_ON_ERROR) : $data;
+ $data = str_replace( "&", "&", http_build_query( $data ) );
+ } catch (\JsonException) {
+ $data = false;
+ }
+ }
+
+ if (is_string($data)) {
+ $opts = array(
+ 'http' => array(
+ 'method' => $method,
+ 'timeout' => 5,
+ 'content' => $data,
+ ),
+ );
+ $context = stream_context_create( $opts );
+ $result = @file_get_contents( $url, 0, $context );
+ } else {
+ return array('error' => 'No CURL. Preparing GET request: data param is not valid.');
+ }
}
$out = $result === false
diff --git a/cleantalk/settings.php b/cleantalk/settings.php
index c10c333..c6b6f0f 100644
--- a/cleantalk/settings.php
+++ b/cleantalk/settings.php
@@ -98,9 +98,26 @@
File::replace__variable( $path_to_config, 'registrations_test', (bool)Post::get( 'registrations_test' ) );
File::replace__variable( $path_to_config, 'general_postdata_test', (bool)Post::get( 'general_postdata_test' ) );
File::replace__variable( $path_to_config, 'spam_firewall', (bool)Post::get( 'spam_firewall' ) );
- File::replace__variable( $path_to_config, 'general_post_exclusion_usage', (bool)Post::get( 'general_post_exclusion_usage' ) );
+ File::replace__variable( $path_to_config, 'service_field_in_post_exclusion_enabled', (bool)Post::get( 'service_field_in_post_exclusion_enabled' ) );
- // SFW actions
+ // form post sign exclusions
+ $form_post_exclusions_enabled = (bool)Post::get('form_post_exclusions_enabled');
+ $form_post_signs_exclusions_string = Post::get('form_post_exclusions_signs_string');
+
+ if ($form_post_exclusions_enabled && $form_post_signs_exclusions_string) {
+ $form_post_signs_exclusions_set = apbct_settings__sanitize__exclusions($form_post_signs_exclusions_string, true);
+ if (!$form_post_signs_exclusions_set || !is_array($form_post_signs_exclusions_set)) {
+ die(Err::add('Exclusion regexp is not valid.')->get_last( 'as_json' ));
+ }
+ File::replace__variable( $path_to_config, 'form_post_signs_exclusions_set', $form_post_signs_exclusions_set );
+ File::replace__variable( $path_to_config, 'form_post_exclusions_enabled', $form_post_exclusions_enabled );
+ } else {
+ File::replace__variable( $path_to_config, 'form_post_exclusions_enabled', false );
+ }
+
+ /**
+ * SFW actions
+ */
if( Post::get( 'spam_firewall' ) && $apikey ){
$sfw = new SFW();
@@ -120,8 +137,9 @@
Err::check() or die(json_encode(array('success' => true)));
die(Err::check_and_output( 'as_json' ));
- }else
+ } else {
die(Err::add('Forbidden')->get_last( 'as_json' ));
+ }
break;
case 'serve_run_cron_sfw_update':
@@ -282,37 +300,55 @@
>
Account registered for email:
Add the tag below to the form that needs to be excluded. Set unique "id" attribute if you have several forms on the same page:
-Statistics