PluginProbe
Code Engine – PHP Snippets, AI Functions & Automation for WordPress / 0.4.3
Code Engine – PHP Snippets, AI Functions & Automation for WordPress v0.4.3
0.5.7 0.5.6 0.5.5 0.5.4 0.5.3 0.5.2 0.5.1 0.5.0 0.4.9 0.4.8 0.4.7 0.4.6 trunk 0.0.1 0.0.2 0.2.8 0.2.9 0.3.0 0.3.1 0.3.2 0.3.3 0.3.4 0.3.5 0.3.6 0.3.7 All 33 releases
← All changes | classes/core.php +74 -40 0.3.30.4.3 View file →
@@ -12,8 +12,9 @@
12 12 public $is_rest = false;
13 13 public $is_cli = false;
14 14 public $site_url = null;
15 15 public $mwcode = null;
16 + public $licenser = null;
16 17
17 18 private $option_name = 'mwcode_options';
18 19
19 20 public function __construct() {
@@ -19,9 +20,9 @@
19 20 public function __construct() {
20 21 global $mwcode;
21 22
22 23 $this->site_url = get_site_url();
23 - $this->is_rest = MeowCommon_Helpers::is_rest();
24 + $this->is_rest = MeowKit_MWCODE_Helpers::is_rest();
24 25 $this->is_cli = defined( 'WP_CLI' ) && WP_CLI;
25 26
26 27 // Snippets
27 28 $snippet = new Meow_MWCODE_Modules_Snippet( $this );
@@ -37,8 +38,13 @@
37 38 add_action( 'plugins_loaded', array( $this, 'init' ) );
38 39 }
39 40
40 41 function init() {
42 + // Initialize the licenser for Pro version
43 + if ( class_exists( 'MeowKitPro_MWCODE_Licenser' ) ) {
44 + $this->licenser = new MeowKitPro_MWCODE_Licenser( MWCODE_PREFIX, MWCODE_ENTRY, MWCODE_DOMAIN, MWCODE_ITEM_ID, MWCODE_VERSION );
45 + }
46 +
41 47 // Part of the core, settings and stuff
42 48 $this->admin = new Meow_MWCODE_Admin( $this );
43 49
44 50 // Only for REST
@@ -83,8 +89,11 @@
83 89 return [
84 90 //Safemode
85 91 "safe_mode_status" => "on", // on, off, whitelist
86 92 "safe_mode_whitelist" => [],
93 + //"disallow_block_php" => true, // Do not allow PHP code to be execute through Blocks "code" parameter
94 + "code_blocks" => false,
95 + "code_blocks_whitelist" => [], // Whitelist for code blocks, if empty, all code blocks are allowed
87 96
88 97 //LOGS
89 98 "server_debug_mode" => false,
90 99
@@ -101,8 +110,11 @@
101 110 "api_token" => md5( time() . rand() ),
102 111
103 112 //MCP
104 113 "mcp_support" => false,
114 +
115 + //MAINTENANCE
116 + "clean_uninstall" => false,
105 117 ];
106 118 }
107 119
108 120 function get_all_options( ) {
@@ -116,19 +128,15 @@
116 128 return $options;
117 129 }
118 130
119 131 function update_options( $options ) {
120 - $current_options = get_option($this->option_name);
121 132
122 - if ($current_options === $options) {
123 - // $this->log('💾 The options are already the expected value.');
124 - } else {
125 - if ( !update_option( $this->option_name, $options, false ) ) {
126 - $this->log( '💾 There was an issue updating the options.' );
127 - }
133 + $options = $this->sanitize_options( $options );
134 +
135 + if ( !update_option( $this->option_name, $options, false ) ) {
136 + $this->log( '💾 There was an issue updating the options.' );
128 137 }
129 -
130 - $options = $this->sanitize_options( $options );
138 +
131 139 return $options;
132 140 }
133 141
134 142 function update_option( $option, $value ) {
@@ -159,9 +167,9 @@
159 167 $options_modified = true;
160 168 }
161 169
162 170 // Update AI Engine status
163 - $options_modified = $this->updateAIEngineStatus( $options ) || $options_modified;
171 + $options = $this->updateAIEngineStatus( $options );
164 172
165 173 // Disable AI related features if AI Engine is not available
166 174 if ( ! $options['ai_engine_status'] ) {
167 175 if ( $options['ai_suggestions'] !== false ) {
@@ -171,12 +179,8 @@
171 179 // Note: We don't disable MCP support here anymore
172 180 // It will be checked at runtime in the MCP class
173 181 }
174 182
175 - if ( $options_modified ) {
176 - update_option( $this->option_name, $options, false );
177 - }
178 -
179 183 return $options;
180 184 }
181 185
182 186 private function updateAIEngineStatus( &$options ) {
@@ -184,28 +188,25 @@
184 188
185 189 if ( is_null( $mwai ) || ! isset( $mwai ) ) {
186 190 $options['ai_engine_status'] = false;
187 191 $options['ai_engine_message'] = 'AI Engine is not available.';
188 - return true;
192 +
193 + return $options;
189 194 }
190 195
191 196 try {
192 197 $status = $mwai->checkStatus();
193 198
194 - if ( $options['ai_engine_status'] != true || $options['ai_engine_message'] != $status ) {
195 - $options['ai_engine_status'] = true;
196 - $options['ai_engine_message'] = $status;
197 - return true;
198 - }
199 + $options['ai_engine_status'] = true;
200 + $options['ai_engine_message'] = is_array( $status ) ? "Environments: " . implode( ', ', $status ) : $status;
201 +
199 202 } catch ( Exception $e ) {
200 - if ( $options['ai_engine_status'] != false || $options['ai_engine_message'] != $e->getMessage() ) {
203 +
201 204 $options['ai_engine_status'] = false;
202 205 $options['ai_engine_message'] = $e->getMessage();
203 - return true;
204 - }
205 206 }
206 207
207 - return false;
208 + return $options;
208 209 }
209 210
210 211 #endregion
211 212
@@ -276,16 +277,16 @@
276 277 $value = array_map( 'trim', $value );
277 278 }
278 279
279 280 if ( $type === 'array' ) {
280 - $value = json_encode( $value );
281 - $value = str_replace( '\\', '', $value );
281 + // Convert to PHP array format instead of JSON
282 + $value = var_export( $value, true );
282 283 }
283 284
284 285 return [ $name, $value ];
285 286 }
286 287
287 - function run_non_fn_snippet( $id, $code = null, $test = false ) {
288 + function run_non_fn_snippet( $id, $code = null, $test = false, $prefix = '' ) {
288 289 // Retrieve the snippet code from the provided code or via the snippet ID.
289 290 if ( $code ) {
290 291 $snippet = [ 'code' => $code ];
291 292 } else {
@@ -292,13 +293,17 @@
292 293 $snippet = $this->get_snippet( $id );
293 294 }
294 295
295 296 // Remove any PHP opening tag.
296 - $snippet['code'] = preg_replace( '/<\?php/', '', $snippet['code'], 1 );
297 + $snippet['code'] = $this->snippet->sanitize_code( $snippet['code'] );
297 298
298 299 if ( $test ) {
299 300 $snippet['code'] = preg_replace( '/echo\s+(.+?);/s', 'echo $1 . "\n";', $snippet['code'] );
300 301 }
302 +
303 + if( $prefix ) {
304 + $snippet['code'] = $prefix . "\n" . $snippet['code'];
305 + }
301 306
302 307 $error = null;
303 308 $output = null;
304 309
@@ -432,13 +437,14 @@
432 437 if ( $index < count( $params['args'] ) - 1 ) {
433 438 $params['code'] .= ', ';
434 439 }
435 440 }
441 +
436 442 $params['code'] .= ");\necho print_r(\$mwcode_result, true);";
437 443
438 444 $error = null;
439 445 $output = null;
440 -
446 +
441 447 try {
442 448 ob_start();
443 449 eval( $params['code'] );
444 450 $output = ob_get_clean();
@@ -580,14 +586,17 @@
580 586
581 587 $blocked = false;
582 588 $page = isset( $_GET["page"] ) ? sanitize_text_field( $_GET["page"] ) : null;
583 589
584 - // Block on settings page for safety
590 +
585 591 if ( $page === 'mwcode_settings' ) {
586 - $blocked = true;
592 + // If we blocks global snippets like nonce_life filter, we would block the settings page so let's remove the block for this page
593 +
594 + $blocked = false;
595 + //$blocked = true;
587 596 }
588 597 // Block REST requests that aren't whitelisted
589 - elseif ( MeowCommon_Helpers::is_rest() && !Meow_MWCODE_Core::is_white_listed_rest() ) {
598 + elseif ( MeowKit_MWCODE_Helpers::is_rest() && !Meow_MWCODE_Core::is_white_listed_rest() ) {
590 599 $blocked = true;
591 600 }
592 601
593 602 if ( empty( $this->snippet ) ) {
@@ -618,9 +627,9 @@
618 627 return;
619 628 }
620 629
621 630 $snippets = array_map( function ( $snippet ) use ( $blocked ) {
622 - $snippet['code'] = preg_replace( '/<\?php/', '', $snippet['code'], 1 );
631 + $snippet['code'] = $this->snippet->sanitize_code( $snippet['code'] );
623 632 $snippet['blocked'] = $blocked;
624 633
625 634 // If the snippet must be executed only in the frontend, we bypass the block
626 635 if ( !is_admin() && $snippet['scope'] === 'frontend' ) {
@@ -636,22 +645,35 @@
636 645
637 646 #endregion
638 647
639 648 #region Shortcodes
649 + function separate_mwcode_atts( $atts ) {
640 650
651 + if( array_key_exists( 'id', $atts ) ) unset( $atts['id'] );
652 + if( array_key_exists( 'target', $atts ) ) unset( $atts['target'] );
653 + if( array_key_exists( 'code', $atts ) ) unset( $atts['code'] );
654 +
655 + return $atts;
656 + }
657 +
641 658 function content_shortcode( $atts ) {
642 659
660 + $user_atts = $this->separate_mwcode_atts( $atts );
661 +
643 662 $atts = shortcode_atts( array(
644 - 'id' => null,
645 - 'target' => null,
646 - 'code' => null,
647 - ), $atts );
663 + 'id' => null,
664 + 'target' => null, // js or php
665 + 'code' => null, // For Guttenberg block usage
666 + ), $atts, 'code-engine' );
648 667
649 668 $id = $atts['id'];
650 669 $target = $atts['target'];
651 670 $code = $atts['code'];
671 + $current_post = get_post();
652 672
653 - $no_js = defined( 'DISALLOW_UNFILTERED_HTML' ) && DISALLOW_UNFILTERED_HTML;
673 + $no_js = defined( 'DISALLOW_UNFILTERED_HTML' ) && DISALLOW_UNFILTERED_HTML;
674 + $allow_php = $this->get_option( 'code_blocks', false );
675 + $allow_php_whitelist = $this->get_option( 'code_blocks_whitelist', [] );
654 676
655 677 // If the ID is null, it means it comes from a Guttenberg block
656 678 $is_block = empty( $id ) && !empty( $code );
657 679
@@ -664,8 +686,19 @@
664 686 if ( $no_js && $target === 'js' ) {
665 687 return '<b>Code Engine:</b> Code Block JS are disabled because unfiltered HTML is not allowed on your server.';
666 688 }
667 689
690 + if ( $target === 'php' ) {
691 +
692 + if ( !$allow_php ) {
693 + return '<b>Code Engine:</b> Code Block PHP are disabled. If you are an administrator, you can enable it in the settings, this is not recommended. Please use a Content Snippet ( PHP ) instead.';
694 + }
695 +
696 + if ( !empty( $allow_php_whitelist ) && !in_array( $current_post->ID, $allow_php_whitelist ) ) {
697 + return '<b>Code Engine:</b> Code Block PHP are disabled for this post. If you are an administrator, you can enable it in the settings, this is not recommended. Please use a Content Snippet ( PHP ) instead.';
698 + }
699 + }
700 +
668 701 // Because the code from Blocks are sanitized, we need to replace the &quot; with "
669 702 $code = str_replace( '&quot;', '"', $code );
670 703
671 704 if ( $target === 'js' ) {
@@ -714,9 +747,10 @@
714 747 $output = '<script>' . $snippet['code'] . '</script>';
715 748 }
716 749
717 750 if ( $is_content_php ) {
718 - $output = $this->run_non_fn_snippet( $id );
751 + $prefix = "\$mwcode_atts = unserialize( '" . serialize( $user_atts ) . "' );";
752 + $output = $this->run_non_fn_snippet( $id, null, false, $prefix );
719 753 }
720 754
721 755 return $output;
722 756 }