BxAntispamDNSURIBlacklists.php 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. <?php defined('BX_DOL') or die('hack attempt');
  2. /**
  3. * Copyright (c) BoonEx Pty Limited - http://www.boonex.com/
  4. * CC-BY License - http://creativecommons.org/licenses/by/3.0/
  5. *
  6. * @defgroup Antispam Antispam
  7. * @ingroup TridentModules
  8. *
  9. * @{
  10. */
  11. /**
  12. * Spam detection based on URIs in the message
  13. */
  14. class BxAntispamDNSURIBlacklists extends BxDol
  15. {
  16. protected $aZonesUrls = array (
  17. 2 => "http://www.surbl.org/tld/two-level-tlds",
  18. 3 => "http://www.surbl.org/tld/three-level-tlds",
  19. );
  20. protected $oDb;
  21. /**
  22. * Constructor
  23. */
  24. public function __construct()
  25. {
  26. parent::__construct();
  27. $this->aZonesUrls = array ( // for some reason original urls are restricted to fetch, so copies are created locally
  28. 2 => BX_DIRECTORY_PATH_MODULES . "boonex/antispam/data/two-level-tlds",
  29. 3 => BX_DIRECTORY_PATH_MODULES . "boonex/antispam/data/three-level-tlds",
  30. );
  31. $this->oDb = BxDolDb::getInstance();;
  32. $this->initZones();
  33. }
  34. public function isSpam ($s)
  35. {
  36. $aURIs = $this->parseUrls ($s);
  37. if (!$aURIs)
  38. return false;
  39. $aURIs = $this->validateUrls ($aURIs);
  40. if (!$aURIs)
  41. return false;
  42. $oModule = BxDolModule::getInstance('bx_antispam');
  43. $o = bx_instance('BxAntispamDNSBlacklists', array(), $oModule->_aModule);
  44. foreach ($aURIs as $sURI) {
  45. if (BX_DOL_DNSBL_POSITIVE == $o->dnsbl_lookup_uri ($sURI))
  46. return true;
  47. }
  48. return false;
  49. }
  50. public function parseUrls (&$s)
  51. {
  52. $aMatches = array ();
  53. if (!preg_match_all("!(https?|ftp|gopher|telnet|file|notes|ms-help):[/\\\\]+([\w\d\.-]*)!", $s, $aMatches))
  54. return false;
  55. if (!$aMatches || !isset($aMatches[2]) || !$aMatches[2])
  56. return false;
  57. $aUrlsUniq = array ();
  58. foreach ($aMatches[2] as $sUrl) {
  59. if (isset($aUrlsUniq[$sUrl]))
  60. continue;
  61. $aUrlsUniq[$sUrl] = $sUrl;
  62. }
  63. return $aUrlsUniq;
  64. }
  65. public function validateUrls ($aUrlsUniq)
  66. {
  67. $aUrls = array ();
  68. foreach ($aUrlsUniq as $sUrl) {
  69. if (0 === strncasecmp('www.', $sUrl, 4))
  70. $sUrl = substr($sUrl, 4);
  71. $aZones = explode ('.', $sUrl);
  72. $iLevels = count($aZones);
  73. if ($iLevels <= 2) {
  74. $aUrls[] = $sUrl;
  75. } elseif (3 == $iLevels) {
  76. if ($this->isDbZoneMatch (2, $aZones[1] . '.' . $aZones[2]))
  77. $aUrls[] = $sUrl;
  78. else
  79. $aUrls[] = $aZones[1] . '.' . $aZones[2];
  80. } else {
  81. $iExt = count($aZones) - 1;
  82. $iDom = $iExt - 1;
  83. $iSubDom = $iExt - 2;
  84. $iSubSubDom = $iExt - 3;
  85. if ($this->isDbZoneMatch (3, $aZones[$iSubDom] . '.' . $aZones[$iDom] . '.' . $aZones[$iExt])) {
  86. $aUrls[] = $aZones[$iSubSubDom] . '.' . $aZones[$iSubDom] . '.' . $aZones[$iDom] . '.' . $aZones[$iExt];
  87. } else {
  88. if ($this->isDbZoneMatch (2, $aZones[$iDom] . '.' . $aZones[$iExt]))
  89. $aUrls[] = $aZones[$iSubDom] . '.' . $aZones[$iDom] . '.' . $aZones[$iExt];
  90. else
  91. $aUrls[] = $aZones[$iDom] . '.' . $aZones[$iExt];
  92. }
  93. }
  94. }
  95. $aUrlsUniq = array ();
  96. foreach ($aUrls as $sUrl) {
  97. if (isset($aUrlsUniq[$sUrl]))
  98. continue;
  99. $aUrlsUniq[$sUrl] = $sUrl;
  100. }
  101. return array_values($aUrlsUniq);
  102. }
  103. public function onPositiveDetection ($sExtraData = '')
  104. {
  105. $oModule = BxDolModule::getInstance('bx_antispam');
  106. $o = bx_instance('BxAntispamDNSBlacklists', array(), $oModule->_aModule);
  107. $o->onPositiveDetection (getVisitorIP(false), $sExtraData, 'dnsbluri');
  108. }
  109. public function getURIDNSBLConfigValues ()
  110. {
  111. return array (
  112. 'block' => _t('_bx_antispam_dnsbl_behaviour_join_block'),
  113. 'approval' => _t('_bx_antispam_dnsbl_behaviour_join_approval'),
  114. );
  115. }
  116. /*************** private function ***************/
  117. private function isDbZoneMatch ($iLevel, $sZone)
  118. {
  119. $sQuery = $this->oDb->prepare("SELECT `level` FROM `bx_antispam_dnsbluri_zones` WHERE `level` = ? AND `zone` = ? LIMIT 1", $iLevel, $sZone);
  120. return $this->oDb->getOne($sQuery) ? true : false;
  121. }
  122. private function initZones()
  123. {
  124. if (0 == $this->oDb->getOne("SELECT COUNT(*) FROM `bx_antispam_dnsbluri_zones`")) {
  125. $this->oDb->query("TRUNCATE TABLE `bx_antispam_dnsbluri_zones`");
  126. foreach ($this->aZonesUrls as $iLevel => $sUrl) {
  127. $f = fopen ($sUrl, 'r');
  128. if (!$f)
  129. return false;
  130. while (!feof($f)) {
  131. $sZone = fgets($f);
  132. $sZone = trim($sZone);
  133. if ($sZone) {
  134. $sQuery = $this->oDb->prepare("INSERT INTO `bx_antispam_dnsbluri_zones` SET `level` = ?, `zone` = ?", $iLevel, $sZone);
  135. $this->oDb->query($sQuery);
  136. }
  137. }
  138. fclose($f);
  139. }
  140. }
  141. return true;
  142. }
  143. }
  144. /** @} */