PluginProbe ʕ •ᴥ•ʔ
Email Encoder – Protect Email Addresses and Phone Numbers / 1.3.0
Email Encoder – Protect Email Addresses and Phone Numbers v1.3.0
2.5.3 2.5.2 2.5.1 2.5.0 2.4.8 trunk 0.10 0.11 0.12 0.20 0.21 0.22 0.30 0.31 0.32 0.40 0.41 0.42 0.50 0.60 0.70 0.71 0.80 1.0.0 1.0.1 1.0.2 1.1.0 1.2.0 1.2.1 1.3.0 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.5 1.5.2 1.51 1.53 2.0.0 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.0.8 2.0.9 2.1.0 2.1.1 2.1.10 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.1.7 2.1.8 2.1.9 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.3.0 2.3.1 2.3.3 2.3.4 2.3.5 2.3.6 2.3.7 2.3.8 2.3.9 2.4.0 2.4.1 2.4.2 2.4.3 2.4.4 2.4.5 2.4.6 2.4.7
email-encoder-bundle / includes / class-eeb-site.php
email-encoder-bundle / includes Last commit date
class-eeb-admin.php 11 years ago class-eeb-site.php 11 years ago deprecated.php 11 years ago template-functions.php 11 years ago
class-eeb-site.php
553 lines
1 <?php defined('ABSPATH') OR die('No direct access.');
2
3 /**
4 * Class Eeb_Site (singleton)
5 *
6 * Contains all nescessary code for the site part
7 *
8 * @extends Eeb_Admin
9 * @final
10 *
11 * @package Email_Encoder_Bundle
12 * @category WordPress Plugins
13 */
14 if (!class_exists('Eeb_Site') && class_exists('Eeb_Admin')):
15
16 final class Eeb_Site extends Eeb_Admin {
17
18 /**
19 * @var Eeb_Site Singleton instance
20 */
21 static private $instance = null;
22
23 /**
24 * @var boolean
25 */
26 private $is_admin_user = false;
27
28 /**
29 * @var array Regular expresssions
30 */
31 private $regexp_patterns = array(
32 'mailto' => '/<a([^<>]*?)href=["\']mailto:(.*?)["\'](.*?)>(.*?)<\/a[\s+]*>/is',
33 'email' => '/([A-Z0-9._-]+@[A-Z0-9][A-Z0-9.-]{0,61}[A-Z0-9]\.[A-Z.]{2,6})/is',
34 );
35
36 /**
37 * Constructor
38 */
39 protected function __construct() {
40 parent::__construct();
41 }
42
43 /**
44 * Make private to prevent multiple objects
45 */
46 private function __clone() {}
47
48 /**
49 * Get singleton instance
50 */
51 static public function getInstance() {
52 if (self::$instance === null) {
53 self::$instance = new Eeb_Site();
54 }
55
56 return self::$instance;
57 }
58
59 /**
60 * wp action
61 */
62 public function wp() {
63 $this->is_admin_user = current_user_can('manage_options');
64
65 if (is_admin()) {
66 return;
67 }
68
69 // apply filters
70 $this->regexp_patterns['mailto'] = apply_filters('eeb_mailto_regexp', $this->regexp_patterns['mailto']);
71 $this->regexp_patterns['email'] = apply_filters('eeb_email_regexp', $this->regexp_patterns['email']);
72
73 if (is_feed()) {
74 // rss feed
75 $rss_filters = array('the_title', 'the_content', 'the_excerpt', 'the_title_rss', 'the_content_rss', 'the_excerpt_rss',
76 'comment_text_rss', 'comment_author_rss', 'the_category_rss', 'the_content_feed', 'author_feed_link', 'feed_link');
77
78 foreach($rss_filters as $filter) {
79 if ($this->options['remove_shortcodes_rss']) {
80 add_filter($filter, array($this, 'callback_rss_remove_shortcodes'), 9);
81 }
82
83 if ($this->options['filter_rss']) {
84 add_filter($filter, array($this, 'callback_filter_rss'), 100);
85 }
86 }
87 } else {
88 // site
89 $filters = array();
90
91 // post content
92 if ($this->options['filter_posts']) {
93 array_push($filters, 'the_title', 'the_content', 'the_excerpt', 'get_the_excerpt');
94 }
95
96 // comments
97 if ($this->options['filter_comments']) {
98 array_push($filters, 'comment_text', 'comment_excerpt', 'comment_url', 'get_comment_author_url', 'get_comment_author_link', 'get_comment_author_url_link');
99 }
100
101 // widgets
102 if ($this->options['filter_widgets']) {
103 array_push($filters, 'widget_title', 'widget_text', 'widget_content');
104
105 // also replace shortcodes
106 if ($this->options['shortcodes_in_widgets']) {
107 add_filter('widget_text', 'do_shortcode', 100);
108 add_filter('widget_content', 'do_shortcode', 100); // widget_content id filter of Widget Logic plugin
109 }
110 }
111
112 foreach($filters as $filter) {
113 add_filter($filter, array($this, 'callback_filter'), 100);
114 }
115 }
116
117 // actions
118 add_action('wp_head', array($this, 'wp_head'));
119
120 // shortcodes
121 add_shortcode('eeb_form', array($this, 'shortcode_email_encoder_form'));
122 add_shortcode('eeb_email', array($this, 'shortcode_encode_email'));
123 add_shortcode('eeb_content', array($this, 'shortcode_encode_content'));
124
125 // hook
126 do_action('eeb_ready', array($this, 'callback_filter'), $this);
127
128 // support for deprecated action and shortcodes
129 if ($this->options['support_deprecated_names'] == 1) {
130 // deprecated template functions
131 require_once('deprecated.php');
132
133 // deprecated shortcodes
134 add_shortcode('email_encoder_form', array($this, 'shortcode_email_encoder_form'));
135 add_shortcode('encode_email', array($this, 'shortcode_encode_email'));
136 add_shortcode('encode_content', array($this, 'shortcode_encode_content'));
137
138 // deprecated hooks
139 do_action('init_email_encoder_bundle', array($this, 'callback_filter'), $this);
140 }
141 }
142
143 /**
144 * WP head
145 */
146 public function wp_head() {
147 // add styling for encoding check message + icon
148 if ($this->is_admin_user && $this->options['show_encoded_check']) {
149 echo <<<CSS
150 <style type="text/css">
151 a.encoded-check { opacity:0.5; position:absolute; text-decoration:none !important; font:10px Arial !important; margin-top:-3px; color:#629632; font-weight:bold; }
152 a.encoded-check:hover { opacity:1; cursor:help; }
153 a.encoded-check img { width:10px; height:10px; }
154 </style>
155 CSS;
156 }
157 }
158
159 /* -------------------------------------------------------------------------
160 * Filter Callbacks
161 * ------------------------------------------------------------------------*/
162
163 /**
164 * WP filter callback
165 * @param string $content
166 * @return string
167 */
168 public function callback_filter($content) {
169 global $post;
170
171 if (isset($post) && in_array($post->ID, $this->skip_posts)) {
172 return $content;
173 }
174
175 return $this->encode_email_filter($content, true, $this->options['encode_mailtos'], $this->options['encode_emails']);
176 }
177
178 /**
179 * RSS Filter callback
180 * @param string $content
181 * @return string
182 */
183 public function callback_filter_rss($content) {
184 $content = preg_replace($this->regexp_patterns, $this->options['protection_text_rss'], $content);
185
186 return $content;
187 }
188
189 /**
190 * RSS Callback Remove shortcodes
191 * @param string $content
192 * @return string
193 */
194 public function callback_rss_remove_shortcodes($content) {
195 // strip shortcodes like [eeb_content], [eeb_form]
196 $content = strip_shortcodes($content);
197
198 return $content;
199 }
200
201 /**
202 * Filter content for encoding
203 * @param string $content
204 * @param boolean $enc_tags Optional, default true
205 * @param boolean $enc_mailtos Optional, default true
206 * @param boolean $enc_plain_emails Optional, default true
207 * @return string
208 */
209 public function encode_email_filter($content, $enc_tags = true, $enc_mailtos = true, $enc_plain_emails = true) {
210 // encode mailto links
211 if ($enc_mailtos) {
212 $content = preg_replace_callback($this->regexp_patterns['mailto'], array($this, 'callback_encode_email'), $content);
213 }
214
215 // replace plain emails
216 if ($enc_plain_emails) {
217 $content = preg_replace_callback($this->regexp_patterns['email'], array($this, 'callback_encode_email'), $content);
218 }
219
220 // workaround for double encoding bug when auto-protect mailto is enabled and method is enc_html
221 if ($this->options['encode_mailtos'] == 1) {
222 // change back to html tag
223 $content = str_replace('[a-replacement]', '<a', $content);
224 }
225
226 return $content;
227 }
228
229 /**
230 * Callback for encoding email
231 * @param array $match
232 * @return string
233 */
234 public function callback_encode_email($match) {
235 if (count($match) < 3) {
236 return $this->encode_email($match[1]);
237 } else if (count($match) == 3) {
238 return $this->encode_email($match[2]);
239 }
240
241 return $this->encode_email($match[2], $match[4], $match[1] . ' ' . $match[3]);
242 }
243
244 /* -------------------------------------------------------------------------
245 * Shortcode Functions
246 * ------------------------------------------------------------------------*/
247
248 /**
249 * Shortcode showing encoder form
250 * @return string
251 */
252 public function shortcode_email_encoder_form() {
253 // add style and script for ajax encoder
254 // wp_enqueue_script('email_encoder', plugins_url('js/src/email-encoder-bundle.js', EMAIL_ENCODER_BUNDLE_FILE), array('jquery'), EMAIL_ENCODER_BUNDLE_VERSION);
255 wp_enqueue_script('email_encoder', plugins_url('js/email-encoder-bundle.min.js', EMAIL_ENCODER_BUNDLE_FILE), array('jquery'), EMAIL_ENCODER_BUNDLE_VERSION);
256
257 return $this->get_encoder_form();
258 }
259
260 /**
261 * Shortcode encoding email
262 * @param array $attrs
263 * @return string
264 */
265 public function shortcode_encode_email($attrs) {
266 if (!is_array($attrs) || !key_exists('email', $attrs)) {
267 return '';
268 }
269
270 $email = $attrs['email'];
271 $display = (key_exists('display', $attrs)) ? $attrs['display'] : $attrs['email'];
272 $method = (key_exists('method', $attrs)) ? $attrs['method'] : null;
273 $extra_attrs = (key_exists('extra_attrs', $attrs)) ? $attrs['extra_attrs'] : null;
274
275 $encoded = $this->encode_email($email, $display, $extra_attrs, $method);
276
277 // workaround for double encoding bug when auto-protect mailto is enabled and method is enc_html
278 if ($this->options['encode_mailtos'] == 1 && $method === 'enc_html') {
279 // change html tag to entity
280 $encoded = str_replace('<a', '[a-replacement]', $encoded);
281 }
282
283 return $encoded;
284 }
285
286 /**
287 * Shortcode encoding content
288 * @param array $attrs
289 * @param string $content Optional
290 * @return string
291 */
292 public function shortcode_encode_content($attrs, $content = '') {
293 $method = (is_array($attrs) && key_exists('method', $attrs)) ? $attrs['method'] : null;
294
295 return $this->encode_content($content, $method);
296 }
297
298 /* -------------------------------------------------------------------------
299 * Encode Functions
300 * -------------------------------------------------------------------------/
301
302
303 /**
304 * Encode the link text to support UTF8 caracter
305 * Solution found @ http://php.net/manual/en/function.utf8-decode.php#85034
306 * @param string $string
307 * @return string
308 */
309
310 function charset_decode_utf_8 ($string) {
311 /* Only do the slow convert if there are 8-bit characters */
312 /* avoid using 0xA0 (\240) in ereg ranges. RH73 does not like that */
313 if (! preg_match("[\200-\237]", $string) and ! preg_match("[\241-\377]", $string))
314 return $string;
315
316 // decode three byte unicode characters
317 $string = preg_replace("/([\340-\357])([\200-\277])([\200-\277])/e", "'&#'.((ord('\\1')-224)*4096 + (ord('\\2')-128)*64 + (ord('\\3')-128)).';'", $string);
318
319 // decode two byte unicode characters
320 $string = preg_replace("/([\300-\337])([\200-\277])/e", "'&#'.((ord('\\1')-192)*64+(ord('\\2')-128)).';'", $string);
321
322 return $string;
323 }
324
325 /**
326 * Encode the given email into an encoded HTML link
327 * @param string $content
328 * @param string $method Optional, else the default setted method will; be used
329 * @param boolean $no_html_checked
330 * @return string
331 */
332
333 public function encode_content($content, $method = null, $no_html_checked = false) {
334 // doesn't work with javascript encoding
335 // $content = $this->charset_decode_utf_8($content);
336
337 // get encode method
338 $method = $this->get_method($method, $this->method);
339
340 // get encoded email code
341 $content = $this->{$method}($content);
342
343 // add visual check
344 if ($no_html_checked !== true) {
345 $content = $this->get_success_check($content);
346 }
347
348 return $content;
349 }
350
351 /**
352 * Encode the given email into an encoded HTML link
353 * @param string $email
354 * @param string $display Optional, if not set display will be the email
355 * @param string $extra_attrs Optional
356 * @param string $method Optional, else the default setted method will; be used
357 * @param boolean $no_html_checked
358 * @return string
359 */
360 public function encode_email($email, $display = null, $extra_attrs = '', $method = null, $no_html_checked = false) {
361 // get encode method
362 $method = $this->get_method($method, $this->method);
363
364 // decode entities
365 $email = html_entity_decode($email);
366
367 // set email as display
368 if ($display === null) {
369 $display = $email;
370
371 if ($method === 'enc_html') {
372 $display = $this->enc_html($display);
373 }
374 } else {
375 $display = html_entity_decode($display);
376 }
377
378 if ($method === 'enc_html') {
379 $email = $this->enc_html($email);
380 }
381
382 $class = $this->options['class_name'];
383 $extra_attrs = ' ' . trim($extra_attrs);
384 $mailto = '<a class="'. $class .'" href="mailto:' . $email . '"'. $extra_attrs . '>' . $display . '</a>';
385
386 if ($method === 'enc_html') {
387 // add visual check
388 if ($no_html_checked !== true) {
389 $mailto = $this->get_success_check($mailto);
390 }
391 } else {
392 $mailto = $this->encode_content($mailto, $method, $no_html_checked);
393 }
394
395 // get encoded email code
396 return $mailto;
397 }
398
399 /**
400 * Add html to encoded content to show check icon and text
401 * @param string $content
402 * @return string
403 */
404 private function get_success_check($content) {
405 if (!$this->is_admin_user || !$this->options['show_encoded_check']) {
406 return $content;
407 }
408
409 return $content
410 . '<a href="javascript:;" class="encoded-check"'
411 . ' title="' . __('Successfully Encoded (this is a check and only visible when logged in as admin)', EMAIL_ENCODER_BUNDLE_DOMAIN) . '">'
412 . '<img class="encoded-check-icon" src="' . plugins_url('images/icon-email-encoder-bundle.png', EMAIL_ENCODER_BUNDLE_FILE)
413 . '" alt="' . __('Encoded', EMAIL_ENCODER_BUNDLE_DOMAIN) . '" />'
414 . __('Successfully Encoded', EMAIL_ENCODER_BUNDLE_DOMAIN) . '</a>';
415 }
416
417 /* -------------------------------------------------------------------------
418 * Different Encoding Methods
419 * ------------------------------------------------------------------------*/
420
421 //public function encodeURIComponent($str) {
422 // $revert = array('%21'=>'!', '%2A'=>'*', '%27'=>"'", '%28'=>'(', '%29'=>')');
423 // return strtr(rawurlencode($str), $revert);
424 //}
425
426 /**
427 * ASCII method
428 * Based on function from Tyler Akins (http://rumkin.com/tools/mailto_encoder/)
429 *
430 * @param string $value
431 * @return string
432 */
433 private function enc_ascii($value) {
434 $mail_link = $value;
435
436 // first encode, so special chars can be supported
437 $mail_link = $this->encodeURIComponent($mail_link);
438
439 $mail_letters = '';
440
441 for ($i = 0; $i < strlen($mail_link); $i ++) {
442 $l = substr($mail_link, $i, 1);
443
444 if (strpos($mail_letters, $l) === false) {
445 $p = rand(0, strlen($mail_letters));
446 $mail_letters = substr($mail_letters, 0, $p) .
447 $l . substr($mail_letters, $p, strlen($mail_letters));
448 }
449 }
450
451 $mail_letters_enc = str_replace("\\", "\\\\", $mail_letters);
452 $mail_letters_enc = str_replace("\"", "\\\"", $mail_letters_enc);
453
454 $mail_indices = '';
455 for ($i = 0; $i < strlen($mail_link); $i ++) {
456 $index = strpos($mail_letters, substr($mail_link, $i, 1));
457 $index += 48;
458 $mail_indices .= chr($index);
459 }
460
461 $mail_indices = str_replace("\\", "\\\\", $mail_indices);
462 $mail_indices = str_replace("\"", "\\\"", $mail_indices);
463
464 return '<script type="text/javascript">'
465 . '(function(){'
466 . 'var ml="'. $mail_letters_enc .'",mi="'. $mail_indices .'",o="";'
467 . 'for(var j=0,l=mi.length;j<l;j++){'
468 . 'o+=ml.charAt(mi.charCodeAt(j)-48);'
469 . '}document.write(decodeURIComponent(o));' // decode at the end, this way special chars can be supported
470 . '}());'
471 . '</script><noscript>'
472 . $this->options['protection_text']
473 . '</noscript>';
474 }
475
476 /**
477 * This is the opponent of JavaScripts decodeURIComponent()
478 * @link http://stackoverflow.com/questions/1734250/what-is-the-equivalent-of-javascripts-encodeuricomponent-in-php
479 * @param string $str
480 * @return string
481 */
482 private function encodeURIComponent($str) {
483 $revert = array('%21'=>'!', '%2A'=>'*', '%27'=>"'", '%28'=>'(', '%29'=>')');
484 return strtr(rawurlencode($str), $revert);
485 }
486
487 /**
488 * Escape method
489 * Taken from the plugin "Email Spam Protection" by Adam Hunter (http://blueberryware.net/2008/09/14/email-spam-protection/)
490 *
491 * @param string $value
492 * @return string
493 */
494 private function enc_escape($value) {
495 $string = 'document.write(\'' . $value . '\')';
496
497 // break string into array of characters, we can't use string_split because its php5 only
498 $split = preg_split('||', $string);
499 $out = '<script type="text/javascript">' . "eval(decodeURIComponent('";
500
501 foreach ($split as $c) {
502 // preg split will return empty first and last characters, check for them and ignore
503 if (!empty($c)) {
504 $out .= '%' . dechex(ord($c));
505 }
506 }
507
508 $out .= "'))" . '</script><noscript>'
509 . $this->options['protection_text']
510 . '</noscript>';
511
512 return $out;
513 }
514
515 /**
516 * Convert randomly chars to htmlentities
517 * This method is partly taken from WordPress
518 * @link http://codex.wordpress.org/Function_Reference/antispambot
519 *
520 * @param string $value
521 * @return string
522 */
523 private function enc_html($value) {
524 // check for built-in WP function
525 if (function_exists('antispambot')) {
526 $emailNOSPAMaddy = antispambot($value);
527 } else {
528 $emailNOSPAMaddy = '';
529 srand ((float) microtime() * 1000000);
530 for ($i = 0; $i < strlen($emailaddy); $i = $i + 1) {
531 $j = floor(rand(0, 1+$mailto));
532 if ($j==0) {
533 $emailNOSPAMaddy .= '&#'.ord(substr($emailaddy,$i,1)).';';
534 } elseif ($j==1) {
535 $emailNOSPAMaddy .= substr($emailaddy,$i,1);
536 } elseif ($j==2) {
537 $emailNOSPAMaddy .= '%'.zeroise(dechex(ord(substr($emailaddy, $i, 1))), 2);
538 }
539 }
540 $emailNOSPAMaddy = str_replace('@','&#64;',$emailNOSPAMaddy);
541 }
542
543 $emailNOSPAMaddy = str_replace('@', '&#64;', $emailNOSPAMaddy);
544
545 return $emailNOSPAMaddy;
546 }
547
548 } // end class Eeb_Site
549
550 endif;
551
552 /* ommit PHP closing tag, to prevent unwanted whitespace at the end of the parts generated by the included files */
553