Issues (1182)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

includes/admin/class-wc-admin-status.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * Debug/Status page
4
 *
5
 * @author      WooThemes
6
 * @category    Admin
7
 * @package     WooCommerce/Admin/System Status
8
 * @version     2.2.0
9
 */
10
11
if ( ! defined( 'ABSPATH' ) ) {
12
	exit;
13
}
14
15
/**
16
 * WC_Admin_Status Class.
17
 */
18
class WC_Admin_Status {
19
20
	/**
21
	 * Handles output of the reports page in admin.
22
	 */
23
	public static function output() {
24
		include_once( 'views/html-admin-page-status.php' );
25
	}
26
27
	/**
28
	 * Handles output of report.
29
	 */
30
	public static function status_report() {
31
		include_once( 'views/html-admin-page-status-report.php' );
32
	}
33
34
	/**
35
	 * Handles output of tools.
36
	 */
37
	public static function status_tools() {
38
		global $wpdb;
39
40
		$tools = self::get_tools();
41
42
		if ( ! empty( $_GET['action'] ) && ! empty( $_REQUEST['_wpnonce'] ) && wp_verify_nonce( $_REQUEST['_wpnonce'], 'debug_action' ) ) {
43
44
			switch ( $_GET['action'] ) {
45
				case 'clear_transients' :
46
					wc_delete_product_transients();
47
					wc_delete_shop_order_transients();
48
					WC_Cache_Helper::get_transient_version( 'shipping', true );
49
50
					echo '<div class="updated inline"><p>' . __( 'Product Transients Cleared', 'woocommerce' ) . '</p></div>';
51
				break;
52
				case 'clear_expired_transients' :
53
54
					/*
55
					 * Deletes all expired transients. The multi-table delete syntax is used.
56
					 * to delete the transient record from table a, and the corresponding.
57
					 * transient_timeout record from table b.
58
					 *
59
					 * Based on code inside core's upgrade_network() function.
60
					 */
61
					$sql = "DELETE a, b FROM $wpdb->options a, $wpdb->options b
62
						WHERE a.option_name LIKE %s
63
						AND a.option_name NOT LIKE %s
64
						AND b.option_name = CONCAT( '_transient_timeout_', SUBSTRING( a.option_name, 12 ) )
65
						AND b.option_value < %d";
66
					$rows = $wpdb->query( $wpdb->prepare( $sql, $wpdb->esc_like( '_transient_' ) . '%', $wpdb->esc_like( '_transient_timeout_' ) . '%', time() ) );
67
68
					$sql = "DELETE a, b FROM $wpdb->options a, $wpdb->options b
69
						WHERE a.option_name LIKE %s
70
						AND a.option_name NOT LIKE %s
71
						AND b.option_name = CONCAT( '_site_transient_timeout_', SUBSTRING( a.option_name, 17 ) )
72
						AND b.option_value < %d";
73
					$rows2 = $wpdb->query( $wpdb->prepare( $sql, $wpdb->esc_like( '_site_transient_' ) . '%', $wpdb->esc_like( '_site_transient_timeout_' ) . '%', time() ) );
74
75
					echo '<div class="updated inline"><p>' . sprintf( __( '%d Transients Rows Cleared', 'woocommerce' ), $rows + $rows2 ) . '</p></div>';
76
				break;
77
				case 'reset_roles' :
78
					// Remove then re-add caps and roles
79
					WC_Install::remove_roles();
80
					WC_Install::create_roles();
81
82
					echo '<div class="updated inline"><p>' . __( 'Roles successfully reset', 'woocommerce' ) . '</p></div>';
83
				break;
84
				case 'recount_terms' :
85
86
					$product_cats = get_terms( 'product_cat', array( 'hide_empty' => false, 'fields' => 'id=>parent' ) );
87
88
					_wc_term_recount( $product_cats, get_taxonomy( 'product_cat' ), true, false );
89
90
					$product_tags = get_terms( 'product_tag', array( 'hide_empty' => false, 'fields' => 'id=>parent' ) );
91
92
					_wc_term_recount( $product_tags, get_taxonomy( 'product_tag' ), true, false );
93
94
					echo '<div class="updated inline"><p>' . __( 'Terms successfully recounted', 'woocommerce' ) . '</p></div>';
95
				break;
96
				case 'clear_sessions' :
97
98
					$wpdb->query( "TRUNCATE {$wpdb->prefix}woocommerce_sessions" );
99
100
					wp_cache_flush();
101
102
					echo '<div class="updated inline"><p>' . __( 'Sessions successfully cleared', 'woocommerce' ) . '</p></div>';
103
				break;
104
				case 'install_pages' :
105
					WC_Install::create_pages();
106
					echo '<div class="updated inline"><p>' . __( 'All missing WooCommerce pages was installed successfully.', 'woocommerce' ) . '</p></div>';
107
				break;
108
				case 'delete_taxes' :
109
110
					$wpdb->query( "TRUNCATE TABLE {$wpdb->prefix}woocommerce_tax_rates;" );
111
					$wpdb->query( "TRUNCATE TABLE {$wpdb->prefix}woocommerce_tax_rate_locations;" );
112
					WC_Cache_Helper::incr_cache_prefix( 'taxes' );
113
114
					echo '<div class="updated inline"><p>' . __( 'Tax rates successfully deleted', 'woocommerce' ) . '</p></div>';
115
				break;
116
				case 'reset_tracking' :
117
					delete_option( 'woocommerce_allow_tracking' );
118
					WC_Admin_Notices::add_notice( 'tracking' );
119
120
					echo '<div class="updated inline"><p>' . __( 'Usage tracking settings successfully reset.', 'woocommerce' ) . '</p></div>';
121
				break;
122
				default :
123
					$action = esc_attr( $_GET['action'] );
124
					if ( isset( $tools[ $action ]['callback'] ) ) {
125
						$callback = $tools[ $action ]['callback'];
126
						$return = call_user_func( $callback );
127
						if ( $return === false ) {
128
							$callback_string = is_array( $callback ) ? get_class( $callback[0] ) . '::' . $callback[1] : $callback;
129
							echo '<div class="error inline"><p>' . sprintf( __( 'There was an error calling %s', 'woocommerce' ), $callback_string ) . '</p></div>';
130
						}
131
					}
132
				break;
133
			}
134
		}
135
136
		// Display message if settings settings have been saved
137
		if ( isset( $_REQUEST['settings-updated'] ) ) {
138
			echo '<div class="updated inline"><p>' . __( 'Your changes have been saved.', 'woocommerce' ) . '</p></div>';
139
		}
140
141
		include_once( 'views/html-admin-page-status-tools.php' );
142
	}
143
144
	/**
145
	 * Get tools.
146
	 * @return array of tools
147
	 */
148
	public static function get_tools() {
149
		$tools = array(
150
			'clear_transients' => array(
151
				'name'    => __( 'WC Transients', 'woocommerce' ),
152
				'button'  => __( 'Clear transients', 'woocommerce' ),
153
				'desc'    => __( 'This tool will clear the product/shop transients cache.', 'woocommerce' ),
154
			),
155
			'clear_expired_transients' => array(
156
				'name'    => __( 'Expired Transients', 'woocommerce' ),
157
				'button'  => __( 'Clear expired transients', 'woocommerce' ),
158
				'desc'    => __( 'This tool will clear ALL expired transients from WordPress.', 'woocommerce' ),
159
			),
160
			'recount_terms' => array(
161
				'name'    => __( 'Term counts', 'woocommerce' ),
162
				'button'  => __( 'Recount terms', 'woocommerce' ),
163
				'desc'    => __( 'This tool will recount product terms - useful when changing your settings in a way which hides products from the catalog.', 'woocommerce' ),
164
			),
165
			'reset_roles' => array(
166
				'name'    => __( 'Capabilities', 'woocommerce' ),
167
				'button'  => __( 'Reset capabilities', 'woocommerce' ),
168
				'desc'    => __( 'This tool will reset the admin, customer and shop_manager roles to default. Use this if your users cannot access all of the WooCommerce admin pages.', 'woocommerce' ),
169
			),
170
			'clear_sessions' => array(
171
				'name'    => __( 'Customer Sessions', 'woocommerce' ),
172
				'button'  => __( 'Clear all sessions', 'woocommerce' ),
173
				'desc'    => __( '<strong class="red">Warning:</strong> This tool will delete all customer session data from the database, including any current live carts.', 'woocommerce' ),
174
			),
175
			'install_pages' => array(
176
				'name'    => __( 'Install WooCommerce Pages', 'woocommerce' ),
177
				'button'  => __( 'Install pages', 'woocommerce' ),
178
				'desc'    => __( '<strong class="red">Note:</strong> This tool will install all the missing WooCommerce pages. Pages already defined and set up will not be replaced.', 'woocommerce' ),
179
			),
180
			'delete_taxes' => array(
181
				'name'    => __( 'Delete all WooCommerce tax rates', 'woocommerce' ),
182
				'button'  => __( 'Delete ALL tax rates', 'woocommerce' ),
183
				'desc'    => __( '<strong class="red">Note:</strong> This option will delete ALL of your tax rates, use with caution.', 'woocommerce' ),
184
			),
185
			'reset_tracking' => array(
186
				'name'    => __( 'Reset Usage Tracking Settings', 'woocommerce' ),
187
				'button'  => __( 'Reset usage tracking settings', 'woocommerce' ),
188
				'desc'    => __( 'This will reset your usage tracking settings, causing it to show the opt-in banner again and not sending any data.', 'woocommerce' ),
189
			)
190
		);
191
192
		return apply_filters( 'woocommerce_debug_tools', $tools );
193
	}
194
195
	/**
196
	 * Show the logs page.
197
	 */
198
	public static function status_logs() {
199
200
		$logs = self::scan_log_files();
201
202
		if ( ! empty( $_REQUEST['log_file'] ) && isset( $logs[ sanitize_title( $_REQUEST['log_file'] ) ] ) ) {
203
			$viewed_log = $logs[ sanitize_title( $_REQUEST['log_file'] ) ];
204
		} elseif ( ! empty( $logs ) ) {
205
			$viewed_log = current( $logs );
206
		}
207
208
		include_once( 'views/html-admin-page-status-logs.php' );
209
	}
210
211
	/**
212
	 * Retrieve metadata from a file. Based on WP Core's get_file_data function.
213
	 * @since  2.1.1
214
	 * @param  string $file Path to the file
215
	 * @return string
216
	 */
217
	public static function get_file_version( $file ) {
218
219
		// Avoid notices if file does not exist
220
		if ( ! file_exists( $file ) ) {
221
			return '';
222
		}
223
224
		// We don't need to write to the file, so just open for reading.
225
		$fp = fopen( $file, 'r' );
226
227
		// Pull only the first 8kiB of the file in.
228
		$file_data = fread( $fp, 8192 );
229
230
		// PHP will close file handle, but we are good citizens.
231
		fclose( $fp );
232
233
		// Make sure we catch CR-only line endings.
234
		$file_data = str_replace( "\r", "\n", $file_data );
235
		$version   = '';
236
237
		if ( preg_match( '/^[ \t\/*#@]*' . preg_quote( '@version', '/' ) . '(.*)$/mi', $file_data, $match ) && $match[1] )
238
			$version = _cleanup_header_comment( $match[1] );
239
240
		return $version ;
241
	}
242
243
	/**
244
	 * Scan the template files.
245
	 * @param  string $template_path
246
	 * @return array
247
	 */
248
	public static function scan_template_files( $template_path ) {
249
250
		$files  = @scandir( $template_path );
251
		$result = array();
252
253
		if ( ! empty( $files ) ) {
254
255
			foreach ( $files as $key => $value ) {
256
257
				if ( ! in_array( $value, array( ".",".." ) ) ) {
258
259
					if ( is_dir( $template_path . DIRECTORY_SEPARATOR . $value ) ) {
260
						$sub_files = self::scan_template_files( $template_path . DIRECTORY_SEPARATOR . $value );
261
						foreach ( $sub_files as $sub_file ) {
262
							$result[] = $value . DIRECTORY_SEPARATOR . $sub_file;
263
						}
264
					} else {
265
						$result[] = $value;
266
					}
267
				}
268
			}
269
		}
270
		return $result;
271
	}
272
273
	/**
274
	 * Scan the log files.
275
	 * @return array
276
	 */
277
	public static function scan_log_files() {
278
		$files  = @scandir( WC_LOG_DIR );
279
		$result = array();
280
281
		if ( $files ) {
282
283
			foreach ( $files as $key => $value ) {
284
285
				if ( ! in_array( $value, array( '.', '..' ) ) ) {
286
					if ( ! is_dir( $value ) && strstr( $value, '.log' ) ) {
287
						$result[ sanitize_title( $value ) ] = $value;
288
					}
289
				}
290
			}
291
292
		}
293
294
		return $result;
295
	}
296
297
	/**
298
	 * Get latest version of a theme by slug.
299
	 * @param  object $theme WP_Theme object.
300
	 * @return string Version number if found.
301
	 */
302
	public static function get_latest_theme_version( $theme ) {
303
		$api = themes_api( 'theme_information', array(
304
			'slug'     => $theme->get_stylesheet(),
305
			'fields'   => array(
306
				'sections' => false,
307
				'tags'     => false,
308
			)
309
		) );
310
311
		$update_theme_version = 0;
312
313
		// Check .org for updates.
314
		if ( is_object( $api ) && ! is_wp_error( $api ) ) {
315
			$update_theme_version = $api->version;
316
317
		// Check WooThemes Theme Version.
318
		} elseif ( strstr( $theme->{'Author URI'}, 'woothemes' ) ) {
319
			$theme_dir = substr( strtolower( str_replace( ' ','', $theme->Name ) ), 0, 45 );
320
321 View Code Duplication
			if ( false === ( $theme_version_data = get_transient( $theme_dir . '_version_data' ) ) ) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
322
				$theme_changelog = wp_safe_remote_get( 'http://dzv365zjfbd8v.cloudfront.net/changelogs/' . $theme_dir . '/changelog.txt' );
323
				$cl_lines  = explode( "\n", wp_remote_retrieve_body( $theme_changelog ) );
324
				if ( ! empty( $cl_lines ) ) {
325
					foreach ( $cl_lines as $line_num => $cl_line ) {
326
						if ( preg_match( '/^[0-9]/', $cl_line ) ) {
327
							$theme_date         = str_replace( '.' , '-' , trim( substr( $cl_line , 0 , strpos( $cl_line , '-' ) ) ) );
328
							$theme_version      = preg_replace( '~[^0-9,.]~' , '' ,stristr( $cl_line , "version" ) );
329
							$theme_update       = trim( str_replace( "*" , "" , $cl_lines[ $line_num + 1 ] ) );
330
							$theme_version_data = array( 'date' => $theme_date , 'version' => $theme_version , 'update' => $theme_update , 'changelog' => $theme_changelog );
331
							set_transient( $theme_dir . '_version_data', $theme_version_data , DAY_IN_SECONDS );
332
							break;
333
						}
334
					}
335
				}
336
			}
337
338
			if ( ! empty( $theme_version_data['version'] ) ) {
339
				$update_theme_version = $theme_version_data['version'];
340
			}
341
		}
342
343
		return $update_theme_version;
344
	}
345
}
346