PluginProbe ʕ •ᴥ•ʔ
Email Encoder – Protect Email Addresses and Phone Numbers / 2.4.2
Email Encoder – Protect Email Addresses and Phone Numbers v2.4.2
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 / src / Validate / Encoding.php
email-encoder-bundle / src / Validate Last commit date
EncoderForm.php 5 months ago Encoding.php 5 months ago Filters.php 5 months ago Validate.php 5 months ago
Encoding.php
559 lines
1 <?php
2
3 namespace OnlineOptimisation\EmailEncoderBundle\Validate;
4
5 use OnlineOptimisation\EmailEncoderBundle\Traits\PluginHelper;
6
7 class Encoding
8 {
9 use PluginHelper;
10
11 private string $at_identifier;
12
13 public function boot(): void
14 {
15 $this->at_identifier = $this->settings()->get_at_identifier();
16 }
17
18
19 /**
20 * ######################
21 * ###
22 * #### ENCODINGS
23 * ###
24 * ######################
25 */
26
27 public function temp_encode_at_symbol( $content, $decode = false )
28 {
29 if ( $decode ) {
30 return str_replace( $this->at_identifier, '@', $content );
31 }
32
33 return str_replace( '@', $this->at_identifier, $content );
34 }
35
36 /**
37 * ASCII method
38 *
39 * @param string $value
40 * @param string $protection_text
41 * @return string
42 */
43 public function encode_ascii($value, $protection_text)
44 {
45 $mail_link = $value;
46
47 // first encode, so special chars can be supported
48 $mail_link = $this->helper()->encode_uri_components( $mail_link );
49
50 $mail_letters = '';
51
52 for ( $i = 0; $i < strlen( $mail_link ); $i++ ) {
53 $l = substr($mail_link, $i, 1);
54
55 if (strpos($mail_letters, $l) === false) {
56 $p = rand(0, strlen($mail_letters));
57 $mail_letters = substr($mail_letters, 0, $p) .
58 $l . substr($mail_letters, $p, strlen($mail_letters));
59 }
60 }
61
62 $mail_letters_enc = str_replace( "\\", "\\\\", $mail_letters );
63 $mail_letters_enc = str_replace( "\"", "\\\"", $mail_letters_enc );
64
65 $mail_indices = '';
66 for ( $i = 0; $i < strlen( $mail_link ); $i++ ) {
67 $index = strpos( $mail_letters, substr( $mail_link, $i, 1 ) );
68 $index += 48;
69 $mail_indices .= chr( $index );
70 }
71
72 $mail_indices = str_replace("\\", "\\\\", $mail_indices);
73 $mail_indices = str_replace("\"", "\\\"", $mail_indices);
74
75 $element_id = 'eeb-' . mt_rand( 0, 1000000 ) . '-' . mt_rand(0, 1000000);
76
77 return '<span id="' . $element_id . '"></span>'
78 . '<script type="text/javascript">'
79 . '(function() {'
80 . 'var ml="' . $mail_letters_enc . '",mi="' . $mail_indices . '",o="";'
81 . 'for(var j=0,l=mi.length;j<l;j++) {'
82 . 'o+=ml.charAt(mi.charCodeAt(j)-48);'
83 . '}document.getElementById("' . $element_id . '").innerHTML = decodeURIComponent(o);' // decode at the end, this way special chars can be supported
84 . '}());'
85 . '</script><noscript>'
86 . $protection_text
87 . '</noscript>'
88 ;
89 }
90
91 /**
92 * Escape encoding method
93 *
94 * @param string $value
95 * @param string $protection_text
96 * @return string
97 */
98 public function encode_escape( $value, $protection_text )
99 {
100 $element_id = 'eeb-' . mt_rand( 0, 1000000 ) . '-' . mt_rand( 0, 1000000 );
101 $string = '\'' . $value . '\'';
102
103 //Validate escape sequences
104 $string = preg_replace('/\s+/S', " ", $string);
105
106 // break string into array of characters, we can't use string_split because its php5 only
107 $split = preg_split( '||', $string );
108 $out = '<span id="' . $element_id . '"></span>'
109 . '<script type="text/javascript">' . 'document.getElementById("' . $element_id . '").innerHTML = ev' . 'al(decodeURIComponent("';
110
111 foreach ( $split as $c ) {
112 // preg split will return empty first and last characters, check for them and ignore
113 if ( ! empty( $c ) || $c === '0' ) {
114 $out .= '%' . dechex( ord( $c ) );
115 }
116 }
117
118 $out .= '"))' . '</script><noscript>'
119 . $protection_text
120 . '</noscript>';
121
122 return $out;
123 }
124
125 /**
126 * Encode email in input field
127 * @param string $input
128 * @param string $email
129 * @return string
130 */
131 public function encode_input_field( $input, $email, $strongEncoding = false )
132 {
133
134 $show_encoded_check = (bool) $this->getSetting( 'show_encoded_check', true );
135
136 if ( $strongEncoding === false ) {
137 // encode email with entities (default wp method)
138 $sub_return = str_replace( $email, antispambot( $email ), $input );
139
140 if ( current_user_can( $this->getAdminCap( 'frontend-display-security-check' ) ) && $show_encoded_check ) {
141 $sub_return .= $this->get_encoded_email_icon();
142 }
143
144 return $sub_return;
145 }
146
147 // add data-enc-email after "<input"
148 $inputWithDataAttr = substr( $input, 0, 6 );
149 $inputWithDataAttr .= ' data-enc-email="' . $this->get_encoded_email( $email ) . '"';
150 $inputWithDataAttr .= substr( $input, 6 );
151
152 // mark link as successfullly encoded (for admin users)
153 if ( current_user_can( $this->getAdminCap( 'frontend-display-security-check' ) ) && $show_encoded_check ) {
154 $inputWithDataAttr .= $this->get_encoded_email_icon();
155 }
156
157 // remove email from value attribute
158 $encInput = str_replace( $email, '', $inputWithDataAttr );
159
160 return $encInput;
161 }
162
163 /**
164 * Get encoded email, used for data-attribute (translate by javascript)
165 *
166 * @param string $email
167 * @return string
168 */
169 public function get_encoded_email( $email )
170 {
171 $encEmail = $email;
172
173 // decode entities
174 $encEmail = html_entity_decode( $encEmail );
175
176 // rot13 encoding
177 $encEmail = str_rot13( $encEmail );
178
179 // replace @
180 $encEmail = str_replace( '@', '[at]', $encEmail );
181
182 return $encEmail;
183 }
184
185 /**
186 * Get the ebcoded email icon
187 *
188 * @param string $text
189 * @return string
190 */
191 public function get_encoded_email_icon( $text = 'Email encoded successfully!' )
192 {
193
194 $html = '<i class="eeb-encoded dashicons-before dashicons-lock" title="' . __( $text, 'email-encoder-bundle' ) . '"></i>';
195
196 return apply_filters( 'eeb/validate/get_encoded_email_icon', $html, $text );
197 }
198
199 /**
200 * Create a protected email
201 *
202 * @param string $display
203 * @param array $attrs Optional
204 * @return string
205 */
206 public function create_protected_mailto( $display, $attrs = array(), $protection_method = null )
207 {
208 $email = '';
209 $class_ori = ( empty( $attrs['class'] ) ) ? '' : $attrs['class'];
210 $custom_class = (string) $this->getSetting( 'class_name', true );
211 $show_encoded_check = (string) $this->getSetting( 'show_encoded_check', true );
212
213 // set user-defined class
214 if ( $custom_class !== '' && strpos( $class_ori, $custom_class ) === false ) {
215 $attrs['class'] = ( empty( $attrs['class'] ) ) ? $custom_class : $attrs['class'] . ' ' . $custom_class;
216 }
217
218 // check title for email address
219 if ( ! empty( $attrs['title'] ) ) {
220 $attrs['title'] = $this->filterPlainEmails( $attrs['title'], '{{email}}' ); // {{email}} will be replaced in javascript
221 }
222
223 // set ignore to data-attribute to prevent being processed by WPEL plugin
224 $attrs['data-wpel-link'] = 'ignore';
225
226 // create element code
227 $link = '<a ';
228
229 foreach ( $attrs as $key => $value ) {
230 if ( strtolower( $key ) === 'href' ) {
231 if ( $protection_method === 'without_javascript' ) {
232 $link .= $key . '="' . antispambot( $value ) . '" ';
233 } else {
234 // get email from href
235 $email = substr($value, 7);
236
237 $encoded_email = $this->get_encoded_email( $email );
238
239 // set attrs
240 $link .= 'href="javascript:;" ';
241 $link .= 'data-enc-email="' . $encoded_email . '" ';
242 }
243
244 } else {
245 $link .= $key . '="' . $value . '" ';
246 }
247 }
248
249 // remove last space
250 $link = substr( $link, 0, -1 );
251
252 $link .= '>';
253
254 $link .= ( preg_match( $this->settings()->get_email_regex(), $display) > 0 ) ? $this->get_protected_display( $display, $protection_method ) : $display;
255
256 $link .= '</a>';
257
258 // filter
259 $link = apply_filters( 'eeb_mailto', $link, $display, $email, $attrs );
260
261 // just in case there are still email addresses f.e. within title-tag
262 $link = $this->filterPlainEmails( $link, null, 'char_encode' );
263
264 // mark link as successfullly encoded (for admin users)
265 if ( current_user_can( $this->getAdminCap( 'frontend-display-security-check' ) ) && $show_encoded_check !== '' ) {
266 $link .= $this->get_encoded_email_icon();
267 }
268
269
270 return $link;
271 }
272
273 /**
274 * Create a protected custom attribute
275 *
276 * @param string $display
277 * @param array $attrs Optional
278 * @return string
279 */
280 public function create_protected_href_att( $display, $attrs = array(), $protection_method = null )
281 {
282 $email = '';
283 $class_ori = ( empty( $attrs['class'] ) ) ? '' : $attrs['class'];
284 $custom_class = (string) $this->getSetting( 'class_name', true );
285 $show_encoded_check = (string) $this->getSetting( 'show_encoded_check', true );
286
287 // set user-defined class
288 if ( $custom_class !== '' && strpos( $class_ori, $custom_class ) === false ) {
289 $attrs['class'] = ( empty( $attrs['class'] ) ) ? $custom_class : $attrs['class'] . ' ' . $custom_class;
290 }
291
292 // check title for email address
293 if ( ! empty( $attrs['title'] ) ) {
294 $attrs['title'] = antispambot( $attrs['title'] );
295 }
296
297 // set ignore to data-attribute to prevent being processed by WPEL plugin
298 $attrs['data-wpel-link'] = 'ignore';
299
300 // create element code
301 $link = '<a ';
302
303 foreach ( $attrs as $key => $value ) {
304 if ( strtolower( $key ) === 'href' ) {
305 $link .= $key . '="' . antispambot( $value ) . '" ';
306 } else {
307 $link .= $key . '="' . $value . '" ';
308 }
309 }
310
311 // remove last space
312 $link = substr( $link, 0, -1 );
313
314 $link .= '>';
315
316 $link .= $this->get_protected_display( $display, $protection_method );
317
318 $link .= '</a>';
319
320 // filter
321 $link = apply_filters( 'eeb_custom_href', $link, $display, $email, $attrs );
322
323 // mark link as successfullly encoded (for admin users)
324 if ( current_user_can( $this->getAdminCap( 'frontend-display-security-check' ) ) && $show_encoded_check ) {
325 $link .= $this->get_encoded_email_icon( 'Custom attribute encoded successfully!' );
326 }
327
328
329 return $link;
330 }
331
332 /**
333 * Create protected display combining these 3 methods:
334 * - reversing string
335 * - adding no-display spans with dummy values
336 * - using the wp antispambot function
337 *
338 * @param string|array $display
339 * @return string Protected display
340 */
341 public function get_protected_display( $display, $protection_method = null )
342 {
343
344 $convert_plain_to_image = (bool) $this->getSetting( 'convert_plain_to_image', true, 'filter_body' );
345 $protection_text = __( $this->getSetting( 'protection_text', true ), 'email-encoder-bundle' );
346 $raw_display = $display;
347
348 // get display out of array (result of preg callback)
349 if ( is_array( $display ) ) {
350 $display = $display[0];
351 }
352
353 if ( $convert_plain_to_image ) {
354 $display = '<img src="' . $this->generate_email_image_url( $display ) . '" />';
355 } elseif ( $protection_method !== 'without_javascript' ) {
356 $display = $this->dynamic_js_email_encoding( $display, $protection_text );
357 } else {
358 $display = $this->encode_email_css( $display );
359 }
360
361 return apply_filters( 'eeb/validate/get_protected_display', $display, $raw_display, $protection_method, $protection_text );
362 }
363
364 /**
365 * Dynamic email encoding with certain javascript methods
366 *
367 * @param string $email
368 * @param string $protection_text
369 * @return string the encoded email
370 */
371 public function dynamic_js_email_encoding( $email, $protection_text = null )
372 {
373 $return = $email;
374 $rand = apply_filters( 'eeb/validate/random_encoding', rand( 0, 2 ), $email, $protection_text );
375
376 switch ( $rand ) {
377 case 2:
378 $return = $this->encode_escape( $return, $protection_text );
379 break;
380 case 1:
381 $return = $this->encode_ascii( $return, $protection_text );
382 break;
383 default:
384 $return = $this->encode_ascii( $return, $protection_text );
385 break;
386 }
387
388 return $return;
389 }
390
391 public function encode_email_css( $display )
392 {
393 $deactivate_rtl = (bool) $this->getSetting( 'deactivate_rtl', true, 'filter_body' );
394
395 // $this->log( 'display: ' . $display );
396 $stripped_display = strip_tags( $display );
397 $stripped_display = html_entity_decode( $stripped_display );
398
399 $length = strlen( $stripped_display );
400 $interval = ceil( min( 5, $length / 2 ) );
401 $offset = 0;
402 $dummy_data = time();
403 $protected = '';
404 $protection_classes = 'eeb';
405
406 if ( $deactivate_rtl ) {
407 $rev = $stripped_display;
408 $protection_classes .= ' eeb-nrtl';
409 } else {
410 // reverse string ( will be corrected with CSS )
411 $rev = strrev( $stripped_display );
412 $protection_classes .= ' eeb-rtl';
413 }
414
415
416 while ( $offset < $length ) {
417 $protected .= '<span class="eeb-sd">' . antispambot( substr( $rev, $offset, $interval ) ) . '</span>';
418
419 // setup dummy content
420 $protected .= '<span class="eeb-nodis">' . $dummy_data . '</span>';
421 $offset += $interval;
422 }
423
424 $protected = '<span class="' . $protection_classes . '">' . $protected . '</span>';
425
426 return $protected;
427 }
428
429 public function email_to_image( $email, $image_string_color = 'default', $image_background_color = 'default', $alpha_string = 0, $alpha_fill = 127, $font_size = 4 )
430 {
431
432 $setting_image_string_color = (string) $this->getSetting( 'image_color', true, 'image_settings' );
433 $setting_image_background_color = (string) $this->getSetting( 'image_background_color', true, 'image_settings' );
434 $image_text_opacity = (int) $this->getSetting( 'image_text_opacity', true, 'image_settings' );
435 $image_background_opacity = (int) $this->getSetting( 'image_background_opacity', true, 'image_settings' );
436 $image_font_size = (int) $this->getSetting( 'image_font_size', true, 'image_settings' );
437 $image_underline = (int) $this->getSetting( 'image_underline', true, 'image_settings' );
438 $border_padding = 0;
439 $border_offset = 2;
440 $border_height = ( is_numeric( $image_underline ) && ! empty( $image_underline ) )
441 ? intval( $image_underline )
442 : 0
443 ;
444
445 if ( $image_background_color === 'default' ) {
446 $image_background_color = $setting_image_background_color;
447 } else {
448 $image_background_color = '0,0,0';
449 }
450
451 $colors = explode( ',', $image_background_color );
452 $bg_red = $colors[0];
453 $bg_green = $colors[1];
454 $bg_blue = $colors[2];
455
456 if ( $image_string_color === 'default' ) {
457 $image_string_color = $setting_image_string_color;
458 } else {
459 $image_string_color = '0,0,0';
460 }
461
462 $colors = explode( ',', $image_string_color );
463 $string_red = $colors[0];
464 $string_green = $colors[1];
465 $string_blue = $colors[2];
466
467 if (
468 ! empty( $image_text_opacity )
469 && $image_text_opacity >= 0
470 && $image_text_opacity <= 127
471 ) {
472 $alpha_string = intval( $image_text_opacity );
473 }
474
475 if (
476 ! empty( $image_background_opacity )
477 && $image_background_opacity >= 0
478 && $image_background_opacity <= 127
479 ) {
480 $alpha_fill = intval( $image_background_opacity );
481 }
482
483 if ( ! empty( $image_font_size ) && $image_font_size >= 1 && $image_font_size <= 5 ) {
484 $font_size = intval( $image_font_size );
485 }
486
487 $img_width = imagefontwidth( $font_size ) * strlen( $email );
488 $img_height = imagefontheight( $font_size );
489
490 if ( ! empty( $border_height ) ) {
491 $img_real_height = $img_height + $border_offset + $border_height;
492 } else {
493 $img_real_height = $img_height;
494 }
495
496 $img = imagecreatetruecolor( $img_width, $img_real_height );
497 imagesavealpha( $img, true );
498 imagefill( $img, 0, 0, imagecolorallocatealpha ($img, $bg_red, $bg_green, $bg_blue, $alpha_fill ) );
499 imagestring(
500 $img,
501 $font_size,
502 0,
503 0,
504 $email,
505 imagecolorallocatealpha( $img, $string_red, $string_green, $string_blue, $alpha_string )
506 );
507
508
509 if ( ! empty( $border_height ) ) {
510 $border_fill = imagecolorallocatealpha ($img, $string_red, $string_green, $string_blue, $alpha_string );
511 imagefilledrectangle(
512 $img,
513 0,
514 $border_offset + $img_height + $border_height - 1,
515 $border_padding + $img_width,
516 $border_offset + $img_height,
517 $border_fill
518 );
519 }
520
521 ob_start();
522 imagepng( $img );
523 imagedestroy( $img );
524
525 return ob_get_clean ();
526 }
527
528 public function generate_email_signature( $email, $secret )
529 {
530
531 if ( ! $secret ) {
532 return false;
533 }
534
535 $hash_signature = apply_filters( 'eeb/validate/email_signature', 'sha256', $email );
536
537 return base64_encode( hash_hmac( $hash_signature, $email, $secret, true ) );
538 }
539
540 public function generate_email_image_url( $email )
541 {
542
543 if ( ! function_exists( 'imagefontwidth' ) || empty( $email ) || ! is_email( $email ) ) {
544 return false;
545 }
546
547 $secret = $this->settings()->get_email_image_secret();
548 $signature = $this->generate_email_signature( $email, $secret );
549 $url = home_url();
550 $url .= '?eeb_mail=' . urlencode( base64_encode( $email ) );
551 $url .= '&eeb_hash=' . urlencode( $signature );
552
553 $url = apply_filters( 'eeb/validate/generate_email_image_url', $url, $email );
554
555 return $url;
556 }
557
558 }
559