Skip to content

Commit bd41dba

Browse files
authored
Upd. Settings. Updated flow to check pingback. (#764) (#773)
* Upd. Settings. Updated flow to check pingback. (#764) * Upd. Settings. Updated flow to check pingback. * upd structure * Upd. Code. Add test. * ci: rerun checks * try run test * try run test * add test
1 parent 2072165 commit bd41dba

3 files changed

Lines changed: 276 additions & 29 deletions

File tree

.github/workflows/tests.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ on: # event list
1111
branches:
1212
- dev
1313
- master
14+
- '**'
1415

1516
env: # environment variables (available in any part of the action)
1617
PHP_VERSION: 7.4

lib/Cleantalk/Antispam/Integrations/CleantalkPreprocessComment.php

Lines changed: 33 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -445,37 +445,41 @@ private function doSkipReason($current_user, $ct_comment_done)
445445
return __FILE__ . ' -> ' . __FUNCTION__ . '():' . __LINE__;
446446
}
447447

448-
//do not hadle trackbacks on exclusions
449-
if ($this->wp_comment['comment_type'] !== 'trackback') {
450-
/**
451-
* Process main ruleset
452-
*/
453-
if (
454-
apbct_is_user_enable() === false ||
455-
$this->apbct->settings['forms__comments_test'] == 0 ||
456-
$ct_comment_done ||
457-
(isset($_SERVER['HTTP_REFERER']) && stripos($_SERVER['HTTP_REFERER'], 'page=wysija_campaigns&action=editTemplate') !== false) ||
458-
(isset($_SERVER['REQUEST_URI']) && strpos($_SERVER['REQUEST_URI'], '/wp-admin/') !== false)
459-
) {
460-
return __FILE__ . ' -> ' . __FUNCTION__ . '():' . __LINE__;
461-
}
448+
$comment_type = isset($this->wp_comment['comment_type']) ? $this->wp_comment['comment_type'] : 'comment';
462449

463-
/**
464-
* Check if wordpress integrated words/chars blacklists.
465-
*/
466-
$wordpress_own_string_blacklists_result = apbct_wp_blacklist_check(
467-
$this->wp_comment['comment_author'],
468-
$this->wp_comment['comment_author_email'],
469-
$this->wp_comment['comment_author_url'],
470-
$this->wp_comment['comment_content'],
471-
Server::get('REMOTE_ADDR'),
472-
Server::get('HTTP_USER_AGENT')
473-
);
450+
// Pingbacks and trackbacks are link notifications, not visitor form comments — no cloud check.
451+
if ( in_array($comment_type, array('pingback', 'trackback'), true) ) {
452+
return __FILE__ . ' -> ' . __FUNCTION__ . '():' . __LINE__;
453+
}
474454

475-
// Go out if author in local blacklists, already stopped
476-
if ( $wordpress_own_string_blacklists_result === true ) {
477-
return __FILE__ . ' -> ' . __FUNCTION__ . '():' . __LINE__;
478-
}
455+
/**
456+
* Process main ruleset
457+
*/
458+
if (
459+
apbct_is_user_enable() === false ||
460+
$this->apbct->settings['forms__comments_test'] == 0 ||
461+
$ct_comment_done ||
462+
(isset($_SERVER['HTTP_REFERER']) && stripos($_SERVER['HTTP_REFERER'], 'page=wysija_campaigns&action=editTemplate') !== false) ||
463+
(isset($_SERVER['REQUEST_URI']) && strpos($_SERVER['REQUEST_URI'], '/wp-admin/') !== false)
464+
) {
465+
return __FILE__ . ' -> ' . __FUNCTION__ . '():' . __LINE__;
466+
}
467+
468+
/**
469+
* Check if wordpress integrated words/chars blacklists.
470+
*/
471+
$wordpress_own_string_blacklists_result = apbct_wp_blacklist_check(
472+
$this->wp_comment['comment_author'],
473+
$this->wp_comment['comment_author_email'],
474+
$this->wp_comment['comment_author_url'],
475+
$this->wp_comment['comment_content'],
476+
Server::get('REMOTE_ADDR'),
477+
Server::get('HTTP_USER_AGENT')
478+
);
479+
480+
// Go out if author in local blacklists, already stopped
481+
if ( $wordpress_own_string_blacklists_result === true ) {
482+
return __FILE__ . ' -> ' . __FUNCTION__ . '():' . __LINE__;
479483
}
480484

481485
return false;
Lines changed: 242 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,242 @@
1+
<?php
2+
3+
namespace Cleantalk\Antispam\Integrations;
4+
5+
use PHPUnit\Framework\TestCase;
6+
7+
/**
8+
* Covers skip rules for pingback/trackback in preprocess comment flow (see PR #764 / #773).
9+
*/
10+
class TestCleantalkPreprocessComment extends TestCase
11+
{
12+
/**
13+
* @var mixed
14+
*/
15+
private $savedCurrentUser;
16+
/**
17+
* @var string
18+
*/
19+
private $savedDisallowedKeys;
20+
21+
protected function setUp(): void
22+
{
23+
parent::setUp();
24+
global $current_user;
25+
$this->savedCurrentUser = isset($current_user) ? $current_user : null;
26+
$this->savedDisallowedKeys = (string) get_option('disallowed_keys', '');
27+
}
28+
29+
protected function tearDown(): void
30+
{
31+
global $current_user;
32+
$current_user = $this->savedCurrentUser;
33+
if (function_exists('wp_set_current_user')) {
34+
wp_set_current_user(0);
35+
}
36+
update_option('disallowed_keys', $this->savedDisallowedKeys);
37+
parent::tearDown();
38+
}
39+
40+
/**
41+
* @return \stdClass
42+
*/
43+
private function makeSubscriberUser()
44+
{
45+
$subscriber = new \stdClass();
46+
$subscriber->ID = 91234;
47+
$subscriber->roles = array('subscriber');
48+
$subscriber->caps = array('subscriber' => true);
49+
50+
return $subscriber;
51+
}
52+
53+
/**
54+
* @param array<string, mixed> $wp_comment
55+
* @param object $current_user
56+
* @param bool $ct_comment_done
57+
* @param object|null $apbct
58+
*
59+
* @return mixed
60+
*/
61+
private function invokeDoSkipReason(array $wp_comment, $current_user, $ct_comment_done = false, $apbct = null)
62+
{
63+
$integration = new CleantalkPreprocessComment();
64+
$reflection = new \ReflectionClass($integration);
65+
66+
$wp_comment_prop = $reflection->getProperty('wp_comment');
67+
$wp_comment_prop->setAccessible(true);
68+
$wp_comment_prop->setValue($integration, $wp_comment);
69+
70+
if ($apbct !== null) {
71+
$apbct_prop = $reflection->getProperty('apbct');
72+
$apbct_prop->setAccessible(true);
73+
$apbct_prop->setValue($integration, $apbct);
74+
}
75+
76+
$method = $reflection->getMethod('doSkipReason');
77+
$method->setAccessible(true);
78+
79+
return $method->invoke($integration, $current_user, $ct_comment_done);
80+
}
81+
82+
public function testDoSkipReasonSkipsAdministratorBeforePingbackHandling(): void
83+
{
84+
$user = new \stdClass();
85+
$user->roles = array('administrator');
86+
87+
$result = $this->invokeDoSkipReason(
88+
array(
89+
'comment_type' => 'pingback',
90+
'comment_post_ID' => 1,
91+
),
92+
$user
93+
);
94+
95+
$this->assertNotFalse($result);
96+
$this->assertStringContainsString('doSkipReason', $result);
97+
}
98+
99+
public function testDoSkipReasonSkipsPingback(): void
100+
{
101+
$user = new \stdClass();
102+
$user->roles = array('subscriber');
103+
104+
$result = $this->invokeDoSkipReason(
105+
array(
106+
'comment_type' => 'pingback',
107+
'comment_post_ID' => 1,
108+
),
109+
$user
110+
);
111+
112+
$this->assertNotFalse($result);
113+
$this->assertStringContainsString('doSkipReason', $result);
114+
}
115+
116+
public function testDoSkipReasonSkipsTrackback(): void
117+
{
118+
$user = new \stdClass();
119+
$user->roles = array('subscriber');
120+
121+
$result = $this->invokeDoSkipReason(
122+
array(
123+
'comment_type' => 'trackback',
124+
'comment_post_ID' => 1,
125+
),
126+
$user
127+
);
128+
129+
$this->assertNotFalse($result);
130+
$this->assertStringContainsString('doSkipReason', $result);
131+
}
132+
133+
/**
134+
* Missing comment_type must default to "comment" and continue into the main ruleset (not pingback skip).
135+
*/
136+
public function testDoSkipReasonDefaultsMissingCommentTypeToComment(): void
137+
{
138+
global $current_user;
139+
$subscriber = $this->makeSubscriberUser();
140+
$current_user = $subscriber;
141+
142+
$apbct = (object) array(
143+
'settings' => array(
144+
'forms__comments_test' => 0,
145+
),
146+
);
147+
148+
$wp_comment = array(
149+
'comment_post_ID' => 1,
150+
);
151+
152+
$result = $this->invokeDoSkipReason($wp_comment, $subscriber, false, $apbct);
153+
154+
$this->assertNotFalse($result);
155+
$this->assertStringContainsString('doSkipReason', $result);
156+
}
157+
158+
public function testDoSkipReasonSkipsWhenCommentAlreadyHandled(): void
159+
{
160+
global $current_user;
161+
$subscriber = $this->makeSubscriberUser();
162+
$current_user = $subscriber;
163+
164+
$apbct = (object) array(
165+
'settings' => array(
166+
'forms__comments_test' => 1,
167+
),
168+
);
169+
170+
$wp_comment = array(
171+
'comment_type' => 'comment',
172+
'comment_post_ID' => 1,
173+
'comment_author' => 'John',
174+
'comment_author_email' => 'john@example.com',
175+
'comment_author_url' => 'https://example.com',
176+
'comment_content' => 'Regular text',
177+
);
178+
179+
$result = $this->invokeDoSkipReason($wp_comment, $subscriber, true, $apbct);
180+
181+
$this->assertNotFalse($result);
182+
$this->assertStringContainsString('doSkipReason', $result);
183+
}
184+
185+
public function testDoSkipReasonReturnsFalseForRegularCommentWithoutBlacklistedContent(): void
186+
{
187+
global $current_user;
188+
$subscriber = $this->makeSubscriberUser();
189+
$current_user = $subscriber;
190+
191+
update_option('disallowed_keys', 'forbidden-keyword-that-is-not-used');
192+
193+
$apbct = (object) array(
194+
'settings' => array(
195+
'forms__comments_test' => 1,
196+
),
197+
);
198+
199+
$wp_comment = array(
200+
'comment_type' => 'comment',
201+
'comment_post_ID' => 1,
202+
'comment_author' => 'John',
203+
'comment_author_email' => 'john@example.com',
204+
'comment_author_url' => 'https://example.com',
205+
'comment_content' => 'Absolutely clean content',
206+
);
207+
208+
$result = $this->invokeDoSkipReason($wp_comment, $subscriber, false, $apbct);
209+
210+
$this->assertFalse($result);
211+
}
212+
213+
public function testDoSkipReasonSkipsWhenWordPressBlacklistMatches(): void
214+
{
215+
global $current_user;
216+
$subscriber = $this->makeSubscriberUser();
217+
$current_user = $subscriber;
218+
219+
update_option('disallowed_keys', 'blacklisted-fragment');
220+
221+
$apbct = (object) array(
222+
'settings' => array(
223+
'forms__comments_test' => 1,
224+
),
225+
);
226+
227+
$wp_comment = array(
228+
'comment_type' => 'comment',
229+
'comment_post_ID' => 1,
230+
'comment_author' => 'John',
231+
'comment_author_email' => 'john@example.com',
232+
'comment_author_url' => 'https://example.com',
233+
'comment_content' => 'Message contains blacklisted-fragment inside',
234+
);
235+
236+
$result = $this->invokeDoSkipReason($wp_comment, $subscriber, false, $apbct);
237+
238+
$this->assertNotFalse($result);
239+
$this->assertStringContainsString('doSkipReason', $result);
240+
}
241+
}
242+

0 commit comments

Comments
 (0)