SproutCMS

This is the code documentation for the SproutCMS project

source of /sprout/Helpers/Spam.php

  1. <?php
  2. /*
  3.  * Copyright (C) 2017 Karmabunny Pty Ltd.
  4.  *
  5.  * This file is a part of SproutCMS.
  6.  *
  7.  * SproutCMS is free software: you can redistribute it and/or modify it under the terms
  8.  * of the GNU General Public License as published by the Free Software Foundation, either
  9.  * version 2 of the License, or (at your option) any later version.
  10.  *
  11.  * For more information, visit <http://getsproutcms.com>.
  12.  */
  13.  
  14. namespace Sprout\Helpers;
  15.  
  16. use Kohana;
  17.  
  18.  
  19. /**
  20.  * Helper for a simple mechanism to dissuade and annoy entry-level spammers.
  21.  *
  22.  * For rigorous protection, use a CAPTCHA. @see Captcha
  23.  */
  24. class Spam
  25. {
  26.  
  27. /**
  28.   * Generates a div containing an input which should never be filled in, in order to trap spam bots.
  29.   * To be used with {@see Spam::check}
  30.   * @return string HTML
  31.   */
  32. public static function glue()
  33. {
  34. $code = 'f_' . Security::randStr(12);
  35. $out = '<div style="display:none">';
  36. $out .= ' <p>Leave the following field blank, it is an anti-spam field.</p>';
  37. $out .= ' <p><b><label for="' . $code . '">Email address:</label></b><br><input name="_email" id="' . $code . '" value=""></p>';
  38. $out .= '</div>';
  39. return $out;
  40. }
  41.  
  42. /**
  43.   * Checks that the spam field was not submitted with the form
  44.   *
  45.   * @return boolean true on success, false otherwise
  46.   */
  47. public static function check()
  48. {
  49. if (!empty($_POST['_email'])) return false;
  50. return true;
  51. }
  52.  
  53. /**
  54.   * Checks that the spam field was not submitted with the form
  55.   *
  56.   * If the check fails the user will be redirected to the URL base ('/') along
  57.   * with a notification. Normal users will never encounter this scenario.
  58.   * @return void If the check succeeded.
  59.   * @noreturn If the check failed.
  60.   */
  61. public static function checkOrDie()
  62. {
  63. if (self::check()) return;
  64.  
  65. Notification::error('Are you a spam bot?');
  66. Url::redirect('result/error');
  67. }
  68.  
  69.  
  70. /**
  71.   * Checks text for bad words, like 'tax' and 'capsicum'
  72.   *
  73.   * @see config sprout.censor_level to set the desired censor level
  74.   * @note Disallowed sequences are collated from /media/text/bannedwords_level{level}.txt which
  75.   * must take the form of a list of new-line separated character sequences.
  76.   * @param string $text The text to censor
  77.   * @return string The censored text, with disallowed sequences replaced with '*'
  78.   */
  79. public static function censor($text)
  80. {
  81. static $words = null;
  82.  
  83. if ($words == null) {
  84. $words = array();
  85.  
  86. $level = Kohana::config('sprout.censor_level');
  87. if ($level === null or $level > 3) $level = 3;
  88.  
  89. if ($level > 0) {
  90. for ($i = 1; $i <= $level; $i++) {
  91. $file = file_get_contents(DOCROOT . "media/text/bannedwords_level{$i}.txt");
  92. $lines = explode("\n", $file);
  93. foreach ($lines as $l) {
  94. $l = trim($l);
  95. if ($l != '') $words[] = $l;
  96. }
  97. unset ($file, $lines);
  98. }
  99. }
  100. }
  101.  
  102. return Text::censor($text, $words, '*');
  103. }
  104.  
  105.  
  106. /**
  107.   * Looks at a block of text to see if it looks like spam.
  108.   *
  109.   * @note Do not rely on this to provide rigorous protection against spam.
  110.   * @param string $text The text to check for spam
  111.   * @return array An array of errors. An empty array signals no unusual sequences were detected
  112.   */
  113. public static function detect($text)
  114. {
  115. $errors = [];
  116.  
  117. // HTML tags
  118. if (strip_tags($text) != $text) {
  119. $errors['html'] = 'Cannot contain HTML';
  120. }
  121.  
  122. // URLs
  123. if (preg_match('!(https?|ftp)://[-_.a-zA-Z0-9]+!', $text)) {
  124. $errors['url'] = 'Cannot contain a url';
  125. } else if (preg_match('!\b[-_a-zA-Z0-9]+[.][-_.a-zA-Z0-9]+\b!', $text)) {
  126. $errors['url'] = 'Cannot contain a url';
  127. }
  128.  
  129. // Email addresses
  130. if (preg_match('![-_.a-zA-Z0-9]+[@][-_.a-zA-Z0-9]+!', $text)) {
  131. $errors['email'] = 'Cannot contain an email address';
  132. }
  133.  
  134. return $errors;
  135. }
  136.  
  137. }
  138.