BxAntispamDNSURIBlacklists.php 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  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 DolphinModules
  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 = &$GLOBALS['MySQL'];
  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. $o = bx_instance('BxDolDNSBlacklists');
  43. foreach ($aURIs as $sURI) {
  44. if (BX_DOL_DNSBL_POSITIVE == $o->dnsbl_lookup_uri ($sURI))
  45. return true;
  46. }
  47. return false;
  48. }
  49. public function parseUrls (&$s)
  50. {
  51. $aMatches = array ();
  52. if (!preg_match_all("!(https?|ftp|gopher|telnet|file|notes|ms-help):[/\\\\]+([\w\d\.]*)!", $s, $aMatches))
  53. return false;
  54. if (!$aMatches || !isset($aMatches[2]) || !$aMatches[2])
  55. return false;
  56. $aUrlsUniq = array ();
  57. foreach ($aMatches[2] as $sUrl) {
  58. if (isset($aUrlsUniq[$sUrl]))
  59. continue;
  60. $aUrlsUniq[$sUrl] = $sUrl;
  61. }
  62. return $aUrlsUniq;
  63. }
  64. public function validateUrls ($aUrlsUniq)
  65. {
  66. $aUrls = array ();
  67. foreach ($aUrlsUniq as $sUrl) {
  68. if (0 == strncasecmp('www.', $sUrl, 4))
  69. $sUrl = substr($sUrl, 4);
  70. $aZones = explode ('.', $sUrl);
  71. $iLevels = count($aZones);
  72. if ($iLevels <= 2) {
  73. $aUrls[] = $sUrl;
  74. } elseif (3 == $iLevels) {
  75. if ($this->isDbZoneMatch (2, $aZones[1] . '.' . $aZones[2]))
  76. $aUrls[] = $sUrl;
  77. else
  78. $aUrls[] = $aZones[1] . '.' . $aZones[2];
  79. } else {
  80. $iExt = count($aZones) - 1;
  81. $iDom = $iExt - 1;
  82. $iSubDom = $iExt - 2;
  83. $iSubSubDom = $iExt - 3;
  84. if ($this->isDbZoneMatch (3, $aZones[$iSubDom] . '.' . $aZones[$iDom] . '.' . $aZones[$iExt])) {
  85. $aUrls[] = $aZones[$iSubSubDom] . '.' . $aZones[$iSubDom] . '.' . $aZones[$iDom] . '.' . $aZones[$iExt];
  86. } else {
  87. if ($this->isDbZoneMatch (2, $aZones[$iDom] . '.' . $aZones[$iExt]))
  88. $aUrls[] = $aZones[$iSubDom] . '.' . $aZones[$iDom] . '.' . $aZones[$iExt];
  89. else
  90. $aUrls[] = $aZones[$iDom] . '.' . $aZones[$iExt];
  91. }
  92. }
  93. }
  94. $aUrlsUniq = array ();
  95. foreach ($aUrls as $sUrl) {
  96. if (isset($aUrlsUniq[$sUrl]))
  97. continue;
  98. $aUrlsUniq[$sUrl] = $sUrl;
  99. }
  100. return array_values($aUrlsUniq);
  101. }
  102. public function onPositiveDetection ($sExtraData = '')
  103. {
  104. $o = bx_instance('BxDolDNSBlacklists');
  105. $o->onPositiveDetection (getVisitorIP(false), $sExtraData, 'dnsbluri');
  106. }
  107. /*************** private function ***************/
  108. private function isDbZoneMatch ($iLevel, $sZone)
  109. {
  110. $sQuery = $this->oDb->prepare("SELECT `level` FROM `sys_dnsbluri_zones` WHERE `level` = ? AND `zone` = ? LIMIT 1", $iLevel, $sZone);
  111. return $this->oDb->getOne($sQuery) ? true : false;
  112. }
  113. private function initZones()
  114. {
  115. if (0 == $this->oDb->getOne("SELECT COUNT(*) FROM `sys_dnsbluri_zones`")) {
  116. $this->oDb->query("TRUNCATE TABLE `sys_dnsbluri_zones`");
  117. foreach ($this->aZonesUrls as $iLevel => $sUrl) {
  118. $f = fopen ($sUrl, 'r');
  119. if (!$f)
  120. return false;
  121. while (!feof($f)) {
  122. $sZone = fgets($f);
  123. $sZone = trim($sZone);
  124. if ($sZone) {
  125. $sQuery = $this->oDb->prepare("INSERT INTO `sys_dnsbluri_zones` SET `level` = ?, `zone` = ?", $iLevel, $sZone);
  126. $this->oDb->query($sQuery);
  127. }
  128. }
  129. fclose($f);
  130. }
  131. }
  132. return true;
  133. }
  134. }
  135. /** @} */