PluginProbe ʕ •ᴥ•ʔ
Email Encoder – Protect Email Addresses and Phone Numbers / 2.2.0
Email Encoder – Protect Email Addresses and Phone Numbers v2.2.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 / core / includes / classes / class-email-encoder-bundle-validate.php
email-encoder-bundle / core / includes / classes Last commit date
class-email-encoder-bundle-ajax.php 2 years ago class-email-encoder-bundle-helpers.php 2 years ago class-email-encoder-bundle-run-admin.php 2 years ago class-email-encoder-bundle-run.php 2 years ago class-email-encoder-bundle-settings.php 2 years ago class-email-encoder-bundle-validate.php 2 years ago index.php 2 years ago
class-email-encoder-bundle-validate.php
1186 lines
1 <?php
2
3 /**
4 * Class Email_Encoder_Validate
5 *
6 * The main validation functionality for the plugin.
7 * Here is where the logic happens.
8 *
9 * @since 2.0.0
10 * @package EEB
11 * @author Ironikus <info@ironikus.com>
12 */
13
14 class Email_Encoder_Validate{
15
16 /**
17 * The main page name for our admin page
18 *
19 * @var string
20 * @since 2.0.0
21 */
22 private $page_name;
23
24 /**
25 * The main page title for our admin page
26 *
27 * @var string
28 * @since 2.0.0
29 */
30 private $page_title;
31
32 /**
33 * The hook used for the final output buffer
34 *
35 * @var string
36 * @since 2.0.0
37 */
38 private $final_outout_buffer_hook;
39
40 /**
41 * The identifier used for @ characters
42 *
43 * @var string
44 * @since 2.0.0
45 */
46 private $at_identifier;
47
48 /**
49 * Our Email_Encoder_Run constructor.
50 */
51 function __construct(){
52 $this->page_name = EEB()->settings->get_page_name();
53 $this->page_title = EEB()->settings->get_page_title();
54 $this->final_outout_buffer_hook = EEB()->settings->get_final_outout_buffer_hook();
55 $this->at_identifier = EEB()->settings->get_at_identifier();
56 }
57
58 /**
59 * ######################
60 * ###
61 * #### FILTERS
62 * ###
63 * ######################
64 */
65
66 /**
67 * The main page filter function
68 *
69 * @param string $content - the content that needs to be filtered
70 * @param bool $convertPlainEmails - wether plain emails should be preserved or not
71 * @return string - The filtered content
72 */
73 public function filter_page( $content, $protect_using ){
74
75 //Added in 2.0.6
76 $content = apply_filters( 'eeb/validate/filter_page_content', $content, $protect_using );
77
78 $content = $this->filter_soft_dom_attributes( $content, 'char_encode' );
79
80 $htmlSplit = preg_split( '/(<body(([^>]*)>))/is', $content, -1, PREG_SPLIT_DELIM_CAPTURE );
81
82 if ( count( $htmlSplit ) < 4 ) {
83 return $content;
84 }
85
86 switch( $protect_using ){
87 case 'with_javascript':
88 case 'without_javascript':
89 case 'char_encode':
90 $head_encoding_method = 'char_encode';
91 break;
92 default:
93 $head_encoding_method = 'default';
94 break;
95 }
96
97 //Filter head area
98 $filtered_head = $this->filter_plain_emails( $htmlSplit[0], null, $head_encoding_method );
99
100 //Filter body
101 //Soft attributes always need to be protected using only the char encode method since otherwise the logic breaks
102 $filtered_body = $this->filter_soft_attributes( $htmlSplit[4], 'char_encode' );
103 $filtered_body = $this->filter_content( $filtered_body, $protect_using );
104
105 $filtered_content = $filtered_head . $htmlSplit[1] . $filtered_body;
106
107 //Revalidate filtered emails that should not bbe encoded
108 $filtered_content = $this->temp_encode_at_symbol( $filtered_content, true );
109
110 return $filtered_content;
111 }
112
113 /**
114 * Filter content
115 *
116 * @param string $content
117 * @param integer $protect_using
118 * @return string
119 */
120 public function filter_content( $content, $protect_using ){
121 $filtered = $content;
122 $self = $this;
123 $encode_mailtos = (bool) EEB()->settings->get_setting( 'encode_mailtos', true, 'filter_body' );
124 $convert_plain_to_image = (bool) EEB()->settings->get_setting( 'convert_plain_to_image', true, 'filter_body' );
125
126 //Added in 2.0.6
127 $filtered = apply_filters( 'eeb/validate/filter_content_content', $filtered, $protect_using );
128
129 //Soft attributes always need to be protected using only the char encode method since otherwise the logic breaks
130 $filtered = $this->filter_soft_attributes( $filtered, 'char_encode' );
131
132 switch( $protect_using ){
133 case 'char_encode':
134 $filtered = $this->filter_plain_emails( $filtered, null, 'char_encode' );
135 break;
136 case 'strong_method':
137 $filtered = $this->filter_plain_emails( $filtered );
138 break;
139 case 'without_javascript':
140 $filtered = $this->filter_input_fields( $filtered, $protect_using );
141 $filtered = $this->filter_mailto_links( $filtered, 'without_javascript' );
142 $filtered = $this->filter_custom_links( $filtered, 'without_javascript' );
143
144 if( $convert_plain_to_image ){
145 $replace_by = 'convert_image';
146 } else {
147 $replace_by = 'use_css';
148 }
149
150 if( $encode_mailtos ){
151 if( ! ( function_exists( 'et_fb_enabled' ) && et_fb_enabled() ) ){
152 $filtered = $this->filter_plain_emails( $filtered, function ( $match ) use ( $self ) {
153 return $self->create_protected_mailto( $match[0], array( 'href' => 'mailto:' . $match[0] ), 'without_javascript' );
154 }, $replace_by);
155 } else {
156 $filtered = $this->filter_plain_emails( $filtered, null, $replace_by );
157 }
158 } else {
159 $filtered = $this->filter_plain_emails( $filtered, null, $replace_by );
160 }
161
162 break;
163 case 'with_javascript':
164 $filtered = $this->filter_input_fields( $filtered, $protect_using );
165 $filtered = $this->filter_mailto_links( $filtered );
166 $filtered = $this->filter_custom_links( $filtered );
167
168 if( $convert_plain_to_image ){
169 $replace_by = 'convert_image';
170 } else {
171 $replace_by = 'use_javascript';
172 }
173
174 if( $encode_mailtos ){
175 if( ! ( function_exists( 'et_fb_enabled' ) && et_fb_enabled() ) ){
176 $filtered = $this->filter_plain_emails( $filtered, function ( $match ) use ( $self ) {
177 return $self->create_protected_mailto( $match[0], array( 'href' => 'mailto:' . $match[0] ), 'with_javascript' );
178 }, $replace_by);
179 } else {
180 $filtered = $this->filter_plain_emails( $filtered, null, $replace_by );
181 }
182 } else {
183 $filtered = $this->filter_plain_emails( $filtered, null, $replace_by );
184 }
185
186 break;
187 }
188
189 //Revalidate filtered emails that should not be encoded
190 $filtered = $this->temp_encode_at_symbol( $filtered, true );
191
192 return $filtered;
193 }
194
195 /**
196 * Emails will be replaced by '*protected email*'
197 * @param string $content
198 * @param string|callable $replace_by Optional
199 * @param string $protection_method Optional
200 * @param mixed $show_encoded_check Optional
201 * @return string
202 */
203 public function filter_plain_emails($content, $replace_by = null, $protection_method = 'default', $show_encoded_check = 'default' ){
204
205 if( $show_encoded_check === 'default' ){
206 $show_encoded_check = (bool) EEB()->settings->get_setting( 'show_encoded_check', true );
207 }
208
209 if ( $replace_by === null ) {
210 $replace_by = __( EEB()->settings->get_setting( 'protection_text', true ), 'email-encoder-bundle' );
211 }
212
213 $self = $this;
214
215 return preg_replace_callback( EEB()->settings->get_email_regex(), function ( $matches ) use ( $replace_by, $protection_method, $show_encoded_check, $self ) {
216 // workaround to skip responsive image names containing @
217 $extention = strtolower( $matches[4] );
218 $excludedList = array(
219 '.jpg',
220 '.jpeg',
221 '.png',
222 '.gif',
223 '.svg',
224 '.webp',
225 '.bmp',
226 '.tiff',
227 '.avif',
228 );
229
230 //Added in 2.1.1
231 $excludedList = apply_filters( 'eeb/validate/excluded_image_urls', $excludedList );
232
233 if ( in_array( $extention, $excludedList ) ) {
234 return $matches[0];
235 }
236
237 if ( is_callable( $replace_by ) ) {
238 return call_user_func( $replace_by, $matches, $protection_method );
239 }
240
241 if( $protection_method === 'char_encode' ){
242 $protected_return = antispambot( $matches[0] );
243 } elseif( $protection_method === 'convert_image' ){
244
245 $image_link = $self->generate_email_image_url( $matches[0] );
246 if( ! empty( $image_link ) ){
247 $protected_return = '<img src="' . $image_link . '" />';
248 } else {
249 $protected_return = antispambot( $matches[0] );
250 }
251
252 } elseif( $protection_method === 'use_javascript' ){
253 $protection_text = __( EEB()->settings->get_setting( 'protection_text', true ), 'email-encoder-bundle' );
254 $protected_return = $this->dynamic_js_email_encoding( $matches[0], $protection_text );
255 } elseif( $protection_method === 'use_css' ){
256 $protection_text = __( EEB()->settings->get_setting( 'protection_text', true ), 'email-encoder-bundle' );
257 $protected_return = $this->encode_email_css( $matches[0], $protection_text );
258 } elseif( $protection_method === 'no_encoding' ){
259 $protected_return = $matches[0];
260 } else {
261 $protected_return = $replace_by;
262 }
263
264 // mark link as successfully encoded (for admin users)
265 if ( current_user_can( EEB()->settings->get_admin_cap( 'frontend-display-security-check' ) ) && $show_encoded_check ) {
266 $protected_return .= $this->get_encoded_email_icon();
267 }
268
269 return $protected_return;
270
271 }, $content );
272 }
273
274 /**
275 * Filter passed input fields
276 *
277 * @param string $content
278 * @return string
279 */
280 public function filter_input_fields( $content, $encoding_method = 'default' ){
281 $self = $this;
282 $strong_encoding = (bool) EEB()->settings->get_setting( 'input_strong_protection', true, 'filter_body' );
283
284 $callback_encode_input_fields = function ( $match ) use ( $self, $encoding_method, $strong_encoding ) {
285 $input = $match[0];
286 $email = $match[2];
287
288 //Only allow strong encoding if javascript is supported
289 if( $encoding_method === 'without_javascript' ){
290 $strong_encoding = false;
291 }
292
293 return $self->encode_input_field( $input, $email, $strong_encoding );
294 };
295
296 $regexpInputField = '/<input([^>]*)value=["\'][\s+]*' . EEB()->settings->get_email_regex( true ) . '[\s+]*["\']([^>]*)>/is';
297
298 return preg_replace_callback( $regexpInputField, $callback_encode_input_fields, $content );
299 }
300
301 /**
302 * @param string $content
303 * @return string
304 */
305 public function filter_mailto_links( $content, $protection_method = null ){
306 $self = $this;
307
308 $callbackEncodeMailtoLinks = function ( $match ) use ( $self, $protection_method ) {
309 $attrs = EEB()->helpers->parse_html_attributes( $match[1] );
310 return $self->create_protected_mailto( $match[4], $attrs, $protection_method );
311 };
312
313 $regexpMailtoLink = '/<a[\s+]*(([^>]*)href=["\']mailto\:([^>]*)["\' ])>(.*?)<\/a[\s+]*>/is';
314
315 return preg_replace_callback( $regexpMailtoLink, $callbackEncodeMailtoLinks, $content );
316 }
317
318 /**
319 * @param string $content
320 * @return string
321 */
322 public function filter_custom_links( $content, $protection_method = null ){
323 $self = $this;
324 $custom_href_attr = (string) EEB()->settings->get_setting( 'custom_href_attr', true );
325
326 if( ! empty( $custom_href_attr ) ){
327 $custom_attr_list = explode( ',', $custom_href_attr );
328 foreach( $custom_attr_list as $s_attr ){
329 $attr_name = trim( $s_attr );
330
331 $callbackEncodeCustomLinks = function ( $match ) use ( $self, $protection_method ) {
332 $attrs = shortcode_parse_atts( $match[1] );
333 return $self->create_protected_href_att( $match[4], $attrs, $protection_method );
334 };
335
336 $regexpMailtoLink = '/<a[\s+]*(([^>]*)href=["\']' . addslashes( $attr_name ) . '\:([^>]*)["\' ])>(.*?)<\/a[\s+]*>/is';
337
338 $content = preg_replace_callback( $regexpMailtoLink, $callbackEncodeCustomLinks, $content );
339 }
340 }
341
342 return $content;
343 }
344
345 /**
346 * Emails will be replaced by '*protected email*'
347 *
348 * @param string $content
349 * @return string
350 */
351 public function filter_rss( $content, $protection_type ){
352
353 if( $protection_type === 'strong_method' ) {
354 $filtered = $this->filter_plain_emails( $content );
355 } else {
356 $filtered = $this->filter_plain_emails( $content, null, 'char_encode' );
357 }
358
359 return $filtered;
360 }
361
362 /**
363 * Filter plain emails using soft attributes
364 *
365 * @param string $content - the content that should be soft filtered
366 * @param string $protection_method - The method (E.g. char_encode)
367 * @return string
368 */
369 public function filter_soft_attributes( $content, $protection_method ){
370 $soft_attributes = EEB()->settings->get_soft_attribute_regex();
371
372 foreach( $soft_attributes as $ident => $regex ){
373
374 $attributes = array();
375 preg_match_all( $regex, $content, $attributes );
376
377 if( is_array( $attributes ) && isset( $attributes[0] ) ){
378 foreach( $attributes[0] as $single ){
379
380 if( empty( $single ) ){
381 continue;
382 }
383
384 $content = str_replace( $single, $this->filter_plain_emails( $single, null, $protection_method, false ), $content );
385 }
386 }
387
388 }
389
390 return $content;
391 }
392
393 /**
394 * Filter plain emails using soft dom attributes
395 *
396 * @param string $content - the content that should be soft filtered
397 * @param string $protection_method - The method (E.g. char_encode)
398 * @return string
399 */
400 public function filter_soft_dom_attributes( $content, $protection_method ){
401
402 $no_script_tags = (bool) EEB()->settings->get_setting( 'no_script_tags', true, 'filter_body' );
403 $no_attribute_validation = (bool) EEB()->settings->get_setting( 'no_attribute_validation', true, 'filter_body' );
404
405 if( ! empty( $content ) && is_string( $content ) ){
406
407 if( class_exists( 'DOMDocument' ) ){
408 $dom = new DOMDocument();
409 @$dom->loadHTML($content);
410
411 //Filter html attributes
412 if( ! $no_attribute_validation ){
413 $allNodes = $dom->getElementsByTagName('*');
414 foreach( $allNodes as $snote ){
415 if( $snote->hasAttributes() ) {
416 foreach( $snote->attributes as $attr ) {
417 if( $attr->nodeName == 'href' || $attr->nodeName == 'src' ){
418 continue;
419 }
420
421 if( strpos( $attr->nodeValue, '@' ) !== FALSE ){
422 $single_tags = array();
423 preg_match_all( '/' . $attr->nodeName . '=["\']([^"]*)["\']/i', $content, $single_tags );
424
425 if( is_array( $single_tags ) && isset( $single_tags[0] ) ){
426 foreach( $single_tags[0] as $single ){
427
428 if( empty( $single ) ){
429 continue;
430 }
431
432 $content = str_replace( $single, $this->filter_plain_emails( $single, null, $protection_method, false ), $content );
433 }
434 }
435
436 }
437 }
438 }
439 }
440 }
441
442 //Keep for now
443 //Soft-encode scripts
444 // $script = $dom->getElementsByTagName('script');
445 // if( ! empty( $script ) ){
446 // $scripts_encoded = true;
447
448 // if( ! $no_script_tags ){
449 // foreach( $script as $item ){
450 // $content = str_replace( $item->nodeValue, $this->filter_plain_emails( $item->nodeValue, null, $protection_method, false ), $content );
451 // }
452 // } else {
453 // foreach( $script as $item ){
454 // $content = str_replace( $item->nodeValue, $this->temp_encode_at_symbol( $item->nodeValue ), $content );
455 // }
456 // }
457 // }
458
459 }
460
461 //Validate script tags for better encoding
462 $pattern = '/<script\b[^>]*>(.*?)<\/script>/is';
463
464 preg_match_all($pattern, $content, $matches);
465 if(
466 isset( $matches[1] )
467 && ! empty( $matches[1] )
468 ){
469 if( ! $no_script_tags ){
470 foreach( $matches[1] as $key => $item ){
471
472 //Don't do anything if something doesn't add up
473 if( ! isset( $matches[0][ $key ] ) ){
474 continue;
475 }
476
477 $org_script = $matches[0][ $key ];
478
479 //Only encode emails when a CDATA is given to not cause any break within the scripts
480 if( strpos( $item, '<![CDATA' ) !== false ){
481 $validated_script = str_replace( $item, $this->filter_plain_emails( $item, null, $protection_method, false ), $org_script );
482 } else {
483 $validated_script = str_replace( $item, $this->temp_encode_at_symbol( $item ), $org_script );
484 }
485
486 $content = str_replace( $org_script, $validated_script, $content );
487 }
488 } else {
489 foreach( $matches[1] as $key => $item ){
490
491 //Don't do anything if something doesn't add up
492 if( ! isset( $matches[0][ $key ] ) ){
493 continue;
494 }
495
496 $org_script = $matches[0][ $key ];
497 $validated_script = str_replace( $item, $this->temp_encode_at_symbol( $item ), $org_script );
498
499 $content = str_replace( $org_script, $validated_script, $content );
500 }
501 }
502 }
503
504 }
505
506
507 return $content;
508 }
509
510 /**
511 * ######################
512 * ###
513 * #### ENCODINGS
514 * ###
515 * ######################
516 */
517
518 public function temp_encode_at_symbol( $content, $decode = false ){
519 if( $decode ){
520 return str_replace( $this->at_identifier, '@', $content );
521 }
522
523 return str_replace( '@', $this->at_identifier, $content );
524 }
525
526 /**
527 * ASCII method
528 *
529 * @param string $value
530 * @param string $protection_text
531 * @return string
532 */
533 public function encode_ascii($value, $protection_text) {
534 $mail_link = $value;
535
536 // first encode, so special chars can be supported
537 $mail_link = EEB()->helpers->encode_uri_components( $mail_link );
538
539 $mail_letters = '';
540
541 for ($i = 0; $i < strlen($mail_link); $i ++) {
542 $l = substr($mail_link, $i, 1);
543
544 if (strpos($mail_letters, $l) === false) {
545 $p = rand(0, strlen($mail_letters));
546 $mail_letters = substr($mail_letters, 0, $p) .
547 $l . substr($mail_letters, $p, strlen($mail_letters));
548 }
549 }
550
551 $mail_letters_enc = str_replace("\\", "\\\\", $mail_letters);
552 $mail_letters_enc = str_replace("\"", "\\\"", $mail_letters_enc);
553
554 $mail_indices = '';
555 for ($i = 0; $i < strlen($mail_link); $i ++) {
556 $index = strpos($mail_letters, substr($mail_link, $i, 1));
557 $index += 48;
558 $mail_indices .= chr($index);
559 }
560
561 $mail_indices = str_replace("\\", "\\\\", $mail_indices);
562 $mail_indices = str_replace("\"", "\\\"", $mail_indices);
563
564 $element_id = 'eeb-' . mt_rand( 0, 1000000 ) . '-' . mt_rand(0, 1000000);
565
566 return '<span id="'. $element_id . '"></span>'
567 . '<script type="text/javascript">'
568 . '(function(){'
569 . 'var ml="'. $mail_letters_enc .'",mi="'. $mail_indices .'",o="";'
570 . 'for(var j=0,l=mi.length;j<l;j++){'
571 . 'o+=ml.charAt(mi.charCodeAt(j)-48);'
572 . '}document.getElementById("' . $element_id . '").innerHTML = decodeURIComponent(o);' // decode at the end, this way special chars can be supported
573 . '}());'
574 . '</script><noscript>'
575 . $protection_text
576 . '</noscript>';
577 }
578
579 /**
580 * Escape encoding method
581 *
582 * @param string $value
583 * @param string $protection_text
584 * @return string
585 */
586 public function encode_escape( $value, $protection_text ) {
587 $element_id = 'eeb-' . mt_rand( 0, 1000000 ) . '-' . mt_rand( 0, 1000000 );
588 $string = '\'' . $value . '\'';
589
590 //Validate escape sequences
591 $string = preg_replace('/\s+/S', " ", $string);
592
593 // break string into array of characters, we can't use string_split because its php5 only
594 $split = preg_split( '||', $string );
595 $out = '<span id="'. $element_id . '"></span>'
596 . '<script type="text/javascript">' . 'document.getElementById("' . $element_id . '").innerHTML = ev' . 'al(decodeURIComponent("';
597
598 foreach( $split as $c ) {
599 // preg split will return empty first and last characters, check for them and ignore
600 if( ! empty( $c ) || $c === '0' ) {
601 $out .= '%' . dechex( ord( $c ) );
602 }
603 }
604
605 $out .= '"))' . '</script><noscript>'
606 . $protection_text
607 . '</noscript>';
608
609 return $out;
610 }
611
612 /**
613 * Encode email in input field
614 * @param string $input
615 * @param string $email
616 * @return string
617 */
618 public function encode_input_field( $input, $email, $strongEncoding = false ){
619
620 $show_encoded_check = (bool) EEB()->settings->get_setting( 'show_encoded_check', true );
621
622 if ( $strongEncoding === false ) {
623 // encode email with entities (default wp method)
624 $sub_return = str_replace( $email, antispambot( $email ), $input );
625
626 if ( current_user_can( EEB()->settings->get_admin_cap( 'frontend-display-security-check' ) ) && $show_encoded_check ) {
627 $sub_return .= $this->get_encoded_email_icon();
628 }
629
630 return $sub_return;
631 }
632
633 // add data-enc-email after "<input"
634 $inputWithDataAttr = substr( $input, 0, 6 );
635 $inputWithDataAttr .= ' data-enc-email="' . $this->get_encoded_email( $email ) . '"';
636 $inputWithDataAttr .= substr( $input, 6 );
637
638 // mark link as successfullly encoded (for admin users)
639 if ( current_user_can( EEB()->settings->get_admin_cap( 'frontend-display-security-check' ) ) && $show_encoded_check ) {
640 $inputWithDataAttr .= $this->get_encoded_email_icon();
641 }
642
643 // remove email from value attribute
644 $encInput = str_replace( $email, '', $inputWithDataAttr );
645
646 return $encInput;
647 }
648
649 /**
650 * Get encoded email, used for data-attribute (translate by javascript)
651 *
652 * @param string $email
653 * @return string
654 */
655 public function get_encoded_email( $email ){
656 $encEmail = $email;
657
658 // decode entities
659 $encEmail = html_entity_decode( $encEmail );
660
661 // rot13 encoding
662 $encEmail = str_rot13( $encEmail );
663
664 // replace @
665 $encEmail = str_replace( '@', '[at]', $encEmail );
666
667 return $encEmail;
668 }
669
670 /**
671 * Get the ebcoded email icon
672 *
673 * @param string $email
674 * @return string
675 */
676 public function get_encoded_email_icon( $text = 'Email encoded successfully!' ){
677
678 $html = '<i class="eeb-encoded dashicons-before dashicons-lock" title="' . __( $text, 'email-encoder-bundle' ) . '"></i>';
679
680 return apply_filters( 'eeb/validate/get_encoded_email_icon', $html, $text );
681 }
682
683 /**
684 * Create a protected email
685 *
686 * @param string $display
687 * @param array $attrs Optional
688 * @return string
689 */
690 public function create_protected_mailto( $display, $attrs = array(), $protection_method = null ){
691 $email = '';
692 $class_ori = ( empty( $attrs['class'] ) ) ? '' : $attrs['class'];
693 $custom_class = (string) EEB()->settings->get_setting( 'class_name', true );
694 $show_encoded_check = (string) EEB()->settings->get_setting( 'show_encoded_check', true );
695
696 // set user-defined class
697 if ( $custom_class && strpos( $class_ori, $custom_class ) === FALSE ) {
698 $attrs['class'] = ( empty( $attrs['class'] ) ) ? $custom_class : $attrs['class'] . ' ' . $custom_class;
699 }
700
701 // check title for email address
702 if ( ! empty( $attrs['title'] ) ) {
703 $attrs['title'] = $this->filter_plain_emails( $attrs['title'], '{{email}}' ); // {{email}} will be replaced in javascript
704 }
705
706 // set ignore to data-attribute to prevent being processed by WPEL plugin
707 $attrs['data-wpel-link'] = 'ignore';
708
709 // create element code
710 $link = '<a ';
711
712 foreach ( $attrs AS $key => $value ) {
713 if ( strtolower( $key ) == 'href' ) {
714 if( $protection_method === 'without_javascript' ){
715 $link .= $key . '="' . antispambot( $value ) . '" ';
716 } else {
717 // get email from href
718 $email = substr($value, 7);
719
720 $encoded_email = $this->get_encoded_email( $email );
721
722 // set attrs
723 $link .= 'href="javascript:;" ';
724 $link .= 'data-enc-email="' . $encoded_email . '" ';
725 }
726
727 } else {
728 $link .= $key . '="' . $value . '" ';
729 }
730 }
731
732 // remove last space
733 $link = substr( $link, 0, -1 );
734
735 $link .= '>';
736
737 $link .= ( preg_match( EEB()->settings->get_email_regex(), $display) > 0 ) ? $this->get_protected_display( $display, $protection_method ) : $display;
738
739 $link .= '</a>';
740
741 // filter
742 $link = apply_filters( 'eeb_mailto', $link, $display, $email, $attrs );
743
744 // just in case there are still email addresses f.e. within title-tag
745 $link = $this->filter_plain_emails( $link, null, 'char_encode' );
746
747 // mark link as successfullly encoded (for admin users)
748 if ( current_user_can( EEB()->settings->get_admin_cap( 'frontend-display-security-check' ) ) && $show_encoded_check ) {
749 $link .= $this->get_encoded_email_icon();
750 }
751
752
753 return $link;
754 }
755
756 /**
757 * Create a protected custom attribute
758 *
759 * @param string $display
760 * @param array $attrs Optional
761 * @return string
762 */
763 public function create_protected_href_att( $display, $attrs = array(), $protection_method = null ){
764 $email = '';
765 $class_ori = ( empty( $attrs['class'] ) ) ? '' : $attrs['class'];
766 $custom_class = (string) EEB()->settings->get_setting( 'class_name', true );
767 $show_encoded_check = (string) EEB()->settings->get_setting( 'show_encoded_check', true );
768
769 // set user-defined class
770 if ( $custom_class && strpos( $class_ori, $custom_class ) === FALSE ) {
771 $attrs['class'] = ( empty( $attrs['class'] ) ) ? $custom_class : $attrs['class'] . ' ' . $custom_class;
772 }
773
774 // check title for email address
775 if ( ! empty( $attrs['title'] ) ) {
776 $attrs['title'] = antispambot( $attrs['title'] );
777 }
778
779 // set ignore to data-attribute to prevent being processed by WPEL plugin
780 $attrs['data-wpel-link'] = 'ignore';
781
782 // create element code
783 $link = '<a ';
784
785 foreach ( $attrs AS $key => $value ) {
786 if ( strtolower( $key ) == 'href' ) {
787 $link .= $key . '="' . antispambot( $value ) . '" ';
788 } else {
789 $link .= $key . '="' . $value . '" ';
790 }
791 }
792
793 // remove last space
794 $link = substr( $link, 0, -1 );
795
796 $link .= '>';
797
798 $link .= $this->get_protected_display( $display, $protection_method );
799
800 $link .= '</a>';
801
802 // filter
803 $link = apply_filters( 'eeb_custom_href', $link, $display, $email, $attrs );
804
805 // mark link as successfullly encoded (for admin users)
806 if ( current_user_can( EEB()->settings->get_admin_cap( 'frontend-display-security-check' ) ) && $show_encoded_check ) {
807 $link .= $this->get_encoded_email_icon( 'Custom attribute encoded successfully!' );
808 }
809
810
811 return $link;
812 }
813
814 /**
815 * Create protected display combining these 3 methods:
816 * - reversing string
817 * - adding no-display spans with dummy values
818 * - using the wp antispambot function
819 *
820 * @param string|array $display
821 * @return string Protected display
822 */
823 public function get_protected_display( $display, $protection_method = null ){
824
825 $convert_plain_to_image = (bool) EEB()->settings->get_setting( 'convert_plain_to_image', true, 'filter_body' );
826 $protection_text = __( EEB()->settings->get_setting( 'protection_text', true ), 'email-encoder-bundle' );
827 $raw_display = $display;
828
829 // get display out of array (result of preg callback)
830 if ( is_array( $display ) ) {
831 $display = $display[0];
832 }
833
834 if( $convert_plain_to_image ){
835 $display = '<img src="' . $this->generate_email_image_url( $display ) . '" />';
836 } elseif( $protection_method !== 'without_javascript' ){
837 $display = $this->dynamic_js_email_encoding( $display, $protection_text );
838 } else {
839 $display = $this->encode_email_css( $display );
840 }
841
842 return apply_filters( 'eeb/validate/get_protected_display', $display, $raw_display, $protection_method, $protection_text );
843
844 }
845
846 /**
847 * Dynamic email encoding with certain javascript methods
848 *
849 * @param string $email
850 * @param string $protection_text
851 * @return the encoded email
852 */
853 public function dynamic_js_email_encoding( $email, $protection_text = null ){
854 $return = $email;
855 $rand = apply_filters( 'eeb/validate/random_encoding', rand(0,2), $email, $protection_text );
856
857 switch( $rand ){
858 case 2:
859 $return = $this->encode_escape( $return, $protection_text );
860 break;
861 case 1:
862 $return = $this->encode_ascii( $return, $protection_text );
863 break;
864 default:
865 $return = $this->encode_ascii( $return, $protection_text );
866 break;
867 }
868
869 return $return;
870 }
871
872 public function encode_email_css( $display ){
873 $deactivate_rtl = (bool) EEB()->settings->get_setting( 'deactivate_rtl', true, 'filter_body' );
874
875 $stripped_display = strip_tags( $display );
876 $stripped_display = html_entity_decode( $stripped_display );
877
878 $length = strlen( $stripped_display );
879 $interval = ceil( min( 5, $length / 2 ) );
880 $offset = 0;
881 $dummy_data = time();
882 $protected = '';
883 $protection_classes = 'eeb';
884
885 if( $deactivate_rtl ){
886 $rev = $stripped_display;
887 $protection_classes .= ' eeb-nrtl';
888 } else {
889 // reverse string ( will be corrected with CSS )
890 $rev = strrev( $stripped_display );
891 $protection_classes .= ' eeb-rtl';
892 }
893
894
895 while ( $offset < $length ) {
896 $protected .= '<span class="eeb-sd">' . antispambot( substr( $rev, $offset, $interval ) ) . '</span>';
897
898 // setup dummy content
899 $protected .= '<span class="eeb-nodis">' . $dummy_data . '</span>';
900 $offset += $interval;
901 }
902
903 $protected = '<span class="' . $protection_classes . '">' . $protected . '</span>';
904
905 return $protected;
906 }
907
908 public function email_to_image( $email, $image_string_color = 'default', $image_background_color = 'default', $alpha_string = 0, $alpha_fill = 127, $font_size = 4 ){
909
910 $setting_image_string_color = (string) EEB()->settings->get_setting( 'image_color', true, 'image_settings' );
911 $setting_image_background_color = (string) EEB()->settings->get_setting( 'image_background_color', true, 'image_settings' );
912 $image_text_opacity = (int) EEB()->settings->get_setting( 'image_text_opacity', true, 'image_settings' );
913 $image_background_opacity = (int) EEB()->settings->get_setting( 'image_background_opacity', true, 'image_settings' );
914 $image_font_size = (int) EEB()->settings->get_setting( 'image_font_size', true, 'image_settings' );
915 $image_underline = (int) EEB()->settings->get_setting( 'image_underline', true, 'image_settings' );
916 $border_padding = 0;
917 $border_offset = 2;
918 $border_height = ( is_numeric( $image_underline ) && ! empty( $image_underline ) ) ? intval( $image_underline ) : 0;
919
920 if( $image_background_color === 'default' ){
921 $image_background_color = $setting_image_background_color;
922 } else {
923 $image_background_color = '0,0,0';
924 }
925
926 $colors = explode( ',', $image_background_color );
927 $bg_red = $colors[0];
928 $bg_green = $colors[1];
929 $bg_blue = $colors[2];
930
931 if( $image_string_color === 'default' ){
932 $image_string_color = $setting_image_string_color;
933 } else {
934 $image_string_color = '0,0,0';
935 }
936
937 $colors = explode( ',', $image_string_color );
938 $string_red = $colors[0];
939 $string_green = $colors[1];
940 $string_blue = $colors[2];
941
942 if( ! empty( $image_text_opacity ) && $image_text_opacity >= 0 && $image_text_opacity <= 127 ){
943 $alpha_string = intval( $image_text_opacity );
944 }
945
946 if( ! empty( $image_background_opacity ) && $image_background_opacity >= 0 && $image_background_opacity <= 127 ){
947 $alpha_fill = intval( $image_background_opacity );
948 }
949
950 if( ! empty( $image_font_size ) && $image_font_size >= 1 && $image_font_size <= 5 ){
951 $font_size = intval( $image_font_size );
952 }
953
954 $img_width = imagefontwidth( $font_size ) * strlen( $email );
955 $img_height = imagefontheight( $font_size );
956
957 if( ! empty( $border_height ) ){
958 $img_real_height = $img_height + $border_offset + $border_height;
959 } else {
960 $img_real_height = $img_height;
961 }
962
963 $img = imagecreatetruecolor( $img_width, $img_real_height );
964 imagesavealpha( $img, true );
965 imagefill( $img, 0, 0, imagecolorallocatealpha ($img, $bg_red, $bg_green, $bg_blue, $alpha_fill ) );
966 imagestring( $img, $font_size, 0, 0, $email, imagecolorallocatealpha( $img, $string_red, $string_green, $string_blue, $alpha_string ) );
967
968
969 if( ! empty( $border_height ) ){
970 $border_fill = imagecolorallocatealpha ($img, $string_red, $string_green, $string_blue, $alpha_string );
971 imagefilledrectangle( $img, 0, $border_offset + $img_height + $border_height - 1, $border_padding + $img_width, $border_offset + $img_height, $border_fill );
972 }
973
974 ob_start();
975 imagepng( $img );
976 imagedestroy( $img );
977
978 return ob_get_clean ();
979 }
980
981 public function generate_email_signature( $email, $secret ) {
982
983 if( ! $secret ){
984 return false;
985 }
986
987 $hash_signature = apply_filters( 'eeb/validate/email_signature', 'sha256', $email );
988
989 return base64_encode( hash_hmac( $hash_signature, $email, $secret, true ) );
990 }
991
992 public function generate_email_image_url( $email ) {
993
994 if( empty( $email ) || ! is_email( $email ) ){
995 return false;
996 }
997
998 $secret = EEB()->settings->get_email_image_secret();
999 $signature = $this->generate_email_signature( $email, $secret );
1000 $url = home_url() . '?eeb_mail=' . urlencode( base64_encode( $email ) ) . '&eeb_hash=' . urlencode( $signature );
1001
1002 $url = apply_filters( 'eeb/validate/generate_email_image_url', $url, $email );
1003
1004 return $url;
1005 }
1006
1007 /**
1008 * ######################
1009 * ###
1010 * #### ENCODER FORM
1011 * ###
1012 * ######################
1013 */
1014
1015 /**
1016 * Get the encoder form (to use as a demo, like on the options page)
1017 * @return string
1018 */
1019 public function get_encoder_form() {
1020 $powered_by_setting = (bool) EEB()->settings->get_setting( 'powered_by', true, 'encoder_form' );
1021
1022 //shorten circle
1023 if(
1024 ! EEB()->helpers->is_page( $this->page_name )
1025 && ! (bool) EEB()->settings->get_setting( 'encoder_form_frontend', true, 'encoder_form' )
1026 ){
1027 return apply_filters('eeb_form_content_inactive', '' );
1028 }
1029
1030 $powered_by = '';
1031 if ($powered_by_setting) {
1032 $powered_by .= '<p class="powered-by">' . __('Powered by free', 'email-encoder-bundle') . ' <a rel="external" href="https://wordpress.org/plugins/email-encoder-bundle/">Email Encoder</a></p>';
1033 }
1034
1035 $smethods = array(
1036 'rot13' => __( 'Rot13 (Javascript)', 'email-encoder-bundle' ),
1037 'escape' => __( 'Escape (Javascript)', 'email-encoder-bundle' ),
1038 'encode' => __( 'Encode (HTML)', 'email-encoder-bundle' ),
1039 );
1040 $method_options = '';
1041 $selected = false;
1042 foreach( $smethods as $method_name => $name ) {
1043 $method_options .= '<option value="' . $method_name . '"' . ( ($selected === false ) ? ' selected="selected"' : '') . '>' . $name . '</option>';
1044 $selected = true;
1045 }
1046
1047 $labels = array(
1048 'email' => __( 'Email Address:', 'email-encoder-bundle' ),
1049 'display' => __( 'Display Text:', 'email-encoder-bundle' ),
1050 'mailto' => __( 'Mailto Link:', 'email-encoder-bundle' ),
1051 'method' => __( 'Encoding Method:', 'email-encoder-bundle' ),
1052 'create_link' => __( 'Create Protected Mail Link &gt;&gt;', 'email-encoder-bundle' ),
1053 'output' => __( 'Protected Mail Link (code):', 'email-encoder-bundle' ),
1054 'powered_by' => $powered_by,
1055 );
1056
1057 extract($labels);
1058
1059 $form = <<<FORM
1060 <div class="eeb-form">
1061 <form>
1062 <fieldset>
1063 <div class="input">
1064 <table>
1065 <tbody>
1066 <tr>
1067 <th><label for="eeb-email">{$email}</label></th>
1068 <td><input type="text" class="regular-text" id="eeb-email" name="eeb-email" /></td>
1069 </tr>
1070 <tr>
1071 <th><label for="eeb-display">{$display}</label></th>
1072 <td><input type="text" class="regular-text" id="eeb-display" name="eeb-display" /></td>
1073 </tr>
1074 <tr>
1075 <th>{$mailto}</th>
1076 <td><span class="eeb-example"></span></td>
1077 </tr>
1078 <tr>
1079 <th><label for="eeb-encode-method">{$method}</label></th>
1080 <td><select id="eeb-encode-method" name="eeb-encode-method" class="postform">
1081 {$method_options}
1082 </select>
1083 <input type="button" id="eeb-ajax-encode" name="eeb-ajax-encode" value="{$create_link}" />
1084 </td>
1085 </tr>
1086 </tbody>
1087 </table>
1088 </div>
1089 <div class="eeb-output">
1090 <table>
1091 <tbody>
1092 <tr>
1093 <th><label for="eeb-encoded-output">{$output}</label></th>
1094 <td><textarea class="large-text node" id="eeb-encoded-output" name="eeb-encoded-output" cols="50" rows="4"></textarea></td>
1095 </tr>
1096 </tbody>
1097 </table>
1098 </div>
1099 {$powered_by}
1100 </fieldset>
1101 </form>
1102 </div>
1103 FORM;
1104
1105 // apply filters
1106 $form = apply_filters('eeb_form_content', $form, $labels, $powered_by_setting );
1107
1108 return $form;
1109 }
1110
1111
1112 public function is_post_excluded( $post_id = null ){
1113
1114 $return = false;
1115 $skip_posts = (string) EEB()->settings->get_setting( 'skip_posts', true );
1116 if( ! empty( $skip_posts ) ){
1117
1118 if( empty( $post_id ) ){
1119 global $post;
1120 if( ! empty( $post ) ){
1121 $post_id = $post->ID;
1122 }
1123 } else {
1124 $post_id = intval( $post_id );
1125 }
1126
1127 $exclude_pages = explode( ',', $skip_posts );
1128
1129 if( is_array( $exclude_pages ) ){
1130 $exclude_pages_validated = array();
1131
1132 foreach( $exclude_pages as $spost_id ){
1133 $spost_id = trim($spost_id);
1134 if( is_numeric( $spost_id ) ){
1135 $exclude_pages_validated[] = intval( $spost_id );
1136 }
1137 }
1138
1139 if ( in_array( $post_id, $exclude_pages_validated ) ) {
1140 $return = true;
1141 }
1142 }
1143
1144 }
1145
1146 return apply_filters( 'eeb/validate/is_post_excluded', $return, $post_id, $skip_posts );
1147 }
1148
1149 /**
1150 * Filter if to exclude specific URL parameters from filtering
1151 *
1152 * @since 2.2.0
1153 * @param array $parameters
1154 * @return boolean
1155 */
1156 public function is_query_parameter_excluded( $parameters = null ){
1157
1158 if( $parameters === null ){
1159 $parameters = $_GET;
1160 }
1161
1162 $return = false;
1163 $skip_query_parameters = (string) EEB()->settings->get_setting( 'skip_query_parameters', true );
1164 if( ! empty( $skip_query_parameters ) && ! empty( $parameters ) ){
1165
1166 $excluded_parameters = explode( ',', $skip_query_parameters );
1167
1168 if( is_array( $excluded_parameters ) ){
1169
1170 foreach( $excluded_parameters as $param ){
1171 $param = trim($param);
1172
1173 if( isset( $parameters[ $param ] ) ){
1174 $return = true;
1175 break;
1176 }
1177 }
1178
1179 }
1180
1181 }
1182
1183 return apply_filters( 'eeb/validate/is_query_parameter_excluded', $return, $parameters );
1184 }
1185 }
1186