PluginProbe
CartFlows – Funnel Builder & Checkout Plugin for WooCommerce / 3.3.0
CartFlows – Funnel Builder & Checkout Plugin for WooCommerce v3.3.0
3.3.0 3.2.1 3.2.0 3.1.4 3.1.3 3.1.2 3.1.1 3.1.0 3.0.1 trunk 1.0.4 1.1.0 1.1.0.1 1.1.1 1.1.10 1.1.11 1.1.12 1.1.13 1.1.14 1.1.15 1.1.16 1.1.17 1.1.18 1.1.19 1.1.2 All 162 releases
cartflows / admin-core / ajax / debugger.php

debugger.php in CartFlows – Funnel Builder & Checkout Plugin for WooCommerce 3.3.0, at admin-core/ajax/debugger.php

254 lines 6.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * CartFlows Flows ajax actions.
4 *
5 * @package CartFlows
6 */
7
8 namespace CartflowsAdmin\AdminCore\Ajax;
9
10 // Exit if accessed directly.
11 if ( ! defined( 'ABSPATH' ) ) {
12 exit;
13 }
14
15 use CartflowsAdmin\AdminCore\Ajax\AjaxBase;
16 use CartflowsAdmin\AdminCore\Inc\LogStatus;
17
18 /**
19 * Class Steps.
20 */
21 class Debugger extends AjaxBase {
22
23 /**
24 * Instance
25 *
26 * @access private
27 * @var object Class object.
28 * @since 1.0.0
29 */
30 private static $instance;
31
32 /**
33 * Deleted
34 *
35 * @access private
36 * @var object Class object.
37 * @since 1.0.0
38 */
39 private static $file_deleted = false;
40
41 /**
42 * Initiator
43 *
44 * @since 1.0.0
45 * @return object initialized object of class.
46 */
47 public static function get_instance() {
48 if ( ! isset( self::$instance ) ) {
49 self::$instance = new self();
50 }
51 return self::$instance;
52 }
53
54 /**
55 * Register ajax events.
56 *
57 * @since 1.0.0
58 * @return void
59 */
60 public function register_ajax_events() {
61
62 $ajax_events = array(
63 'show_cf_log',
64 'delete_cf_log',
65 'download_cf_log',
66 'sync_kb_docs',
67 );
68
69 $this->init_ajax_events( $ajax_events );
70 }
71
72 /**
73 * Sync knowledge base library.
74 *
75 * @since 2.0.0
76 * @return void
77 */
78 public function sync_kb_docs() {
79
80 if ( ! current_user_can( 'cartflows_manage_flows_steps' ) ) {
81 wp_die( esc_html__( 'You don\'t have permission to perform this action.', 'cartflows' ) );
82 }
83
84 check_ajax_referer( 'cartflows_sync_kb_docs', 'security' );
85
86 $docs_json = json_decode( wp_remote_retrieve_body( wp_remote_get( 'https://cartflows.com//wp-json/powerful-docs/v1/get-docs' ) ) );
87
88 // Never autoload — this payload runs to hundreds of KB and only the Knowledge Base screen reads it.
89 update_option( 'cartflows_docs_data', $docs_json, false );
90
91 $response_data = array(
92 'message' => __( 'Sync Success.', 'cartflows' ),
93 'status' => true,
94 );
95
96 wp_send_json_success( $response_data );
97 }
98
99
100 /**
101 * Clone step with its meta.
102 */
103 public function show_cf_log() {
104
105 if ( ! current_user_can( 'cartflows_manage_settings' ) ) {
106 wp_die( esc_html__( 'You don\'t have permission to view this page.', 'cartflows' ) );
107 }
108
109 check_ajax_referer( 'cartflows_show_cf_log', 'security' );
110
111 $log_key = isset( $_POST['log_key'] ) ? sanitize_text_field( wp_unslash( $_POST['log_key'] ) ) : '';
112
113
114 $logs = LogStatus::get_instance()->get_log_files();
115
116 $log_filename = isset( $logs[ $log_key ] ) ? $logs[ $log_key ] : '';
117
118 $file_content = file_get_contents( CARTFLOWS_LOG_DIR . $log_filename );
119
120 wp_send_json(
121 array(
122 'log_content' => esc_html( $file_content ),
123 )
124 );
125 }
126
127 /**
128 * Delete Provided log file
129 */
130 public function delete_cf_log() {
131
132 // Ensure the current user has permission to manage CartFlows settings.
133 if ( ! current_user_can( 'cartflows_manage_settings' ) ) {
134 wp_die( esc_html__( 'You don\'t have permission to perform this action.', 'cartflows' ) );
135 }
136
137 // Verify the nonce to protect against CSRF attacks.
138 check_ajax_referer( 'cartflows_delete_cf_log', 'security' );
139
140 // Bail early if no log key was provided in the request.
141 if ( empty( $_REQUEST['log_key'] ) ) {
142 $response_data = array(
143 'message' => esc_html__( 'Filename is empty. Please refresh the page and retry.', 'cartflows' ),
144 'file_content' => '',
145 );
146 wp_send_json_error( $response_data );
147 }
148
149 // Sanitize the log key from the request.
150 $log_key = sanitize_text_field( wp_unslash( $_REQUEST['log_key'] ) );
151
152 // Retrieve the list of available log files.
153 $logs = LogStatus::get_instance()->get_log_files();
154
155 // Bail if the provided key does not match any known log file.
156 if ( ! isset( $logs[ $log_key ] ) ) {
157 $response_data = array(
158 'message' => esc_html__( 'Invalid log file.', 'cartflows' ),
159 'file_content' => '',
160 );
161 wp_send_json_error( $response_data );
162 }
163
164 // Resolve the full file path for the log file.
165 $file_name = $logs[ $log_key ];
166 $file_path = CARTFLOWS_LOG_DIR . $file_name;
167
168 // Security: Validate file path is within log directory to prevent path traversal.
169 $real_path = realpath( $file_path );
170 $real_log_dir = realpath( CARTFLOWS_LOG_DIR );
171
172 if ( $real_path && $real_log_dir && 0 === strpos( $real_path, $real_log_dir ) && file_exists( $real_path ) ) {
173 wp_delete_file( $real_path );
174
175 // Clear the stat cache so the re-check reflects the actual deletion.
176 clearstatcache( true, $real_path );
177
178 // Confirm the file is actually gone before reporting success.
179 if ( ! file_exists( $real_path ) ) {
180 self::$file_deleted = true;
181
182 wp_send_json_success(
183 array(
184 'message' => esc_html__( 'Log file deleted successfully.', 'cartflows' ),
185 )
186 );
187 }
188 }
189
190 // Reaching here means the file was not deleted.
191 wp_send_json_error(
192 array(
193 'message' => esc_html__( 'Log file could not be deleted. Please try again.', 'cartflows' ),
194 )
195 );
196 }
197
198 /**
199 * Download the selected log file.
200 */
201 public function download_cf_log() {
202
203 // Ensure the current user has permission to manage CartFlows settings.
204 if ( ! current_user_can( 'cartflows_manage_settings' ) ) {
205 wp_die( esc_html__( 'You don\'t have permission to perform this action.', 'cartflows' ) );
206 }
207
208 // Verify the nonce to protect against CSRF attacks.
209 check_ajax_referer( 'cartflows_download_cf_log', 'security' );
210
211 // Sanitize the log key from the request, defaulting to empty string if not set.
212 $log_key = isset( $_REQUEST['log_key'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['log_key'] ) ) : '';
213
214 // Retrieve the list of available log files.
215 $logs = LogStatus::get_instance()->get_log_files();
216
217 // Bail if the provided key does not match any known log file.
218 if ( ! isset( $logs[ $log_key ] ) ) {
219 return;
220 }
221
222 // Resolve the full file path for the log file.
223 $file_name = $logs[ $log_key ];
224 $file_path = CARTFLOWS_LOG_DIR . $file_name;
225
226 // Security: Validate file path is within log directory to prevent path traversal.
227 $real_path = realpath( $file_path );
228 $real_log_dir = realpath( CARTFLOWS_LOG_DIR );
229
230 if ( ! $real_path || ! $real_log_dir || 0 !== strpos( $real_path, $real_log_dir ) || ! file_exists( $real_path ) ) {
231 return;
232 }
233
234 $file_extension = pathinfo( $file_name, PATHINFO_EXTENSION );
235 $allowed_files = array( 'log' );
236
237 // Return if the desired file is not found for download.
238 if ( ! in_array( $file_extension, $allowed_files, true ) || strpos( $file_name, '.php' ) !== false ) {
239 wp_die( esc_html__( 'Invalid file.', 'cartflows' ) );
240 return;
241 }
242
243 $file_content = file_get_contents( $real_path ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
244
245 // Return the file contents along with a success message.
246 $response_data = array(
247 'message' => __( 'Export logs successfully', 'cartflows' ),
248 'file_content' => $file_content,
249 );
250
251 wp_send_json_success( $response_data );
252 }
253 }
254