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