PluginProbe
CryptX / 3.4
CryptX v3.4
4.2.0 4.1.1 trunk 1.0 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.9 2.0 2.1 2.2 2.3 2.3.1 2.3.2 2.3.3 2.4.0 2.4.1 2.4.2 2.4.3 2.4.4 2.4.5 All 92 releases
cryptx / classes / CryptX.php

CryptX.php in CryptX 3.4, at classes/CryptX.php

824 lines 26.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace CryptX;
4
5 class CryptX {
6
7 const NOT_FOUND = false;
8 const MAIL_IDENTIFIER = 'mailto:';
9 const SUBJECT_IDENTIFIER = "?subject=";
10 const INDEX_TO_CHECK = 4;
11 const PATTERN = '/(.*)(">)/i';
12 const ASCII_VALUES_BLACKLIST = ['32', '34', '39', '60', '62', '63', '92', '94', '96', '127'];
13
14 private static ?CryptX $_instance = null;
15 private static mixed $cryptXOptions = null;
16 private static array $defaults = array(
17 'version' => null,
18 'at' => ' [at] ',
19 'dot' => ' [dot] ',
20 'css_id' => '',
21 'css_class' => '',
22 'the_content' => 1,
23 'the_meta_key' => 1,
24 'the_excerpt' => 1,
25 'comment_text' => 1,
26 'widget_text' => 1,
27 'java' => 1,
28 'load_java' => 1,
29 'opt_linktext' => 0,
30 'autolink' => 1,
31 'alt_linktext' => '',
32 'alt_linkimage' => '',
33 'http_linkimage_title' => '',
34 'alt_linkimage_title' => '',
35 'excludedIDs' => '',
36 'metaBox' => 1,
37 'alt_uploadedimage' => '0',
38 'c2i_font' => null,
39 'c2i_fontSize' => 10,
40 'c2i_fontRGB' => '#000000',
41 'echo' => 1,
42 'filter' => array('the_content','the_meta_key','the_excerpt','comment_text','widget_text'),
43 'whiteList' => 'jpeg,jpg,png,gif',
44 );
45 private static int $imageCounter = 0;
46 private function __construct()
47 {
48 self::$cryptXOptions = $this->loadCryptXOptionsWithDefaults();
49 }
50
51 /**
52 * Get the instance of the CryptX class.
53 *
54 * This method returns the instance of the CryptX class. If an instance does not exist,
55 * it creates a new instance of the CryptX class and stores it in the static property.
56 * Subsequent calls to this method will return the previously created instance.
57 *
58 * @return CryptX The instance of the CryptX class.
59 */
60 public static function getInstance(): CryptX
61 {
62 if ( ! ( self::$_instance instanceof self) ) {
63 self::$_instance = new self();
64 }
65 return self::$_instance;
66 }
67
68 function startCryptX(): void {
69 if( isset( self::$cryptXOptions['version'] ) && version_compare(CRYPTX_VERSION, self::$cryptXOptions['version']) > 0 ) {
70 $this->updateCryptXSettings();
71 }
72 foreach(self::$cryptXOptions['filter'] as $filter) {
73 if (@self::$cryptXOptions[$filter]) {
74 $this->addPluginFilters($filter);
75 }
76 }
77 add_action( 'activate_' . CRYPTX_BASENAME, [$this, 'installCryptX' ] );
78 add_action( 'wp_enqueue_scripts', [$this, 'loadJavascriptFiles' ] );
79 if (@self::$cryptXOptions['metaBox']) {
80 add_action('admin_menu', [$this, 'metaBox' ]);
81 add_action('wp_insert_post', [$this, 'addPostIdToExcludedList' ] );
82 add_action('wp_update_post', [$this, 'addPostIdToExcludedList' ] );
83 }
84 add_filter( 'plugin_row_meta', 'rw_cryptx_init_row_meta', 10, 2 );
85 add_filter( 'init', [$this, 'cryptXtinyUrl' ]);
86 add_shortcode( 'cryptx', [$this, 'cryptXShortcode']);
87 }
88
89 /**
90 * Returns an array of default options for CryptX.
91 *
92 * This function retrieves an array of default options for CryptX. The default options include
93 * the current version of CryptX and the first available TrueType font from the "fonts" directory.
94 *
95 * @return array The array of default options.
96 */
97 function getCryptXOptionsDefaults(): array
98 {
99 $firstFont = $this->getFilesInDirectory( CRYPTX_DIR_PATH . 'fonts', "ttf");
100 return array_merge(self::$defaults, [ 'version' => CRYPTX_VERSION, 'c2i_font' => $firstFont[0] ]);
101 }
102
103 /**
104 * Loads the cryptX options with default values.
105 *
106 * @return array The cryptX options array with default values.
107 */
108 function loadCryptXOptionsWithDefaults(): array
109 {
110 $defaultValues = $this->getCryptXOptionsDefaults();
111 $currentOptions = get_option('cryptX');
112 return wp_parse_args($currentOptions, $defaultValues);
113 }
114
115 /**
116 * Saves the cryptX options by updating the 'cryptX' option with the saved options merged with the default options.
117 *
118 * @param array $saveOptions The options to be saved.
119 *
120 * @return void
121 */
122 function saveCryptXOptions( array $saveOptions): void {
123 update_option( 'cryptX', wp_parse_args( $saveOptions, $this->loadCryptXOptionsWithDefaults() ) );
124 }
125
126 /**
127 * The shortcode function is used to process the content passed to it and apply the necessary encryption and linking.
128 *
129 * @param string|null $content The content to be processed. Default is null.
130 *
131 * @return string The processed content with encryption and linking applied.
132 */
133 function cryptXShortcode( string $content = null): string
134 {
135 if (@self::$cryptXOptions['autolink']) {
136 $content = $this->addLinkToEmailAddresses($content, true);
137 }
138
139 return $this->encryptAndLinkContent($content);
140 }
141
142 /**
143 * Encrypts and links content.
144 *
145 * @param string $content The content to be encrypted and linked.
146 *
147 * @return string The encrypted and linked content.
148 */
149 function encryptAndLinkContent( string $content): string {
150 $content = $this->findEmailAddressesInContent($content, true);
151 $content = $this->replaceEmailInContent($content, true);
152 return $content;
153 }
154 /**
155 * create image from tinyurl
156 *
157 * @return image
158 */
159 function cryptXtinyUrl() : void
160 {
161 $url = $_SERVER['REQUEST_URI'];
162 $params = explode( '/', $url );
163 if ( count( $params ) > 1 ) {
164 $tiny_url = $params[count( $params ) -2];
165 if ( $tiny_url == md5( get_bloginfo('url') ) ) {
166 $font = CRYPTX_DIR_PATH . 'fonts/' . self::$cryptXOptions['c2i_font'];
167 $msg = $params[count( $params ) -1];
168 $size = self::$cryptXOptions['c2i_fontSize'];
169 $pad = 1;
170 $transparent = 1;
171 $rgb = str_replace("#", "", self::$cryptXOptions['c2i_fontRGB']);
172 $red = hexdec(substr($rgb,0,2));
173 $grn = hexdec(substr($rgb,2,2));
174 $blu = hexdec(substr($rgb,4,2));
175 $bg_red = 255 - $red;
176 $bg_grn = 255 - $grn;
177 $bg_blu = 255 - $blu;
178 $width = 0;
179 $height = 0;
180 $offset_x = 0;
181 $offset_y = 0;
182 $bounds = array();
183 $image = "";
184 $bounds = ImageTTFBBox($size, 0, $font, "W");
185 $font_height = abs($bounds[7]-$bounds[1]);
186 $bounds = ImageTTFBBox($size, 0, $font, $msg);
187 $width = abs($bounds[4]-$bounds[6]);
188 $height = abs($bounds[7]-$bounds[1]);
189 $offset_y = $font_height+abs(($height - $font_height)/2)-1;
190 $offset_x = 0;
191 $image = imagecreatetruecolor($width+($pad*2),$height+($pad*2));
192 imagesavealpha($image, true);
193 $foreground = ImageColorAllocate($image, $red, $grn, $blu);
194 $background = imagecolorallocatealpha($image, 0, 0, 0, 127);
195 imagefill($image, 0, 0, $background);
196 ImageTTFText($image, $size, 0, $offset_x+$pad, $offset_y+$pad, $foreground, $font, $msg);
197 Header("Content-type: image/png");
198 imagePNG($image);
199 die;
200 }
201 }
202 }
203
204 /**
205 * Add plugin filters.
206 *
207 * This function adds the specified plugin filter if the 'autolink' key is present and its value is true in the global $cryptXOptions variable.
208 * It also adds the 'autolink' function as a filter to the $filterName if the global $shortcode_tags variable is not empty.
209 * Additionally, this function calls the addCommonFilters() and addOtherFilters() functions at specific points.
210 *
211 * @param string $filterName The name of the filter to add.
212 *
213 * @return void
214 */
215 function addPluginFilters( string $filterName): void
216 {
217 global $shortcode_tags;
218 if ( array_key_exists('autolink', self::$cryptXOptions) && self::$cryptXOptions['autolink']) {
219 $this->addAutoLinkFilters($filterName);
220 if (!empty($shortcode_tags)) {
221 $this->addAutoLinkFilters($filterName, 11);
222 //add_filter($filterName, [$this,'autolink'], 11);
223 }
224 }
225 $this->addOtherFilters($filterName);
226 }
227
228 /**
229 * Adds common filters to a given filter name.
230 *
231 * This function adds the common filter 'autolink' to the provided $filterName.
232 *
233 * @param string $filterName The name of the filter to add common filters to.
234 *
235 * @return void
236 */
237 function addAutoLinkFilters( string $filterName, $prio = 5): void
238 {
239 add_filter($filterName, [$this, 'addLinkToEmailAddresses' ], $prio);
240 }
241
242 /**
243 * Adds additional filters to a given filter name.
244 *
245 * This function adds two additional filters, 'encryptx' and 'replaceEmailInContent',
246 * to the specified filter name. The 'encryptx' filter is added with a priority of 12,
247 * and the 'replaceEmailInContent' filter is added with a priority of 13.
248 *
249 * @param string $filterName The name of the filter to add the additional filters to.
250 *
251 * @return void
252 */
253 function addOtherFilters( string $filterName): void
254 {
255 add_filter($filterName, [$this, 'findEmailAddressesInContent' ], 12);
256 add_filter($filterName, [$this,'replaceEmailInContent'], 13);
257 }
258
259 /**
260 * Checks if a given ID is excluded based on the 'excludedIDs' variable.
261 *
262 * @param int $ID The ID to check if excluded.
263 *
264 * @return bool Returns true if the ID is excluded, false otherwise.
265 */
266 function isIdExcluded( int $ID): bool
267 {
268 $excludedIds = explode(",", self::$cryptXOptions['excludedIDs']);
269 return in_array($ID, $excludedIds);
270 }
271
272 /**
273 * Replaces email addresses with link text in the given content.
274 *
275 * This function replaces email addresses in the provided content with link text. If the current post
276 * ID is not excluded or the `isShortcode` parameter is set to true, the email addresses will be replaced.
277 *
278 * @param string $content The
279 */
280 function replaceEmailInContent( string $content, bool $isShortcode=false): string {
281 global $post;
282 $postId = (is_object($post))? $post->ID : -1;
283 if ( !$this->isIdExcluded($postId) || $isShortcode ) {
284 $content = $this->replaceEmailWithLinkText($content);
285 }
286 return $content;
287 }
288
289 /**
290 * Replace email addresses in a given content with link text.
291 *
292 * @param string $content The content to search for email addresses.
293 *
294 * @return string The content with email addresses replaced with link text.
295 */
296 function replaceEmailWithLinkText( string $content): string
297 {
298 $emailPattern = "/([_a-zA-Z0-9-+]+(\.[_a-zA-Z0-9-+]+)*@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*(\.[a-zA-Z]{2,}))/i";
299 return preg_replace_callback($emailPattern, [$this,'encodeEmailToLinkText'], $content );
300 }
301
302 /**
303 * Encode email address to link text.
304 *
305 * @param array $Match The matched email address.
306 *
307 * @return array|string The encoded link text.
308 */
309 function encodeEmailToLinkText( array $Match): array|string {
310 if($this->in_white_list($Match)) return $Match[1];
311 switch (self::$cryptXOptions['opt_linktext']) {
312 case 1:
313 $text = $this->getLinkText();
314 break;
315 case 2:
316 $text = $this->getLinkImage();
317 break;
318 case 3:
319 $img_url = wp_get_attachment_url( self::$cryptXOptions['alt_uploadedimage'] );
320 $text = $this->getUploadedImage($img_url);
321 self::$imageCounter++;
322 break;
323 case 4:
324 $text = antispambot($Match[1]);
325 break;
326 case 5:
327 $text = $this->getImageFromText($Match);
328 self::$imageCounter++;
329 break;
330 default:
331 $text = $this->getDefaultLinkText($Match);
332 }
333
334 return $text;
335 }
336
337 /**
338 * Check if the given match is in the whitelist.
339 *
340 * @param array $Match The match to check against the whitelist.
341 *
342 * @return bool True if the match is in the whitelist, false otherwise.
343 */
344 function in_white_list( array $Match): bool
345 {
346 $whiteList = array_filter(array_map('trim', explode(",", self::$cryptXOptions['whiteList'])));
347 $tmp = explode(".", $Match[0]);
348 return in_array(end($tmp), $whiteList);
349 }
350
351 /**
352 * Get the link text from cryptXOptions
353 *
354 * @return string The link text
355 */
356 function getLinkText(): string {
357 return self::$cryptXOptions['alt_linktext'];
358 }
359
360 /**
361 * Generate an HTML image tag with the link image URL as the source
362 *
363 * @return string The HTML image tag
364 */
365 function getLinkImage(): string
366 {
367 return "<img src=\"" . self::$cryptXOptions['alt_linkimage'] . "\" class=\"cryptxImage\" alt=\"" . self::$cryptXOptions['alt_linkimage_title'] . "\" title=\"" . antispambot(self::$cryptXOptions['alt_linkimage_title']) . "\" />";
368 }
369
370 /**
371 * Get the HTML tag for an uploaded image.
372 *
373 * @param string $img_url The URL of the image.
374 *
375 * @return string The HTML tag for the image.
376 */
377 function getUploadedImage( string $img_url): string
378 {
379 return "<img src=\"" . $img_url . "\" class=\"cryptxImage cryptxImage_" . self::$imageCounter . "\" alt=\"" . self::$cryptXOptions['http_linkimage_title'] . " title=\"" . antispambot( self::$cryptXOptions['http_linkimage_title']) . "\" />";
380 }
381
382 /**
383 * Converts a matched image URL into an HTML image element with cryptX classes and attributes.
384 *
385 * @param array $Match The matched image URL and other related data.
386 *
387 * @return string Returns the HTML image element.
388 */
389 function getImageFromText( array $Match): string
390 {
391 return "<img src=\"" . get_bloginfo('url') . "/" . md5( get_bloginfo('url') ) . "/" . antispambot($Match[1]) . "\" class=\"cryptxImage cryptxImage_" . self::$imageCounter . "\" alt=\"" . antispambot($Match[1]) . "\" title=\"" . antispambot($Match[1]) . "\" />";
392 }
393
394 /**
395 * Replaces specific characters with values from cryptX options in a given string.
396 *
397 * @param array $Match The array containing matches from a regular expression search.
398 * Array format: `[0 => string, 1 => string, ...]`.
399 * The first element is ignored, and the second element is used as input string.
400 *
401 * @return array|string The string with replaced characters or the original array if no matches were found.
402 * If the input string is an array, the function returns an array with replaced characters
403 * for each element.
404 */
405 function getDefaultLinkText( array $Match): array|string
406 {
407 $text = str_replace("@", self::$cryptXOptions['at'], $Match[1]);
408 return str_replace(".", self::$cryptXOptions['dot'], $text);
409 }
410
411 /**
412 * List all files in a directory that match the given filter.
413 *
414 * @param string $path The path of the directory to list files from.
415 * @param array|string $filter The file extensions to filter by.
416 * If it's a string, it will be converted to an array of a single element.
417 *
418 * @return array An array of file names that match the filter.
419 */
420 function getFilesInDirectory( string $path, array|string $filter): array
421 {
422 if(!is_array($filter)) {
423 $filter = (array) $filter;
424 }
425 $directoryHandle = opendir($path);
426 $directoryContent = array();
427 while ($file = readdir($directoryHandle)) {
428 $fileExtension = substr(strtolower($file), -3);
429 if (in_array($fileExtension, $filter)) {
430 $directoryContent[] = $file;
431 }
432 }
433 return $directoryContent;
434 }
435
436 /**
437 * Encrypts email addresses in the given content
438 *
439 * @param string $content The content to be encrypted
440 * @param bool $shortcode Whether to encrypt email addresses even if post ID is excluded
441 *
442 * @return string The encrypted content
443 */
444 function findEmailAddressesInContent( string $content, bool $shortcode = false): string
445 {
446 global $post;
447 $postId = (is_object($post))? $post->ID : -1;
448
449 $isIdExcluded = $this->isIdExcluded($postId);
450 $mailtoRegex = '/<a (.*?)(href=("|\')mailto:(.*?)("|\')(.*?)|)>\s*(.*?)\s*<\/a>/i';
451
452 if ((!$isIdExcluded || $shortcode !== null)) {
453 $content = preg_replace_callback($mailtoRegex, [$this, 'encryptEmailAddress' ], $content);
454 }
455
456 return $content;
457 }
458
459 /**
460 * Encrypts email addresses in search results.
461 *
462 * @param array $searchResults The search results containing email addresses.
463 *
464 * @return string The search results with encrypted email addresses.
465 */
466 function encryptEmailAddress( array $searchResults): string
467 {
468 $originalValue = $searchResults[0];
469
470 if(strpos($searchResults[self::INDEX_TO_CHECK], '@') === self::NOT_FOUND) {
471 return $originalValue;
472 }
473
474 $mailReference = self::MAIL_IDENTIFIER . $searchResults[self::INDEX_TO_CHECK];
475
476 if ( str_starts_with( $searchResults[ self::INDEX_TO_CHECK ], self::SUBJECT_IDENTIFIER ) ) {
477 return $originalValue;
478 }
479
480 $return = $originalValue;
481 if (!empty(self::$cryptXOptions['java'])) {
482 $javaHandler="javascript:DeCryptX('" . $this->generateHashFromString($searchResults[self::INDEX_TO_CHECK]) . "')";
483 $return = str_replace(self::MAIL_IDENTIFIER.$searchResults[self::INDEX_TO_CHECK], $javaHandler, $originalValue);
484 }
485
486 $return = str_replace($mailReference, antispambot($mailReference), $return);
487
488 if(!empty(self::$cryptXOptions['css_id'])) {
489 $return = preg_replace(self::PATTERN, '$1" id="'.self::$cryptXOptions['css_id'] . '">', $return );
490 }
491
492 if(!empty(self::$cryptXOptions['css_class'])) {
493 $return = preg_replace(self::PATTERN, '$1" class="'.self::$cryptXOptions['css_class'] . '">', $return );
494 }
495
496 return $return;
497 }
498
499
500 /**
501 * Generate a hash string for the given input string.
502 *
503 * @param string $inputString The input string to generate a hash for.
504 *
505 * @return string The generated hash string.
506 */
507 function generateHashFromString( string $inputString): string
508 {
509 $inputString = str_replace("&", "&", $inputString);
510 $crypt = '';
511
512 for ($i = 0; $i < strlen($inputString); $i++) {
513 do {
514 $salt = mt_rand(0, 3);
515 $asciiValue = ord(substr($inputString, $i)) + $salt;
516 if (8364 <= $asciiValue) {
517 $asciiValue = 128;
518 }
519 } while (in_array($asciiValue, self::ASCII_VALUES_BLACKLIST));
520
521 $crypt .= $salt . chr($asciiValue);
522 }
523 return $crypt;
524 }
525 /**
526 * add link to email addresses
527 */
528 /**
529 * Auto-link emails in the given content.
530 *
531 * @param string $content The content to process.
532 * @param bool $shortcode Whether the function is called from a shortcode or not.
533 *
534 * @return string The content with emails auto-linked.
535 */
536 function addLinkToEmailAddresses( string $content, bool $shortcode = false ): string
537 {
538 global $post;
539 $postID = is_object( $post ) ? $post->ID : - 1;
540
541 if ( $this->isIdExcluded( $postID ) && ! $shortcode ) {
542 return $content;
543 }
544
545 $emailPattern = "[_a-zA-Z0-9-+]+(\.[_a-zA-Z0-9-+]+)*@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*(\.[a-zA-Z]{2,})";
546 $linkPattern = "<a href=\"mailto:\\2\">\\2</a>";
547 $src = [
548 "/([\s])($emailPattern)/si",
549 "/(>)($emailPattern)(<)/si",
550 "/(\()($emailPattern)(\))/si",
551 "/(>)($emailPattern)([\s])/si",
552 "/([\s])($emailPattern)(<)/si",
553 "/^($emailPattern)/si",
554 "/(<a[^>]*>)<a[^>]*>/",
555 "/(<\/A>)<\/A>/i"
556 ];
557 $tar = [
558 "\\1$linkPattern",
559 "\\1$linkPattern\\6",
560 "\\1$linkPattern\\6",
561 "\\1$linkPattern\\6",
562 "\\1$linkPattern\\6",
563 "<a href=\"mailto:\\0\">\\0</a>",
564 "\\1",
565 "\\1"
566 ];
567
568 return preg_replace( $src, $tar, $content );
569 }
570
571 /**
572 * Installs the CryptX plugin by updating its options and loading default values.
573 */
574 function installCryptX(): void {
575 global $wpdb;
576 self::$cryptXOptions['admin_notices_deprecated'] =true;
577 if ( self::$cryptXOptions['excludedIDs'] == "") {
578 $tmp = array();
579 $excludes = $wpdb->get_results("SELECT post_id FROM $wpdb->postmeta WHERE meta_key = 'cryptxoff' AND meta_value = 'true'");
580 if(count($excludes) > 0) {
581 foreach ($excludes as $exclude) {
582 $tmp[] = $exclude->post_id;
583 }
584 sort($tmp);
585 self::$cryptXOptions['excludedIDs'] = implode(",", $tmp);
586 update_option( 'cryptX', self::$cryptXOptions);
587 self::$cryptXOptions = $this->loadCryptXOptionsWithDefaults(); // reread Options
588 $wpdb->query("DELETE FROM $wpdb->postmeta WHERE meta_key = 'cryptxoff'");
589 }
590 }
591 if (empty(self::$cryptXOptions['c2i_font'])) {
592 self::$cryptXOptions['c2i_font'] = CRYPTX_DIR_PATH . 'fonts/' . $firstFont[0];
593 }
594 if (empty(self::$cryptXOptions['c2i_fontSize'])) {
595 self::$cryptXOptions['c2i_fontSize'] = 10;
596 }
597 if (empty(self::$cryptXOptions['c2i_fontRGB'])) {
598 self::$cryptXOptions['c2i_fontRGB'] = '000000';
599 }
600 update_option( 'cryptX', self::$cryptXOptions);
601 self::$cryptXOptions = $this->loadCryptXOptionsWithDefaults(); // reread Options
602 }
603
604 function addHooksHelper($function_name, $hook_name): void {
605 if ( function_exists($function_name) ) {
606 call_user_func($function_name, 'cryptx', 'CryptX', [$this, 'metaCheckbox' ], $hook_name);
607 } else {
608 add_action("dbx_{$hook_name}_sidebar", [$this, 'metaOptionFieldset' ]);
609 }
610 }
611
612 function metaBox(): void {
613 $this->addHooksHelper('add_meta_box', 'post');
614 $this->addHooksHelper('add_meta_box', 'page');
615 }
616
617 /**
618 * Displays a checkbox to disable CryptX for the current post or page.
619 *
620 * This function outputs HTML code for a checkbox that allows the user to disable CryptX
621 * functionality for the current post or page. If the current post or page ID is excluded
622 **/
623 function metaCheckbox(): void
624 {
625 global $post;
626 ?>
627 <label><input type="checkbox" name="disable_cryptx_pageid" <?php if ($this->isIdExcluded($post->ID)) { echo 'checked="checked"'; } ?>/>
628 Disable CryptX for this post/page</label>
629 <?php
630 }
631
632 /**
633 * Renders the CryptX option fieldset for the current post/page if the user has permission to edit posts.
634 * This fieldset allows the user to enable or disable CryptX for the current post/page.
635 *
636 * @return void
637 */
638 function metaOptionFieldset(): void
639 {
640 global $post;
641 if ( current_user_can('edit_posts') ) { ?>
642 <fieldset id="cryptxoption" class="dbx-box">
643 <h3 class="dbx-handle">CryptX</h3>
644 <div class="dbx-content">
645 <label><input type="checkbox" name="disable_cryptx_pageid" <?php if ($this->isIdExcluded($post->ID)) { echo 'checked="checked"'; } ?>/> Disable CryptX for this post/page</label>
646 </div>
647 </fieldset>
648 <?php
649 }
650 }
651
652 /**
653 * Adds a post ID to the excluded list in the cryptX options.
654 *
655 * @param int $postId The post ID to be added to the excluded list.
656 *
657 * @return void
658 */
659 function addPostIdToExcludedList( int $postId): void {
660 $postId = wp_is_post_revision($postId) ?: $postId;
661 $excludedIds = $this->updateExcludedIdsList(self::$cryptXOptions['excludedIDs'], $postId);
662 self::$cryptXOptions['excludedIDs'] = implode(",", array_filter($excludedIds));
663 update_option('cryptX', self::$cryptXOptions);
664 }
665
666 /**
667 * Updates the excluded IDs list based on a given ID and the current list.
668 *
669 * @param string $excludedIds The current excluded IDs list, separated by commas.
670 * @param int $postId The ID to be updated in the excluded IDs list.
671 *
672 * @return array The updated excluded IDs list as an array, with the ID removed if it existed and added if necessary.
673 */
674 function updateExcludedIdsList(string $excludedIds, int $postId): array {
675 $excludedIdsArray = explode(",", $excludedIds);
676 $excludedIdsArray = $this->removePostIdFromExcludedIds($excludedIdsArray, $postId);
677 $excludedIdsArray = $this->addPostIdToExcludedIdsIfNecessary($excludedIdsArray, $postId);
678 return $this->makeExcludedIdsUniqueAndSorted($excludedIdsArray);
679 }
680
681 /**
682 * Removes a specific post ID from the array of excluded IDs.
683 *
684 * @param array $excludedIds The array of excluded IDs.
685 * @param int $postId The ID of the post to be removed from the excluded IDs.
686 *
687 * @return array The updated array of excluded IDs without the specified post ID.
688 */
689 function removePostIdFromExcludedIds(array $excludedIds, int $postId): array {
690 foreach($excludedIds as $key => $id) {
691 if($id == $postId) {
692 unset($excludedIds[$key]);
693 break;
694 }
695 }
696 return $excludedIds;
697 }
698
699 /**
700 * Adds the post ID to the list of excluded IDs if necessary.
701 *
702 * @param array $excludedIds The array of excluded IDs.
703 * @param int $postId The post ID to be added to the excluded IDs.
704 *
705 * @return array The updated array of excluded IDs.
706 */
707 function addPostIdToExcludedIdsIfNecessary(array $excludedIds, int $postId): array {
708 if (isset($_POST['disable_cryptx_pageid'])) {
709 $excludedIds[] = $postId;
710 }
711 return $excludedIds;
712 }
713
714 /**
715 * Makes the excluded IDs unique and sorted.
716 *
717 * @param array $excludedIds The array of excluded IDs.
718 *
719 * @return array The array of excluded IDs with duplicate values removed and sorted in ascending order.
720 */
721 function makeExcludedIdsUniqueAndSorted(array $excludedIds): array {
722 $excludedIds = array_unique($excludedIds);
723 sort($excludedIds);
724 return $excludedIds;
725 }
726
727 /**
728 * Displays a message in a styled div.
729 *
730 * @param string $message The message to be displayed.
731 * @param bool $errormsg Optional. Indicates whether the message is an error message. Default is false.
732 *
733 * @return void
734 */
735 function showMessage($message, $errormsg = false): void {
736 if ($errormsg) {
737 echo '<div id="message" class="error">';
738 }
739 else {
740 echo '<div id="message" class="updated fade">';
741 }
742
743 echo "$message</div>";
744 }
745
746 /**
747 * Retrieves the domain from the current site URL.
748 *
749 * @return string The domain of the current site URL.
750 */
751 function getDomain(): string {
752 return $this->trimSlashFromDomain($this->removeProtocolFromUrl($this->getSiteUrl()));
753 }
754
755 /**
756 * Retrieves the site URL.
757 *
758 * @return string The site URL.
759 */
760 function getSiteUrl(): string {
761 return get_option( 'siteurl' );
762 }
763
764 /**
765 * Removes the protocol from a URL.
766 *
767 * @param string $url The URL string to remove the protocol from.
768 *
769 * @return string The URL string without the protocol.
770 */
771 function removeProtocolFromUrl(string $url): string
772 {
773 return preg_replace( '|https?://|', '', $url );
774 }
775
776 /**
777 * Trims the trailing slash from a domain.
778 *
779 * @param string $domain The domain to trim the slash from.
780 *
781 * @return string The domain with the trailing slash removed.
782 */
783 function trimSlashFromDomain(string $domain): string
784 {
785 if ( $slashPosition = strpos( $domain, '/' ) ) {
786 $domain = substr( $domain, 0, $slashPosition );
787 }
788 return $domain;
789 }
790
791 /**
792 * Loads Javascript files required for CryptX functionality.
793 *
794 * @return void
795 */
796 function loadJavascriptFiles(): void {
797 wp_enqueue_script( 'cryptx-js', CRYPTX_DIR_URL . 'js/cryptx.min.js', false, false, self::$cryptXOptions['load_java'] );
798 wp_enqueue_style( 'cryptx-styles', CRYPTX_DIR_URL . 'css/cryptx.css');
799 }
800
801 /**
802 * Updates the CryptX settings.
803 *
804 * This method retrieves the current CryptX options from the database and checks if the version of CryptX
805 * stored in the options is less than the current version of CryptX. If the version is outdated, the method
806 * updates the necessary settings and saves the updated options back to the database.
807 *
808 * @return void
809 */
810 function updateCryptXSettings(): void {
811 self::$cryptXOptions = get_option('cryptX');
812 if( isset( self::$cryptXOptions['version'] ) && version_compare(CRYPTX_VERSION, self::$cryptXOptions['version']) > 0 ) {
813 if( isset(self::$cryptXOptions['version']) ) unset(self::$cryptXOptions['version']);
814 if( isset(self::$cryptXOptions['c2i_font']) ) unset(self::$cryptXOptions['c2i_font']);
815 if( isset(self::$cryptXOptions['c2i_fontRGB']) ) self::$cryptXOptions['c2i_fontRGB'] = "#" . self::$cryptXOptions['c2i_fontRGB'];
816 if( isset(self::$cryptXOptions['alt_uploadedimage']) && !is_int(self::$cryptXOptions['alt_uploadedimage'])) {
817 unset(self::$cryptXOptions['alt_uploadedimage']);
818 if( self::$cryptXOptions['opt_linktext'] == 3 ) unset(self::$cryptXOptions['opt_linktext']);
819 }
820 self::$cryptXOptions = wp_parse_args( self::$cryptXOptions, $this->getCryptXOptionsDefaults() );
821 update_option( 'cryptX', self::$cryptXOptions);
822 }
823 }
824 }