PluginProbe ʕ •ᴥ•ʔ
Email Encoder – Protect Email Addresses and Phone Numbers / 1.4.0
Email Encoder – Protect Email Addresses and Phone Numbers v1.4.0
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
.htaccess 11 years ago 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
554 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 'input' => '/<input([^>]*)value=["\'][\s+]*([A-Z0-9._-]+@[A-Z0-9][A-Z0-9.-]{0,61}[A-Z0-9]\.[A-Z.]{2,6})[\s+]*["\']([^>]*)>/is',
35 );
36
37 /**
38 * Constructor
39 */
40 protected function __construct() {
41 parent::__construct();
42 }
43
44 /**
45 * Make private to prevent multiple objects
46 */
47 private function __clone() {}
48
49 /**
50 * Get singleton instance
51 */
52 static public function getInstance() {
53 if (self::$instance === null) {
54 self::$instance = new Eeb_Site();
55 }
56
57 return self::$instance;
58 }
59
60 /**
61 * wp action
62 */
63 public function wp() {
64 $this->is_admin_user = current_user_can('manage_options');
65
66 if (is_admin()) {
67 return;
68 }
69
70 // apply filters
71 $this->regexp_patterns['mailto'] = apply_filters('eeb_mailto_regexp', $this->regexp_patterns['mailto']);
72 $this->regexp_patterns['email'] = apply_filters('eeb_email_regexp', $this->regexp_patterns['email']);
73
74 if (is_feed()) {
75 // rss feed
76 $rss_filters = array('the_title', 'the_content', 'the_excerpt', 'the_title_rss', 'the_content_rss', 'the_excerpt_rss',
77 'comment_text_rss', 'comment_author_rss', 'the_category_rss', 'the_content_feed', 'author_feed_link', 'feed_link');
78
79 foreach($rss_filters as $filter) {
80 if ($this->options['remove_shortcodes_rss']) {
81 add_filter($filter, array($this, 'callback_rss_remove_shortcodes'), 9);
82 }
83
84 if ($this->options['filter_rss']) {
85 add_filter($filter, array($this, 'callback_filter_rss'), 100);
86 }
87 }
88 } else {
89 // site
90 $filters = array();
91
92 // post content
93 if ($this->options['filter_posts']) {
94 array_push($filters, 'the_title', 'the_content', 'the_excerpt', 'get_the_excerpt');
95 }
96
97 // comments
98 if ($this->options['filter_comments']) {
99 array_push($filters, 'comment_text', 'comment_excerpt', 'comment_url', 'get_comment_author_url', 'get_comment_author_link', 'get_comment_author_url_link');
100 }
101
102 // widgets
103 if ($this->options['filter_widgets']) {
104 array_push($filters, 'widget_title', 'widget_text', 'widget_content');
105
106 // also replace shortcodes
107 if ($this->options['shortcodes_in_widgets']) {
108 add_filter('widget_text', 'do_shortcode', 100);
109 add_filter('widget_content', 'do_shortcode', 100); // widget_content id filter of Widget Logic plugin
110 }
111 }
112
113 foreach($filters as $filter) {
114 add_filter($filter, array($this, 'callback_filter'), 100);
115 }
116 }
117
118 // actions
119 add_action('wp_head', array($this, 'wp_head'));
120
121 // shortcodes
122 add_shortcode('eeb_form', array($this, 'shortcode_email_encoder_form'));
123 add_shortcode('eeb_email', array($this, 'shortcode_encode_email'));
124 add_shortcode('eeb_content', array($this, 'shortcode_encode_content'));
125
126 // hook
127 do_action('eeb_ready', array($this, 'callback_filter'), $this);
128
129 // support for deprecated action and shortcodes
130 if ($this->options['support_deprecated_names'] == 1) {
131 // deprecated template functions
132 require_once('deprecated.php');
133
134 // deprecated shortcodes
135 add_shortcode('email_encoder_form', array($this, 'shortcode_email_encoder_form'));
136 add_shortcode('encode_email', array($this, 'shortcode_encode_email'));
137 add_shortcode('encode_content', array($this, 'shortcode_encode_content'));
138
139 // deprecated hooks
140 do_action('init_email_encoder_bundle', array($this, 'callback_filter'), $this);
141 }
142 }
143
144 /**
145 * WP head
146 */
147 public function wp_head() {
148 // add styling for encoding check message + icon
149 if ($this->is_admin_user && $this->options['show_encoded_check']) {
150 echo <<<CSS
151 <style type="text/css">
152 a.encoded-check { opacity:0.5; position:absolute; text-decoration:none !important; font:10px Arial !important; margin-top:-3px; color:#629632; font-weight:bold; }
153 a.encoded-check:hover { opacity:1; cursor:help; }
154 a.encoded-check img { width:10px; height:10px; }
155 </style>
156 CSS;
157 }
158 }
159
160 /* -------------------------------------------------------------------------
161 * Filter Callbacks
162 * ------------------------------------------------------------------------*/
163
164 /**
165 * WP filter callback
166 * @param string $content
167 * @return string
168 */
169 public function callback_filter($content) {
170 global $post;
171
172 if (isset($post) && in_array($post->ID, $this->skip_posts)) {
173 return $content;
174 }
175
176 return $this->encode_email_filter($content, true, $this->options['encode_mailtos'], $this->options['encode_emails'], $this->options['encode_fields']);
177 }
178
179 /**
180 * RSS Filter callback
181 * @param string $content
182 * @return string
183 */
184 public function callback_filter_rss($content) {
185 $content = preg_replace($this->regexp_patterns, $this->options['protection_text_rss'], $content);
186
187 return $content;
188 }
189
190 /**
191 * RSS Callback Remove shortcodes
192 * @param string $content
193 * @return string
194 */
195 public function callback_rss_remove_shortcodes($content) {
196 // strip shortcodes like [eeb_content], [eeb_form]
197 $content = strip_shortcodes($content);
198
199 return $content;
200 }
201
202 /**
203 * Filter content for encoding
204 * @param string $content
205 * @param boolean $enc_tags Optional, default true
206 * @param boolean $enc_mailtos Optional, default true
207 * @param boolean $enc_plain_emails Optional, default true
208 * @param boolean $enc_input_fields Optional, default true
209 * @return string
210 */
211 public function encode_email_filter($content, $enc_tags = true, $enc_mailtos = true, $enc_plain_emails = true, $enc_input_fields = true) {
212 // encode input fields with prefilled email address
213 if ($enc_input_fields) {
214 $content = preg_replace_callback($this->regexp_patterns['input'], array($this, 'callback_encode_input_field'), $content);
215 }
216
217 // encode mailto links
218 if ($enc_mailtos) {
219 $content = preg_replace_callback($this->regexp_patterns['mailto'], array($this, 'callback_encode_email'), $content);
220 }
221
222 // replace plain emails
223 if ($enc_plain_emails) {
224 $content = preg_replace_callback($this->regexp_patterns['email'], array($this, 'callback_encode_email'), $content);
225 }
226
227 // workaround for double encoding bug when auto-protect mailto is enabled and method is enc_html
228 $content = str_replace('[a-replacement]', '<a', $content);
229
230 return $content;
231 }
232
233 /**
234 * Callback for encoding email
235 * @param array $match
236 * @return string
237 */
238 public function callback_encode_email($match) {
239 if (count($match) < 3) {
240 $encoded = $this->encode_email($match[1]);
241 } else if (count($match) == 3) {
242 $encoded = $this->encode_email($match[2]);
243 } else {
244 $encoded = $this->encode_email($match[2], $match[4], $match[1] . ' ' . $match[3]);
245 }
246
247 // workaround for double encoding bug when auto-protect mailto is enabled and method is enc_html
248 $encoded = str_replace('<a', '[a-replacement]', $encoded);
249
250 return $encoded;
251 }
252
253 /**
254 * Callback for encoding input field with email address
255 * @param array $match
256 * @return string
257 */
258 public function callback_encode_input_field($match) {
259 if ($this->method === 'enc_html') {
260 // enc_html method
261 $email = $match[2];
262 $encoded_email = $this->enc_html($email);
263
264 $encoded = str_replace($email , $encoded_email, $match[0]);
265 $encoded = $this->get_success_check($encoded);
266 } else {
267 $encoded = $this->encode_content($match[0]);
268 }
269
270 return $encoded;
271 }
272
273 /* -------------------------------------------------------------------------
274 * Shortcode Functions
275 * ------------------------------------------------------------------------*/
276
277 /**
278 * Shortcode showing encoder form
279 * @return string
280 */
281 public function shortcode_email_encoder_form() {
282 // add style and script for ajax encoder
283 // wp_enqueue_script('email_encoder', plugins_url('js/src/email-encoder-bundle.js', EMAIL_ENCODER_BUNDLE_FILE), array('jquery'), EMAIL_ENCODER_BUNDLE_VERSION);
284 wp_enqueue_script('email_encoder', plugins_url('js/email-encoder-bundle.min.js', EMAIL_ENCODER_BUNDLE_FILE), array('jquery'), EMAIL_ENCODER_BUNDLE_VERSION);
285
286 return $this->get_encoder_form();
287 }
288
289 /**
290 * Shortcode encoding email
291 * @param array $attrs
292 * @return string
293 */
294 public function shortcode_encode_email($attrs) {
295 if (!is_array($attrs) || !key_exists('email', $attrs)) {
296 return '';
297 }
298
299 $email = $attrs['email'];
300 $display = (key_exists('display', $attrs)) ? $attrs['display'] : $attrs['email'];
301 $method = (key_exists('method', $attrs)) ? $attrs['method'] : null;
302 $extra_attrs = (key_exists('extra_attrs', $attrs)) ? $attrs['extra_attrs'] : null;
303
304 $encoded = $this->encode_email($email, $display, $extra_attrs, $method);
305
306 // workaround for double encoding bug when auto-protect mailto is enabled and method is enc_html
307 $encoded = str_replace('<a', '[a-replacement]', $encoded);
308
309 return $encoded;
310 }
311
312 /**
313 * Shortcode encoding content
314 * @param array $attrs
315 * @param string $content Optional
316 * @return string
317 */
318 public function shortcode_encode_content($attrs, $content = '') {
319 $method = (is_array($attrs) && key_exists('method', $attrs)) ? $attrs['method'] : null;
320
321 return $this->encode_content($content, $method);
322 }
323
324 /* -------------------------------------------------------------------------
325 * Encode Functions
326 * -------------------------------------------------------------------------/
327
328 /**
329 * Encode the given email into an encoded HTML link
330 * @param string $content
331 * @param string $method Optional, else the default setted method will; be used
332 * @param boolean $no_html_checked Optional
333 * @param string $protection_text Optional
334 * @return string
335 */
336 public function encode_content($content, $method = null, $no_html_checked = false, $protection_text = null) {
337 if ($protection_text === null) {
338 $protection_text = $this->options['protection_text_content'];
339 }
340
341 // get encode method
342 $method = $this->get_method($method, $this->method);
343
344 // get encoded email code
345 $content = $this->{$method}($content, $protection_text);
346
347 // add visual check
348 if ($no_html_checked !== true) {
349 $content = $this->get_success_check($content);
350 }
351
352 return $content;
353 }
354
355 /**
356 * Encode the given email into an encoded HTML link
357 * @param string $email
358 * @param string $display Optional, if not set display will be the email
359 * @param string $extra_attrs Optional
360 * @param string $method Optional, else the default setted method will; be used
361 * @param boolean $no_html_checked
362 * @return string
363 */
364 public function encode_email($email, $display = null, $extra_attrs = '', $method = null, $no_html_checked = false) {
365 // get encode method
366 $method = $this->get_method($method, $this->method);
367
368 // decode entities
369 $email = html_entity_decode($email);
370
371 // set email as display
372 if ($display === null) {
373 $display = $email;
374
375 if ($method === 'enc_html') {
376 $display = $this->enc_html($display);
377 }
378 } else {
379 $display = html_entity_decode($display);
380 }
381
382 if ($method === 'enc_html') {
383 $email = $this->enc_html($email);
384 }
385
386 $class = $this->options['class_name'];
387 $extra_attrs = ' ' . trim($extra_attrs);
388 $mailto = '<a class="'. $class .'" href="mailto:' . $email . '"'. $extra_attrs . '>' . $display . '</a>';
389
390 if ($method === 'enc_html') {
391 // add visual check
392 if ($no_html_checked !== true) {
393 $mailto = $this->get_success_check($mailto);
394 }
395 } else {
396 $mailto = $this->encode_content($mailto, $method, $no_html_checked, $this->options['protection_text']);
397 }
398
399 // get encoded email code
400 return $mailto;
401 }
402
403 /**
404 * Add html to encoded content to show check icon and text
405 * @param string $content
406 * @return string
407 */
408 private function get_success_check($content) {
409 if (!$this->is_admin_user || !$this->options['show_encoded_check']) {
410 return $content;
411 }
412
413 return $content
414 . '<a href="javascript:;" class="encoded-check"'
415 . ' title="' . __('Successfully Encoded (this is a check and only visible when logged in as admin)', EMAIL_ENCODER_BUNDLE_DOMAIN) . '">'
416 . '<img class="encoded-check-icon" src="' . plugins_url('images/icon-email-encoder-bundle.png', EMAIL_ENCODER_BUNDLE_FILE)
417 . '" alt="' . __('Encoded', EMAIL_ENCODER_BUNDLE_DOMAIN) . '" />'
418 . __('Successfully Encoded', EMAIL_ENCODER_BUNDLE_DOMAIN) . '</a>';
419 }
420
421 /* -------------------------------------------------------------------------
422 * Different Encoding Methods
423 * ------------------------------------------------------------------------*/
424
425 /**
426 * ASCII method
427 * Based on function from Tyler Akins (http://rumkin.com/tools/mailto_encoder/)
428 *
429 * @param string $value
430 * @param string $protection_text
431 * @return string
432 */
433 private function enc_ascii($value, $protection_text) {
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 . $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 * @param string $protection_text
493 * @return string
494 */
495 private function enc_escape($value, $protection_text) {
496 $string = 'document.write(\'' . $value . '\')';
497
498 // break string into array of characters, we can't use string_split because its php5 only
499 $split = preg_split('||', $string);
500 $out = '<script type="text/javascript">' . "eval(decodeURIComponent('";
501
502 foreach ($split as $c) {
503 // preg split will return empty first and last characters, check for them and ignore
504 if (!empty($c)) {
505 $out .= '%' . dechex(ord($c));
506 }
507 }
508
509 $out .= "'))" . '</script><noscript>'
510 . $protection_text
511 . '</noscript>';
512
513 return $out;
514 }
515
516 /**
517 * Convert randomly chars to htmlentities
518 * This method is partly taken from WordPress
519 * @link http://codex.wordpress.org/Function_Reference/antispambot
520 *
521 * @param string $value
522 * @return string
523 */
524 private function enc_html($value) {
525 // check for built-in WP function
526 if (function_exists('antispambot')) {
527 $emailNOSPAMaddy = antispambot($value);
528 } else {
529 $emailNOSPAMaddy = '';
530 srand ((float) microtime() * 1000000);
531 for ($i = 0; $i < strlen($emailaddy); $i = $i + 1) {
532 $j = floor(rand(0, 1+$mailto));
533 if ($j==0) {
534 $emailNOSPAMaddy .= '&#'.ord(substr($emailaddy,$i,1)).';';
535 } elseif ($j==1) {
536 $emailNOSPAMaddy .= substr($emailaddy,$i,1);
537 } elseif ($j==2) {
538 $emailNOSPAMaddy .= '%'.zeroise(dechex(ord(substr($emailaddy, $i, 1))), 2);
539 }
540 }
541 $emailNOSPAMaddy = str_replace('@','&#64;',$emailNOSPAMaddy);
542 }
543
544 $emailNOSPAMaddy = str_replace('@', '&#64;', $emailNOSPAMaddy);
545
546 return $emailNOSPAMaddy;
547 }
548
549 } // end class Eeb_Site
550
551 endif;
552
553 /* ommit PHP closing tag, to prevent unwanted whitespace at the end of the parts generated by the included files */
554