BxAntispamModuleTest.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. <?php
  2. use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations;
  3. use PHPUnit\Framework\Attributes\DataProvider;
  4. use PHPUnit\Framework\Attributes\PreserveGlobalState;
  5. use PHPUnit\Framework\Attributes\RunInSeparateProcess;
  6. /**
  7. * Test Antispam module
  8. */
  9. #[AllowMockObjectsWithoutExpectations]
  10. class BxAntispamModuleTest extends BxDolTestCase
  11. {
  12. protected $_sSampleEmail = 'some@email.com';
  13. protected $_sSampleIP = '0.0.0.0';
  14. protected $_oModule;
  15. protected $_oMockIP;
  16. protected $_oMockDNSBlacklists;
  17. protected $_oMockDNSURIBlacklists;
  18. protected $_oMockStopForumSpam;
  19. protected $_oMockAkismet;
  20. protected function setUp(): void
  21. {
  22. $this->_oModule = $this->bxRequireAntispam();
  23. $this->_oMockIP = $this->bxMockGet('BxAntispamIP', $this->_oModule->_aModule);
  24. $this->_oMockDNSBlacklists = $this->bxMockGet('BxAntispamDNSBlacklists', $this->_oModule->_aModule, true);
  25. $this->_oMockDNSURIBlacklists = $this->bxMockGet('BxAntispamDNSURIBlacklists', $this->_oModule->_aModule, true);
  26. $this->_oMockStopForumSpam = $this->bxMockGet('BxAntispamStopForumSpam', $this->_oModule->_aModule);
  27. $this->_oMockAkismet = $this->bxMockGet('BxAntispamAkismet', $this->_oModule->_aModule);
  28. }
  29. protected function tearDown(): void
  30. {
  31. if ($this->_oMockIP)
  32. $this->bxMockFree($this->_oMockIP);
  33. if ($this->_oMockDNSBlacklists)
  34. $this->bxMockFree($this->_oMockDNSBlacklists);
  35. if ($this->_oMockDNSURIBlacklists)
  36. $this->bxMockFree($this->_oMockDNSURIBlacklists);
  37. if ($this->_oMockStopForumSpam)
  38. $this->bxMockFree($this->_oMockStopForumSpam);
  39. if ($this->_oMockAkismet)
  40. $this->bxMockFree($this->_oMockAkismet);
  41. if ($this->_oModule && $this->_oModule->_oConfig)
  42. $this->_oModule->_oConfig->restoreAntispamOptions();
  43. }
  44. static public function providerForServiceIsSpam()
  45. {
  46. $any = null;//'ANY';
  47. return array(
  48. array(true, $any, $any, $any, $any, $any, $any, false), // no spam detection for admin account
  49. // array(false, true, $any, $any, $any, $any, $any, false), // no spam detection for whitelisted IP
  50. // array(false, false, 'on', false, $any, $any, 'on', false), // no spam detection if not listed in URIDNSBL (in "blocking" mode)
  51. // array(false, false, 'on', true, $any, $any, 'on', true), // it is spam if listed in URIDNSBL (in "blocking" mode)
  52. // array(false, false, '', $any, 'on', false, 'on', false), // no spam detection if not listed in Akismet (in "blocking" mode)
  53. // array(false, false, '', $any, 'on', true, 'on', true), // it is spam if listed in Akismet (in "blocking" mode)
  54. // array(false, false, 'on', true, 'on', true, '', false), // no spam detection in URIDNSBL nor Akismet if not in "blocking" mode
  55. );
  56. }
  57. #[DataProvider('providerForServiceIsSpam')]
  58. public function testServiceIsSpam($isAdmin, $bIpWhitelisted, $sUriDnsblEnable, $bUriDnsblBlacklisted, $sAkismetlEnable, $bAkismetBlacklisted, $sBlock, $bRes)
  59. {
  60. $this->_oModule->_oConfig->setAntispamOption('antispam_report', ''); // turn off reporting during testing
  61. $this->_oModule->_oConfig->setAntispamOption('uridnsbl_enable', $sUriDnsblEnable);
  62. $this->_oModule->_oConfig->setAntispamOption('akismet_enable', $sAkismetlEnable);
  63. $this->_oModule->_oConfig->setAntispamOption('antispam_block', $sBlock);
  64. $GLOBALS['logged']['admin'] = $isAdmin;
  65. if ($isAdmin) { // if admin no futher call are performed
  66. $this->_oMockIP->expects($this->never())->method('isIpWhitelisted');
  67. $this->_oMockDNSURIBlacklists->expects($this->never())->method('isSpam');
  68. $this->_oMockAkismet->expects($this->never())->method('isSpam');
  69. } else { // if not admin then check for whitelisting
  70. $this->_oMockIP->expects($this->once())->method('isIpWhitelisted')
  71. ->willReturn($bIpWhitelisted);
  72. }
  73. if ('on' != $sUriDnsblEnable || $isAdmin || $bIpWhitelisted) { // don't check in DNDBL if anything is true
  74. $this->_oMockDNSURIBlacklists->expects($this->never())->method('isSpam');
  75. } else { // check in URIDNSBL if URIDNSBL is enabled, not admin and IP is not whitelisted
  76. $this->_oMockDNSURIBlacklists->expects($this->once())->method('isSpam')
  77. ->willReturn($bUriDnsblBlacklisted);
  78. }
  79. if ('on' != $sAkismetlEnable || $isAdmin || $bIpWhitelisted || ($bUriDnsblBlacklisted && $sUriDnsblEnable)) { // don't check in Akismet if anything is true
  80. $this->_oMockAkismet->expects($this->never())->method('isSpam');
  81. } else { // check in Akismet if Akismet is enabled, not admin, IP is not whitelisted and not previouslu detected in DNSBL
  82. $this->_oMockAkismet->expects($this->once())->method('isSpam')
  83. ->willReturn($bAkismetBlacklisted);
  84. }
  85. // check result boolean value
  86. $sContent = 'test';
  87. $this->assertEquals($bRes, $this->_oModule->serviceIsSpam($sContent, $this->_sSampleIP));
  88. }
  89. static public function providerForServiceCheckJoin()
  90. {
  91. $any = null;//'ANY';
  92. return array(
  93. array(true, $any, $any, $any, $any, false, false), // join is NOT allowed for blocked IPs
  94. array(false, '', $any, $any, false, false, true), // join is allowed if IP isn't blocked, DNSBL checking disabled, not listed in StopForumSpam
  95. array(false, 'on', 'approval', false, false, false, true), // join is allowed if IP isn't blocked and DNSBL enabled in "approval" mode, but not listed
  96. array(false, 'on', 'block', false, false, false, true), // join is allowed if IP isn't blocked and DNSBL enabled in "block", but not listed
  97. // array(false, 'on', 'approval', true, false, true, true), // join is allowed if IP isn't blocked and DNSBL enabled in "approval" and IP listed
  98. // array(false, 'on', 'block', true, $any, false, false), // join is NOT allowed if IP isn't blocked and DNSBL enabled in "block" and IP listed
  99. array(false, '', $any, $any, true, false, false), // join is NOT allowed if IP isn't blocked but listed in StopForumSpam
  100. );
  101. }
  102. #[RunInSeparateProcess]
  103. #[PreserveGlobalState(false)]
  104. #[DataProvider('providerForServiceCheckJoin')]
  105. public function testServiceCheckJoin($bIpBlocked, $sDnsblEnable, $sDnsblBehaviour, $bDnsblIpBlacklisted, $bStopForumSpamSpammer, $bResultSetApprove, $bResultEmptyString)
  106. {
  107. // save exception handler
  108. $previousHandler = set_exception_handler(function () {});
  109. try {
  110. // set different options
  111. $this->_oModule->_oConfig->setAntispamOption('dnsbl_enable', $sDnsblEnable);
  112. $this->_oModule->_oConfig->setAntispamOption('dnsbl_behaviour_join', $sDnsblBehaviour);
  113. // first IP address block checking is called
  114. $this->_oMockIP->expects($this->once())->method('isIpBlocked')
  115. ->with($this->equalTo($this->_sSampleIP))
  116. ->willReturn($bIpBlocked);
  117. if ($bIpBlocked) { // if ip is blocked no other methods should be called
  118. $this->_oMockDNSBlacklists->expects($this->never())->method('dnsbl_lookup_ip');
  119. $this->_oMockStopForumSpam->expects($this->never())->method('isSpammer');
  120. } elseif (!$bIpBlocked) { // if ip is NOT blocked - perform further checks
  121. if ('on' != $sDnsblEnable) { // DNSBL shouldn't be called if it isn't enabled
  122. $this->_oMockDNSBlacklists->expects($this->never())->method('dnsbl_lookup_ip');
  123. } elseif ('on' == $sDnsblEnable) {
  124. /*
  125. $this->_oMockDNSBlacklists->expects($this->at(0))->method('dnsbl_lookup_ip')
  126. ->with($this->equalTo(BX_DOL_DNSBL_CHAIN_SPAMMERS), $this->equalTo($this->_sSampleIP))
  127. ->will($this->returnValue($bDnsblIpBlacklisted ? BX_DOL_DNSBL_POSITIVE : BX_DOL_DNSBL_NEGATIVE));
  128. */
  129. $this->_oMockDNSBlacklists->expects($this->atLeastOnce())->method('dnsbl_lookup_ip');
  130. }
  131. if ('on' == $sDnsblEnable && $bDnsblIpBlacklisted && 'block' == $sDnsblBehaviour) { // StopForumSpam shouldn't be called if DNSBL detected spam
  132. $this->_oMockStopForumSpam->expects($this->never())->method('isSpammer');
  133. } else {
  134. $this->_oMockStopForumSpam->expects($this->once())->method('isSpammer')
  135. ->willReturn($bStopForumSpamSpammer);
  136. }
  137. }
  138. // empty string - no spam detected
  139. $bSetApprove = false;
  140. $this->assertTrue($bResultEmptyString == ('' == $this->_oModule->serviceCheckJoin($this->_sSampleEmail, $bSetApprove, $this->_sSampleIP)));
  141. $this->assertTrue($bResultSetApprove == $bSetApprove);
  142. } finally {
  143. // restore exception handler
  144. set_exception_handler($previousHandler);
  145. }
  146. }
  147. static public function providerForServiceCheckLogin()
  148. {
  149. $any = null;//'ANY';
  150. return array(
  151. array(true, $any, $any, $any, false),
  152. array(false, false, $any, $any, true),
  153. array(false, true, 'log', false, true),
  154. array(false, true, 'block', false, true),
  155. array(false, true, 'log', true, true),
  156. // array(false, true, 'block', true, false),
  157. );
  158. }
  159. #[RunInSeparateProcess]
  160. #[PreserveGlobalState(false)]
  161. #[DataProvider('providerForServiceCheckLogin')]
  162. public function testServiceCheckLogin($bIpBlocked, $sDnsblEnable, $sDnsblBehaviour, $bDnsblIpBlacklisted, $bResultEmptyString)
  163. {
  164. // set different options
  165. $this->_oModule->_oConfig->setAntispamOption('dnsbl_enable', $sDnsblEnable);
  166. $this->_oModule->_oConfig->setAntispamOption('dnsbl_behaviour_login', $sDnsblBehaviour);
  167. // first IP address block checking is called
  168. $this->_oMockIP->expects($this->once())->method('isIpBlocked')
  169. ->willReturn($bIpBlocked);
  170. if ($bIpBlocked || 'on' != $sDnsblEnable) { // if ip is blocked, or DNSBL isn't enabled - DNSBL checking shouldn't be called
  171. $this->_oMockDNSBlacklists->expects($this->never())->method('dnsbl_lookup_ip');
  172. } elseif (!$bIpBlocked && 'on' == $sDnsblEnable) { // call DNSBL checking only if enabled and IP isn't already blocked
  173. /*
  174. $this->_oMockDNSBlacklists->expects($this->at(0))->method('dnsbl_lookup_ip')
  175. ->with($this->equalTo(BX_DOL_DNSBL_CHAIN_SPAMMERS), $this->_sSampleIP)
  176. ->will($this->returnValue($bDnsblIpBlacklisted ? BX_DOL_DNSBL_POSITIVE : BX_DOL_DNSBL_NEGATIVE));
  177. */
  178. $this->_oMockDNSBlacklists->expects($this->atLeastOnce())->method('dnsbl_lookup_ip');
  179. }
  180. // empty string - no spam detected
  181. $this->assertTrue($bResultEmptyString == ('' == $this->_oModule->serviceCheckLogin($this->_sSampleIP)));
  182. }
  183. static public function providerForServiceIsIpDnsBlacklisted()
  184. {
  185. return array(
  186. array(false, false, false),
  187. //array(true, false, true),
  188. //array(true, true, false),
  189. array(false, true, false),
  190. );
  191. }
  192. #[DataProvider('providerForServiceIsIpDnsBlacklisted')]
  193. public function testServiceIsIpDnsBlacklisted($bDnsblSpammer, $bDnsblWhitelisted, $bRes)
  194. {
  195. // check of whitelisting should be called once
  196. $this->_oMockIP->expects($this->once())->method('isIpWhitelisted')
  197. ->with($this->equalTo($this->_sSampleIP))
  198. ->willReturn(false);
  199. /*
  200. // check in 'spammers' chain
  201. $this->_oMockDNSBlacklists->expects($this->at(0))->method('dnsbl_lookup_ip')
  202. ->with($this->equalTo(BX_DOL_DNSBL_CHAIN_SPAMMERS), $this->equalTo($this->_sSampleIP))
  203. ->will($this->returnValue($bDnsblSpammer ? BX_DOL_DNSBL_POSITIVE : BX_DOL_DNSBL_NEGATIVE));
  204. if ($bDnsblSpammer) { // if found in 'spammers' chain, then check if it is whitelisted in 'whitelist' chain
  205. $this->_oMockDNSBlacklists->expects($this->at(1))->method('dnsbl_lookup_ip')
  206. ->with($this->equalTo(BX_DOL_DNSBL_CHAIN_WHITELIST), $this->equalTo($this->_sSampleIP))
  207. ->will($this->returnValue($bDnsblWhitelisted ? BX_DOL_DNSBL_POSITIVE : BX_DOL_DNSBL_NEGATIVE));
  208. }
  209. */
  210. $this->_oMockDNSBlacklists
  211. ->expects($this->exactly($bDnsblSpammer ? 2 : 1))
  212. ->method('dnsbl_lookup_ip');
  213. // check result boolean value
  214. $this->assertEquals($bRes, $this->_oModule->serviceIsIpDnsBlacklisted($this->_sSampleIP));
  215. }
  216. public function testServiceIsIpDnsBlacklistedWhenIpIsWhiletisted()
  217. {
  218. $this->_oMockIP->expects($this->once())->method('isIpWhitelisted')
  219. ->willReturn(true);
  220. $this->_oMockDNSBlacklists->expects($this->never())->method('dnsbl_lookup_ip');
  221. $this->assertEquals(false, $this->_oModule->serviceIsIpDnsBlacklisted($this->_sSampleIP));
  222. }
  223. public function testServiceIsIpWhitelisted()
  224. {
  225. $this->_oMockIP->expects($this->once())->method('isIpWhitelisted');
  226. $this->_oModule->serviceIsIpWhitelisted($this->_sSampleIP);
  227. }
  228. public function testServiceIsIpBlocked()
  229. {
  230. $this->_oMockIP->expects($this->once())->method('isIpBlocked');
  231. $this->_oModule->serviceIsIpBlocked($this->_sSampleIP);
  232. }
  233. public function testServiceBlockIp()
  234. {
  235. $this->_oMockIP->expects($this->once())->method('blockIp');
  236. $this->_oModule->serviceBlockIp($this->_sSampleIP);
  237. }
  238. }