ObfuscateHelper.php 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. <?php
  2. namespace Tools\View\Helper;
  3. use Cake\View\Helper;
  4. /**
  5. * Protect email and alike on output, against bots mainly.
  6. *
  7. * TODO: make snippets more "css and background image" (instead of inline img links)
  8. *
  9. * @author Mark Scherer
  10. * @license MIT
  11. * @property \Cake\View\Helper\HtmlHelper $Html
  12. */
  13. class ObfuscateHelper extends Helper {
  14. /**
  15. * Other helpers used
  16. *
  17. * @var array
  18. */
  19. public $helpers = ['Html'];
  20. /**
  21. * It is still believed that encoding will stop spam-bots being able to find your email address.
  22. * Nevertheless, encoded email address harvester are on the way (http://www.dreamweaverfever.com/experiments/spam/).
  23. *
  24. * Helper Function to Obfuscate Email by inserting a span tag (not more! not very secure on its own...)
  25. * each part of this mail now does not make sense anymore on its own
  26. * (striptags will not work either)
  27. *
  28. * @param string $mail Email, necessary (and valid - containing one @)
  29. * @return string
  30. */
  31. public function encodeEmail($mail) {
  32. $pieces = explode('@', $mail);
  33. if (count($pieces) < 2) {
  34. return $mail;
  35. }
  36. list($mail1, $mail2) = $pieces;
  37. $encMail = $this->encodeText($mail1) . '<span>@</span>' . $this->encodeText($mail2);
  38. return $encMail;
  39. }
  40. /**
  41. * Obfuscates Email (works without JS!) to avoid spam bots to get it
  42. *
  43. * @param string $mail Email to encode
  44. * @param string|null $text Text, ptional (if none is given, email will be text as well)
  45. * @param array $params ?subject=y&body=y to be attached to "mailto:xyz"
  46. * @param array $attr HTML tag attributes
  47. * @return string Save string with JS generated link around email (and non JS fallback)
  48. */
  49. public function encodeEmailUrl($mail, $text = null, array $params = [], array $attr = []) {
  50. if (empty($class)) {
  51. $class = 'email';
  52. }
  53. $defaults = [
  54. 'title' => __d('tools', 'for use in an external mail client'),
  55. 'class' => 'email',
  56. 'escape' => false
  57. ];
  58. if (empty($text)) {
  59. $text = $this->encodeEmail($mail);
  60. }
  61. $encMail = 'mailto:' . $mail;
  62. // additionally there could be a span tag in between: email<span syle="display:none"></span>@web.de
  63. $querystring = '';
  64. foreach ($params as $key => $val) {
  65. if ($querystring) {
  66. $querystring .= "&$key=" . rawurlencode($val);
  67. } else {
  68. $querystring = "?$key=" . rawurlencode($val);
  69. }
  70. }
  71. $attr = array_merge($defaults, $attr);
  72. $xmail = $this->Html->link('', $encMail . $querystring, $attr);
  73. $xmail1 = mb_substr($xmail, 0, count($xmail) - 5);
  74. $xmail2 = mb_substr($xmail, -4, 4);
  75. $len = mb_strlen($xmail1);
  76. $i = 0;
  77. $par = [];
  78. while ($i < $len) {
  79. $c = mt_rand(2, 6);
  80. $par[] = (mb_substr($xmail1, $i, $c));
  81. $i += $c;
  82. }
  83. $join = implode('\'+ \'', $par);
  84. return '<script language=javascript><!--
  85. document.write(\'' . $join . '\');
  86. //--></script>
  87. ' . $text . '
  88. <script language=javascript><!--
  89. document.write(\'' . $xmail2 . '\');
  90. //--></script>';
  91. }
  92. /**
  93. * Encodes Piece of Text (without usage of JS!) to avoid spam bots to get it
  94. *
  95. * @param string $text Text to encode
  96. * @return string (randomly encoded)
  97. */
  98. public function encodeText($text) {
  99. $encmail = '';
  100. $length = mb_strlen($text);
  101. for ($i = 0; $i < $length; $i++) {
  102. $encMod = mt_rand(0, 2);
  103. switch ($encMod) {
  104. case 0: // None
  105. $encmail .= mb_substr($text, $i, 1);
  106. break;
  107. case 1: // Decimal
  108. $encmail .= '&#' . ord(mb_substr($text, $i, 1)) . ';';
  109. break;
  110. case 2: // Hexadecimal
  111. $encmail .= '&#x' . dechex(ord(mb_substr($text, $i, 1))) . ';';
  112. break;
  113. }
  114. }
  115. return $encmail;
  116. }
  117. /**
  118. * test@test.de becomes t..t@t..t.de
  119. *
  120. * @param string $mail Valid(!) email address
  121. * @return string
  122. */
  123. public static function hideEmail($mail) {
  124. $mailParts = explode('@', $mail, 2);
  125. $domainParts = explode('.', $mailParts[1], 2);
  126. $user = mb_substr($mailParts[0], 0, 1) . '..' . mb_substr($mailParts[0], -1, 1);
  127. $domain = mb_substr($domainParts[0], 0, 1) . '..' . mb_substr($domainParts[0], -1, 1) . '.' . $domainParts[1];
  128. return $user . '@' . $domain;
  129. }
  130. /**
  131. * Word Censoring Function
  132. *
  133. * Supply a string and an array of disallowed words and any
  134. * matched words will be converted to #### or to the replacement
  135. * word you've submitted.
  136. *
  137. * @param string $str the text string
  138. * @param array $censored the array of censored words
  139. * @param string|null $replacement the optional replacement value
  140. * @return string
  141. */
  142. public function wordCensor($str, array $censored, $replacement = null) {
  143. if (empty($censored)) {
  144. return $str;
  145. }
  146. $str = ' ' . $str . ' ';
  147. // \w, \b and a few others do not match on a unicode character
  148. // set for performance reasons. As a result words like ..ber
  149. // will not match on a word boundary. Instead, we'll assume that
  150. // a bad word will be bookended by any of these characters.
  151. $delim = '[-_\'\"`() {}<>\[\]|!?@#%&,.:;^~*+=\/ 0-9\n\r\t]';
  152. foreach ($censored as $badword) {
  153. if ($replacement !== null) {
  154. $str = preg_replace("/({$delim})(" . str_replace('\*', '\w*?', preg_quote($badword, '/')) . ")({$delim})/i", "\\1{$replacement}\\3", $str);
  155. } else {
  156. $str = preg_replace_callback("/({$delim})(" . str_replace('\*', '\w*?', preg_quote($badword, '/')) . ")({$delim})/i", function ($matches) {
  157. return $matches[1] . str_repeat('#', strlen($matches[2])) . $matches[3];
  158. }, $str);
  159. }
  160. }
  161. return trim($str);
  162. }
  163. }