outputfilter.obfuscate_email.php
1 <?php
2 /**
3  * wCMF - wemove Content Management Framework
4  * Copyright (C) 2005-2020 wemove digital solutions GmbH
5  *
6  * Licensed under the terms of the MIT License.
7  *
8  * See the LICENSE file distributed with this work for
9  * additional information.
10  */
11 
12 /**
13  * Obfuscate email addresses.
14  * @see https://stackoverflow.com/questions/12592363/looking-for-a-php-only-email-address-obfuscator-function#12592364
15  *
16  * @param $output
17  * @param $template Smarty_Internal_Template
18  * @return String
19  */
20 function smarty_outputfilter_obfuscate_email($output, Smarty_Internal_Template $template) {
21  $encodePercentage = 50;
22 
23  // encoding functions
24  $alwaysEncode = ['.', '@', '+'];
25  $octHexEncodeChar = function($char) use ($alwaysEncode, $encodePercentage) {
26  if (in_array($char, $alwaysEncode) || random_int(1, 100) < $encodePercentage) {
27  if (random_int(0, 1)) {
28  return '&#'.ord($char).';';
29  }
30  else {
31  return '&#x'.dechex(ord($char)).';';
32  }
33  }
34  else {
35  return $char;
36  }
37  };
38  $neverEncode = ['.', '@', '+']; // don't encode those as not fully supported by IE & Chrome
39  $urlEncodeChar = function($char) use ($neverEncode, $encodePercentage) {
40  if (!in_array($char, $neverEncode) && random_int(1, 100) < $encodePercentage) {
41  $charCode = ord($char);
42  return '%'.dechex(($charCode >> 4) & 0xF).dechex($charCode & 0xF);
43  }
44  else {
45  return $char;
46  }
47  };
48 
49  // encode
50  $output = preg_replace_callback(
51  '!<a\s([^>]*)href=["\']mailto:([^"\'\?]+)([^"\']*)["\']([^>]*)>(.*?)</a[^>]*>!is',
52  function($matches) use ($octHexEncodeChar, $urlEncodeChar) {
53  // $matches[0] contains full matched string: <a href="...">...</a>
54  // $matches[1] contains additional parameters
55  // $matches[2] contains the email address which was specified as href
56  // $matches[3] contains parameters such as subject and body
57  // $matches[4] contains additional parameters
58  // $matches[5] contains the text between the opening and closing <a> tag
59 
60  $address = $matches[2];
61  // urlencode address
62  $encodedAddress = preg_replace_callback('/./', function($m) use ($urlEncodeChar) {
63  return $urlEncodeChar($m[0]);
64  }, $address);
65  // obfuscate href
66  $obfuscatedLink = preg_replace_callback('/./', function($m) use ($octHexEncodeChar) {
67  return $octHexEncodeChar($m[0]);
68  }, 'mailto:'.$encodedAddress);
69 
70  $params = trim($matches[3]);
71 
72  $extra = trim($matches[1]." ".$matches[4]);
73  // tell search engines to ignore obfuscated uri
74  if (!preg_match('/rel=["\']nofollow["\']/', $extra)) {
75  $extra = trim($extra.' rel="nofollow"');
76  }
77 
78  // obfuscate text
79  $text = $matches[5];
80  // obfuscate text only, if it contains the email address
81  $obfuscatedText = null;
82  if (strpos($text, $address) !== false) {
83  $obfuscatedText = preg_replace_callback('/./', function($m) use ($octHexEncodeChar) {
84  return $octHexEncodeChar($m[0]);
85  }, $text);
86  }
87 
88  $replace = '<a href="'.$obfuscatedLink.$params.'" '.$extra.'>'.($obfuscatedText ? urldecode($obfuscatedText) : $text).'</a>';
89 
90  return $replace;
91  }, $output);
92  return $output;
93 }
94 ?>