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/class-wc-tracker.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
 * WooCommerce Tracker
4
 *
5
 * The WooCommerce tracker class adds functionality to track WooCommerce usage based on if the customer opted in.
6
 * No personal infomation is tracked, only general WooCommerce settings, general product, order and user counts and admin email for discount code.
7
 *
8
 * @class 		WC_Tracker
9
 * @version		2.3.0
10
 * @package		WooCommerce/Classes
11
 * @category	Class
12
 * @author 		WooThemes
13
 */
14
15
if ( ! defined( 'ABSPATH' ) ) {
16
	exit;
17
}
18
19
class WC_Tracker {
20
21
	/**
22
	 * URL to the WooThemes Tracker API endpoint.
23
	 * @var string
24
	 */
25
	private static $api_url = 'https://tracking.woocommerce.com/v1/';
26
27
	/**
28
	 * Hook into cron event.
29
	 */
30
	public static function init() {
31
		add_action( 'woocommerce_tracker_send_event', array( __CLASS__, 'send_tracking_data' ) );
32
	}
33
34
	/**
35
	 * Decide whether to send tracking data or not.
36
	 *
37
	 * @param boolean $override
38
	 */
39
	public static function send_tracking_data( $override = false ) {
40
		// Dont trigger this on AJAX Requests
41
		if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
42
			return;
43
		}
44
45
		if ( ! apply_filters( 'woocommerce_tracker_send_override', $override ) ) {
46
			// Send a maximum of once per week by default.
47
			$last_send = self::get_last_send_time();
48
			if ( $last_send && $last_send > apply_filters( 'woocommerce_tracker_last_send_interval', strtotime( '-1 week' ) ) ) {
49
				return;
50
			}
51
		} else {
52
			// Make sure there is at least a 1 hour delay between override sends, we dont want duplicate calls due to double clicking links.
53
			$last_send = self::get_last_send_time();
54
			if ( $last_send && $last_send > strtotime( '-1 hours' ) ) {
55
				return;
56
			}
57
		}
58
59
		// Update time first before sending to ensure it is set
60
		update_option( 'woocommerce_tracker_last_send', time() );
61
62
		$params   = self::get_tracking_data();
63
		wp_safe_remote_post( self::$api_url, array(
64
				'method'      => 'POST',
65
				'timeout'     => 45,
66
				'redirection' => 5,
67
				'httpversion' => '1.0',
68
				'blocking'    => false,
69
				'headers'     => array( 'user-agent' => 'WooCommerceTracker/' . md5( esc_url( home_url( '/' ) ) ) . ';' ),
70
				'body'        => json_encode( $params ),
71
				'cookies'     => array()
72
			)
73
		);
74
	}
75
76
	/**
77
	 * Get the last time tracking data was sent.
78
	 * @return int|bool
79
	 */
80
	private static function get_last_send_time() {
81
		return apply_filters( 'woocommerce_tracker_last_send_time', get_option( 'woocommerce_tracker_last_send', false ) );
82
	}
83
84
	/**
85
	 * Get all the tracking data.
86
	 * @return array
87
	 */
88
	private static function get_tracking_data() {
89
		$data                       = array();
90
91
		// General site info
92
		$data['url']                = home_url();
93
		$data['email']              = apply_filters( 'woocommerce_tracker_admin_email', get_option( 'admin_email' ) );
94
		$data['theme']              = self::get_theme_info();
95
96
		// WordPress Info
97
		$data['wp']                 = self::get_wordpress_info();
98
99
		// Server Info
100
		$data['server']             = self::get_server_info();
101
102
		// Plugin info
103
		$all_plugins                = self::get_all_plugins();
104
		$data['active_plugins']     = $all_plugins['active_plugins'];
105
		$data['inactive_plugins']   = $all_plugins['inactive_plugins'];
106
107
		// Jetpack & WooCommerce Connect
108
		$data['jetpack_version']    = defined( 'JETPACK__VERSION' ) ? JETPACK__VERSION : 'none';
109
		$data['jetpack_connected']  = ( class_exists( 'Jetpack' ) && is_callable( 'Jetpack::is_active' ) && Jetpack::is_active() ) ? 'yes' : 'no';
110
		$data['jetpack_is_staging'] = ( class_exists( 'Jetpack' ) && is_callable( 'Jetpack::is_staging_site' ) && Jetpack::is_staging_site() ) ? 'yes' : 'no';
111
		$data['connect_installed']  = class_exists( 'WC_Connect_Loader' ) ? 'yes' : 'no';
112
		$data['connect_active']     = ( class_exists( 'WC_Connect_Loader' ) && wp_next_scheduled( 'wc_connect_fetch_service_schemas' ) ) ? 'yes' : 'no';
113
114
		// Store count info
115
		$data['users']              = self::get_user_counts();
116
		$data['products']           = self::get_product_counts();
117
		$data['orders']             = self::get_order_counts();
118
119
		// Payment gateway info
120
		$data['gateways']           = self::get_active_payment_gateways();
121
122
		// Shipping method info
123
		$data['shipping_methods']   = self::get_active_shipping_methods();
124
125
		// Get all WooCommerce options info
126
		$data['settings']           = self::get_all_woocommerce_options_values();
127
128
		// Template overrides
129
		$data['template_overrides'] = self::get_all_template_overrides();
130
131
		return apply_filters( 'woocommerce_tracker_data', $data );
132
	}
133
134
	/**
135
	 * Get the current theme info, theme name and version.
136
	 * @return array
137
	 */
138
	public static function get_theme_info() {
139
		$wp_version = get_bloginfo( 'version' );
140
141
		if ( version_compare( $wp_version, '3.4', '<' ) ) {
142
			$theme_data = get_theme_data( get_stylesheet_directory() . '/style.css' );
143
			$theme_name = $theme_data['Name'];
144
			$theme_version = $theme_data['Version'];
145
		} else {
146
			$theme_data = wp_get_theme();
147
			$theme_name = $theme_data->Name;
148
			$theme_version = $theme_data->Version;
149
		}
150
		$theme_child_theme = is_child_theme() ? 'Yes' : 'No';
151
		$theme_wc_support = ( ! current_theme_supports( 'woocommerce' ) && ! in_array( $theme_data->template, wc_get_core_supported_themes() ) ) ? 'No' : 'Yes';
152
153
		return array( 'name' => $theme_name, 'version' => $theme_version, 'child_theme' => $theme_child_theme, 'wc_support' => $theme_wc_support );
154
	}
155
156
	/**
157
	 * Get WordPress related data.
158
	 * @return array
159
	 */
160
	private static function get_wordpress_info() {
161
		$wp_data = array();
162
163
		$memory = wc_let_to_num( WP_MEMORY_LIMIT );
164
165 View Code Duplication
		if ( function_exists( 'memory_get_usage' ) ) {
166
			$system_memory = wc_let_to_num( @ini_get( 'memory_limit' ) );
167
			$memory        = max( $memory, $system_memory );
168
		}
169
170
		$wp_data['memory_limit'] = size_format( $memory );
171
		$wp_data['debug_mode']   = ( defined('WP_DEBUG') && WP_DEBUG ) ? 'Yes' : 'No';
172
		$wp_data['locale']       = get_locale();
173
		$wp_data['version']      = get_bloginfo( 'version' );
174
		$wp_data['multisite']    = is_multisite() ? 'Yes' : 'No';
175
176
		return $wp_data;
177
	}
178
179
	/**
180
	 * Get server related info.
181
	 * @return array
182
	 */
183
	private static function get_server_info() {
184
		$server_data = array();
185
186
		if ( isset( $_SERVER['SERVER_SOFTWARE'] ) && ! empty( $_SERVER['SERVER_SOFTWARE'] ) ) {
187
			$server_data['software'] = $_SERVER['SERVER_SOFTWARE'];
188
		}
189
190
		if ( function_exists( 'phpversion' ) ) {
191
			$server_data['php_version'] = phpversion();
192
		}
193
194
		if ( function_exists( 'ini_get' ) ) {
195
			$server_data['php_post_max_size'] = size_format( wc_let_to_num( ini_get( 'post_max_size' ) ) );
196
			$server_data['php_time_limt'] = ini_get( 'max_execution_time' );
197
			$server_data['php_max_input_vars'] = ini_get( 'max_input_vars' );
198
			$server_data['php_suhosin'] = extension_loaded( 'suhosin' ) ? 'Yes' : 'No';
199
		}
200
201
		global $wpdb;
202
		$server_data['mysql_version'] = $wpdb->db_version();
203
204
		$server_data['php_max_upload_size'] = size_format( wp_max_upload_size() );
205
		$server_data['php_default_timezone'] = date_default_timezone_get();
206
		$server_data['php_soap'] = class_exists( 'SoapClient' ) ? 'Yes' : 'No';
207
		$server_data['php_fsockopen'] = function_exists( 'fsockopen' ) ? 'Yes' : 'No';
208
		$server_data['php_curl'] = function_exists( 'curl_init' ) ? 'Yes' : 'No';
209
210
		return $server_data;
211
	}
212
213
	/**
214
	 * Get all plugins grouped into activated or not.
215
	 * @return array
216
	 */
217
	private static function get_all_plugins() {
218
		// Ensure get_plugins function is loaded
219
		if( ! function_exists( 'get_plugins' ) ) {
220
			include ABSPATH . '/wp-admin/includes/plugin.php';
221
		}
222
223
		$plugins        	 = get_plugins();
224
		$active_plugins_keys = get_option( 'active_plugins', array() );
225
		$active_plugins 	 = array();
226
227
		foreach ( $plugins as $k => $v ) {
228
			// Take care of formatting the data how we want it.
229
			$formatted = array();
230
			$formatted['name'] = strip_tags( $v['Name'] );
231
			if ( isset( $v['Version'] ) ) {
232
				$formatted['version'] = strip_tags( $v['Version'] );
233
			}
234
			if ( isset( $v['Author'] ) ) {
235
				$formatted['author'] = strip_tags( $v['Author'] );
236
			}
237
			if ( isset( $v['Network'] ) ) {
238
				$formatted['network'] = strip_tags( $v['Network'] );
239
			}
240
			if ( isset( $v['PluginURI'] ) ) {
241
				$formatted['plugin_uri'] = strip_tags( $v['PluginURI'] );
242
			}
243
			if ( in_array( $k, $active_plugins_keys ) ) {
244
				// Remove active plugins from list so we can show active and inactive separately
245
				unset( $plugins[$k] );
246
				$active_plugins[$k] = $formatted;
247
			} else {
248
				$plugins[$k] = $formatted;
249
			}
250
		}
251
252
		return array( 'active_plugins' => $active_plugins, 'inactive_plugins' => $plugins );
253
	}
254
255
	/**
256
	 * Get user totals based on user role.
257
	 * @return array
258
	 */
259
	private static function get_user_counts() {
260
		$user_count          = array();
261
		$user_count_data     = count_users();
262
		$user_count['total'] = $user_count_data['total_users'];
263
264
		// Get user count based on user role
265
		foreach ( $user_count_data['avail_roles'] as $role => $count ) {
266
			$user_count[ $role ] = $count;
267
		}
268
269
		return $user_count;
270
	}
271
272
	/**
273
	 * Get product totals based on product type.
274
	 * @return array
275
	 */
276
	private static function get_product_counts() {
277
		$product_count          = array();
278
		$product_count_data     = wp_count_posts( 'product' );
279
		$product_count['total'] = $product_count_data->publish;
280
281
		$product_statuses = get_terms( 'product_type', array( 'hide_empty' => 0 ) );
282
		foreach ( $product_statuses as $product_status ) {
283
			$product_count[ $product_status->name ] = $product_status->count;
284
		}
285
286
		return $product_count;
287
	}
288
289
	/**
290
	 * Get order counts based on order status.
291
	 * @return array
292
	 */
293
	private static function get_order_counts() {
294
		$order_count      = array();
295
		$order_count_data = wp_count_posts( 'shop_order' );
296
297
		foreach ( wc_get_order_statuses() as $status_slug => $status_name ) {
298
			$order_count[ $status_slug ] = $order_count_data->{ $status_slug };
299
		}
300
301
		return $order_count;
302
	}
303
304
	/**
305
	 * Get a list of all active payment gateways.
306
	 * @return array
307
	 */
308 View Code Duplication
	private static function get_active_payment_gateways() {
309
		$active_gateways = array();
310
		$gateways        = WC()->payment_gateways->payment_gateways();
311
		foreach ( $gateways as $id => $gateway ) {
312
			if ( isset( $gateway->enabled ) && $gateway->enabled == 'yes' ) {
313
				$active_gateways[ $id ] = array( 'title' => $gateway->title, 'supports' => $gateway->supports );
314
			}
315
		}
316
317
		return $active_gateways;
318
	}
319
320
	/**
321
	 * Get a list of all active shipping methods.
322
	 * @return array
323
	 */
324 View Code Duplication
	private static function get_active_shipping_methods() {
325
		$active_methods   = array();
326
		$shipping_methods = WC()->shipping->get_shipping_methods();
327
		foreach ( $shipping_methods as $id => $shipping_method ) {
328
			if ( isset( $shipping_method->enabled ) && $shipping_method->enabled == 'yes' ) {
329
				$active_methods[ $id ] = array( 'title' => $shipping_method->title, 'tax_status' => $shipping_method->tax_status );
330
			}
331
		}
332
333
		return $active_methods;
334
	}
335
336
	/**
337
	 * Get all options starting with woocommerce_ prefix.
338
	 * @return array
339
	 */
340
	private static function get_all_woocommerce_options_values() {
341
		return array(
342
			'version'                               => WC()->version,
343
			'currency'                              => get_woocommerce_currency(),
344
			'base_location'                         => WC()->countries->get_base_country(),
345
			'selling_locations'                     => WC()->countries->get_allowed_countries(),
346
			'api_enabled'                           => get_option( 'woocommerce_api_enabled' ),
347
			'weight_unit'                           => get_option( 'woocommerce_weight_unit' ),
348
			'dimension_unit'                        => get_option( 'woocommerce_dimension_unit' ),
349
			'download_method'                       => get_option( 'woocommerce_file_download_method' ),
350
			'download_require_login'                => get_option( 'woocommerce_downloads_require_login' ),
351
			'calc_taxes'                            => get_option( 'woocommerce_calc_taxes' ),
352
			'coupons_enabled'                       => get_option( 'woocommerce_enable_coupons' ),
353
			'guest_checkout'                        => get_option( 'woocommerce_enable_guest_checkout'),
354
			'secure_checkout'                       => get_option( 'woocommerce_force_ssl_checkout' ),
355
			'enable_signup_and_login_from_checkout' => get_option( 'woocommerce_enable_signup_and_login_from_checkout' ),
356
			'enable_myaccount_registration'         => get_option( 'woocommerce_enable_myaccount_registration' ),
357
			'registration_generate_username'        => get_option( 'woocommerce_registration_generate_username' ),
358
			'registration_generate_password'        => get_option( 'woocommerce_registration_generate_password' ),
359
		);
360
	}
361
362
	/**
363
	 * Look for any template override and return filenames.
364
	 * @return array
365
	 */
366
	private static function get_all_template_overrides() {
367
		$override_data  = array();
368
		$template_paths = apply_filters( 'woocommerce_template_overrides_scan_paths', array( 'WooCommerce' => WC()->plugin_path() . '/templates/' ) );
369
		$scanned_files  = array();
370
371
		require_once( WC()->plugin_path() . '/includes/admin/class-wc-admin-status.php' );
372
373
		foreach ( $template_paths as $plugin_name => $template_path ) {
374
			$scanned_files[ $plugin_name ] = WC_Admin_Status::scan_template_files( $template_path );
375
		}
376
377
		foreach ( $scanned_files as $plugin_name => $files ) {
378
			foreach ( $files as $file ) {
379 View Code Duplication
				if ( file_exists( get_stylesheet_directory() . '/' . $file ) ) {
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...
380
					$theme_file = get_stylesheet_directory() . '/' . $file;
381
				} elseif ( file_exists( get_stylesheet_directory() . '/woocommerce/' . $file ) ) {
382
					$theme_file = get_stylesheet_directory() . '/woocommerce/' . $file;
383
				} elseif ( file_exists( get_template_directory() . '/' . $file ) ) {
384
					$theme_file = get_template_directory() . '/' . $file;
385
				} elseif( file_exists( get_template_directory() . '/woocommerce/' . $file ) ) {
386
					$theme_file = get_template_directory() . '/woocommerce/' . $file;
387
				} else {
388
					$theme_file = false;
389
				}
390
391
				if ( $theme_file !== false ) {
392
					$override_data[] = basename( $theme_file );
393
				}
394
			}
395
		}
396
		return $override_data;
397
	}
398
}
399
400
WC_Tracker::init();
401