Issues (942)

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-privacy-exporters.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
 * Personal data exporters.
4
 *
5
 * @since 3.4.0
6
 * @package WooCommerce\Classes
7
 */
8
9
defined( 'ABSPATH' ) || exit;
10
11
/**
12
 * WC_Privacy_Exporters Class.
13
 */
14
class WC_Privacy_Exporters {
15
	/**
16
	 * Finds and exports customer data by email address.
17
	 *
18
	 * @since 3.4.0
19
	 * @param string $email_address The user email address.
20
	 * @return array An array of personal data in name value pairs
21
	 */
22 1
	public static function customer_data_exporter( $email_address ) {
23 1
		$user           = get_user_by( 'email', $email_address ); // Check if user has an ID in the DB to load stored personal data.
24 1
		$data_to_export = array();
25
26 1
		if ( $user instanceof WP_User ) {
27 1
			$customer_personal_data = self::get_customer_personal_data( $user );
28 1
			if ( ! empty( $customer_personal_data ) ) {
29 1
				$data_to_export[] = array(
30 1
					'group_id'    => 'woocommerce_customer',
31 1
					'group_label' => __( 'Customer Data', 'woocommerce' ),
32 1
					'item_id'     => 'user',
33 1
					'data'        => $customer_personal_data,
34
				);
35
			}
36
		}
37
38
		return array(
39 1
			'data' => $data_to_export,
40
			'done' => true,
41
		);
42
	}
43
44
	/**
45
	 * Finds and exports data which could be used to identify a person from WooCommerce data associated with an email address.
46
	 *
47
	 * Orders are exported in blocks of 10 to avoid timeouts.
48
	 *
49
	 * @since 3.4.0
50
	 * @param string $email_address The user email address.
51
	 * @param int    $page  Page.
52
	 * @return array An array of personal data in name value pairs
53
	 */
54 1
	public static function order_data_exporter( $email_address, $page ) {
55 1
		$done           = true;
56 1
		$page           = (int) $page;
57 1
		$user           = get_user_by( 'email', $email_address ); // Check if user has an ID in the DB to load stored personal data.
58 1
		$data_to_export = array();
59
		$order_query    = array(
60 1
			'limit'    => 10,
61 1
			'page'     => $page,
62 1
			'customer' => array( $email_address ),
63
		);
64
65 1
		if ( $user instanceof WP_User ) {
66 1
			$order_query['customer'][] = (int) $user->ID;
67
		}
68
69 1
		$orders = wc_get_orders( $order_query );
70
71 1
		if ( 0 < count( $orders ) ) {
72 1
			foreach ( $orders as $order ) {
73 1
				$data_to_export[] = array(
74 1
					'group_id'    => 'woocommerce_orders',
75 1
					'group_label' => __( 'Orders', 'woocommerce' ),
76 1
					'item_id'     => 'order-' . $order->get_id(),
77 1
					'data'        => self::get_order_personal_data( $order ),
78
				);
79
			}
80 1
			$done = 10 > count( $orders );
81
		}
82
83
		return array(
84 1
			'data' => $data_to_export,
85 1
			'done' => $done,
86
		);
87
	}
88
89
	/**
90
	 * Finds and exports customer download logs by email address.
91
	 *
92
	 * @since 3.4.0
93
	 * @param string $email_address The user email address.
94
	 * @param int    $page  Page.
95
	 * @throws Exception When WC_Data_Store validation fails.
96
	 * @return array An array of personal data in name value pairs
97
	 */
98
	public static function download_data_exporter( $email_address, $page ) {
99
		$done            = true;
100
		$page            = (int) $page;
101
		$user            = get_user_by( 'email', $email_address ); // Check if user has an ID in the DB to load stored personal data.
102
		$data_to_export  = array();
103
		$downloads_query = array(
104
			'limit' => 10,
105
			'page'  => $page,
106
		);
107
108 View Code Duplication
		if ( $user instanceof WP_User ) {
109
			$downloads_query['user_id'] = (int) $user->ID;
110
		} else {
111
			$downloads_query['user_email'] = $email_address;
112
		}
113
114
		$customer_download_data_store     = WC_Data_Store::load( 'customer-download' );
115
		$customer_download_log_data_store = WC_Data_Store::load( 'customer-download-log' );
116
		$downloads                        = $customer_download_data_store->get_downloads( $downloads_query );
117
118
		if ( 0 < count( $downloads ) ) {
119
			foreach ( $downloads as $download ) {
120
				$data_to_export[] = array(
121
					'group_id'    => 'woocommerce_downloads',
122
					/* translators: This is the headline for a list of downloads purchased from the store for a given user. */
123
					'group_label' => __( 'Purchased Downloads', 'woocommerce' ),
124
					'item_id'     => 'download-' . $download->get_id(),
125
					'data'        => self::get_download_personal_data( $download ),
126
				);
127
128
				$download_logs = $customer_download_log_data_store->get_download_logs_for_permission( $download->get_id() );
129
130
				foreach ( $download_logs as $download_log ) {
131
					$data_to_export[] = array(
132
						'group_id'    => 'woocommerce_download_logs',
133
						/* translators: This is the headline for a list of access logs for downloads purchased from the store for a given user. */
134
						'group_label' => __( 'Access to Purchased Downloads', 'woocommerce' ),
135
						'item_id'     => 'download-log-' . $download_log->get_id(),
136
						'data'        => array(
137
							array(
138
								'name'  => __( 'Download ID', 'woocommerce' ),
139
								'value' => $download_log->get_permission_id(),
140
							),
141
							array(
142
								'name'  => __( 'Timestamp', 'woocommerce' ),
143
								'value' => $download_log->get_timestamp(),
144
							),
145
							array(
146
								'name'  => __( 'IP Address', 'woocommerce' ),
147
								'value' => $download_log->get_user_ip_address(),
148
							),
149
						),
150
					);
151
				}
152
			}
153
			$done = 10 > count( $downloads );
154
		}
155
156
		return array(
157
			'data' => $data_to_export,
158
			'done' => $done,
159
		);
160
	}
161
162
	/**
163
	 * Get personal data (key/value pairs) for a user object.
164
	 *
165
	 * @since 3.4.0
166
	 * @param WP_User $user user object.
167
	 * @throws Exception If customer cannot be read/found and $data is set to WC_Customer class.
168
	 * @return array
169
	 */
170 1
	protected static function get_customer_personal_data( $user ) {
171 1
		$personal_data = array();
172 1
		$customer      = new WC_Customer( $user->ID );
173
174 1
		if ( ! $customer ) {
175
			return array();
176
		}
177
178 1
		$props_to_export = apply_filters( 'woocommerce_privacy_export_customer_personal_data_props', array(
179 1
			'billing_first_name'  => __( 'Billing First Name', 'woocommerce' ),
180 1
			'billing_last_name'   => __( 'Billing Last Name', 'woocommerce' ),
181 1
			'billing_company'     => __( 'Billing Company', 'woocommerce' ),
182 1
			'billing_address_1'   => __( 'Billing Address 1', 'woocommerce' ),
183 1
			'billing_address_2'   => __( 'Billing Address 2', 'woocommerce' ),
184 1
			'billing_city'        => __( 'Billing City', 'woocommerce' ),
185 1
			'billing_postcode'    => __( 'Billing Postal/Zip Code', 'woocommerce' ),
186 1
			'billing_state'       => __( 'Billing State', 'woocommerce' ),
187 1
			'billing_country'     => __( 'Billing Country', 'woocommerce' ),
188 1
			'billing_phone'       => __( 'Phone Number', 'woocommerce' ),
189 1
			'billing_email'       => __( 'Email Address', 'woocommerce' ),
190 1
			'shipping_first_name' => __( 'Shipping First Name', 'woocommerce' ),
191 1
			'shipping_last_name'  => __( 'Shipping Last Name', 'woocommerce' ),
192 1
			'shipping_company'    => __( 'Shipping Company', 'woocommerce' ),
193 1
			'shipping_address_1'  => __( 'Shipping Address 1', 'woocommerce' ),
194 1
			'shipping_address_2'  => __( 'Shipping Address 2', 'woocommerce' ),
195 1
			'shipping_city'       => __( 'Shipping City', 'woocommerce' ),
196 1
			'shipping_postcode'   => __( 'Shipping Postal/Zip Code', 'woocommerce' ),
197 1
			'shipping_state'      => __( 'Shipping State', 'woocommerce' ),
198 1
			'shipping_country'    => __( 'Shipping Country', 'woocommerce' ),
199 1
		), $customer );
200
201 1
		foreach ( $props_to_export as $prop => $description ) {
202 1
			$value = '';
203
204 1
			if ( is_callable( array( $customer, 'get_' . $prop ) ) ) {
205 1
				$value = $customer->{"get_$prop"}( 'edit' );
206
			}
207
208 1
			$value = apply_filters( 'woocommerce_privacy_export_customer_personal_data_prop_value', $value, $prop, $customer );
209
210 1
			if ( $value ) {
211 1
				$personal_data[] = array(
212 1
					'name'  => $description,
213 1
					'value' => $value,
214
				);
215
			}
216
		}
217
218
		/**
219
		 * Allow extensions to register their own personal data for this customer for the export.
220
		 *
221
		 * @since 3.4.0
222
		 * @param array    $personal_data Array of name value pairs.
223
		 * @param WC_Order $order A customer object.
224
		 */
225 1
		$personal_data = apply_filters( 'woocommerce_privacy_export_customer_personal_data', $personal_data, $customer );
226
227 1
		return $personal_data;
228
	}
229
230
	/**
231
	 * Get personal data (key/value pairs) for an order object.
232
	 *
233
	 * @since 3.4.0
234
	 * @param WC_Order $order Order object.
235
	 * @return array
236
	 */
237 1
	protected static function get_order_personal_data( $order ) {
238 1
		$personal_data   = array();
239 1
		$props_to_export = apply_filters( 'woocommerce_privacy_export_order_personal_data_props', array(
240 1
			'order_number'               => __( 'Order Number', 'woocommerce' ),
241 1
			'date_created'               => __( 'Order Date', 'woocommerce' ),
242 1
			'total'                      => __( 'Order Total', 'woocommerce' ),
243 1
			'items'                      => __( 'Items Purchased', 'woocommerce' ),
244 1
			'customer_ip_address'        => __( 'IP Address', 'woocommerce' ),
245 1
			'customer_user_agent'        => __( 'Browser User Agent', 'woocommerce' ),
246 1
			'formatted_billing_address'  => __( 'Billing Address', 'woocommerce' ),
247 1
			'formatted_shipping_address' => __( 'Shipping Address', 'woocommerce' ),
248 1
			'billing_phone'              => __( 'Phone Number', 'woocommerce' ),
249 1
			'billing_email'              => __( 'Email Address', 'woocommerce' ),
250 1
		), $order );
251
252 1
		foreach ( $props_to_export as $prop => $name ) {
253 1
			$value = '';
254
255 1
			switch ( $prop ) {
256
				case 'items':
257 1
					$item_names = array();
258 1
					foreach ( $order->get_items() as $item ) {
259 1
						$item_names[] = $item->get_name() . ' x ' . $item->get_quantity();
260
					}
261 1
					$value = implode( ', ', $item_names );
262 1
					break;
263
				case 'date_created':
264 1
					$value = wc_format_datetime( $order->get_date_created(), get_option( 'date_format' ) . ', ' . get_option( 'time_format' ) );
265 1
					break;
266
				case 'formatted_billing_address':
267
				case 'formatted_shipping_address':
268 1
					$value = preg_replace( '#<br\s*/?>#i', ', ', $order->{"get_$prop"}() );
269 1
					break;
270
				default:
271 1
					if ( is_callable( array( $order, 'get_' . $prop ) ) ) {
272 1
						$value = $order->{"get_$prop"}();
273
					}
274 1
					break;
275
			}
276
277 1
			$value = apply_filters( 'woocommerce_privacy_export_order_personal_data_prop', $value, $prop, $order );
278
279 1
			if ( $value ) {
280 1
				$personal_data[] = array(
281 1
					'name'  => $name,
282 1
					'value' => $value,
283
				);
284
			}
285
		}
286
287
		// Export meta data.
288 1
		$meta_to_export = apply_filters( 'woocommerce_privacy_export_order_personal_data_meta', array(
289 1
			'Payer first name'     => __( 'Payer first name', 'woocommerce' ),
290 1
			'Payer last name'      => __( 'Payer last name', 'woocommerce' ),
291 1
			'Payer PayPal address' => __( 'Payer PayPal address', 'woocommerce' ),
292 1
			'Transaction ID'       => __( 'Transaction ID', 'woocommerce' ),
293
		) );
294
295 1
		if ( ! empty( $meta_to_export ) && is_array( $meta_to_export ) ) {
296 1
			foreach ( $meta_to_export as $meta_key => $name ) {
297 1
				$value = apply_filters( 'woocommerce_privacy_export_order_personal_data_meta_value', $order->get_meta( $meta_key ), $meta_key, $order );
298
299 1
				if ( $value ) {
300
					$personal_data[] = array(
301
						'name'  => $name,
302
						'value' => $value,
303
					);
304
				}
305
			}
306
		}
307
308
		/**
309
		 * Allow extensions to register their own personal data for this order for the export.
310
		 *
311
		 * @since 3.4.0
312
		 * @param array    $personal_data Array of name value pairs to expose in the export.
313
		 * @param WC_Order $order An order object.
314
		 */
315 1
		$personal_data = apply_filters( 'woocommerce_privacy_export_order_personal_data', $personal_data, $order );
316
317 1
		return $personal_data;
318
	}
319
320
	/**
321
	 * Get personal data (key/value pairs) for a download object.
322
	 *
323
	 * @since 3.4.0
324
	 * @param WC_Order $download Download object.
325
	 * @return array
326
	 */
327
	protected static function get_download_personal_data( $download ) {
328
		$personal_data = array(
329
			array(
330
				'name'  => __( 'Download ID', 'woocommerce' ),
331
				'value' => $download->get_id(),
332
			),
333
			array(
334
				'name'  => __( 'Order ID', 'woocommerce' ),
335
				'value' => $download->get_order_id(),
336
			),
337
			array(
338
				'name'  => __( 'Product', 'woocommerce' ),
339
				'value' => get_the_title( $download->get_product_id() ),
340
			),
341
			array(
342
				'name'  => __( 'User email', 'woocommerce' ),
343
				'value' => $download->get_user_email(),
344
			),
345
			array(
346
				'name'  => __( 'Downloads remaining', 'woocommerce' ),
347
				'value' => $download->get_downloads_remaining(),
348
			),
349
			array(
350
				'name'  => __( 'Download count', 'woocommerce' ),
351
				'value' => $download->get_download_count(),
352
			),
353
			array(
354
				'name'  => __( 'Access granted', 'woocommerce' ),
355
				'value' => date( 'Y-m-d', $download->get_access_granted( 'edit' )->getTimestamp() ),
356
			),
357
			array(
358
				'name'  => __( 'Access expires', 'woocommerce' ),
359
				'value' => ! is_null( $download->get_access_expires( 'edit' ) ) ? date( 'Y-m-d', $download->get_access_expires( 'edit' )->getTimestamp() ) : null,
360
			),
361
		);
362
363
		/**
364
		 * Allow extensions to register their own personal data for this download for the export.
365
		 *
366
		 * @since 3.4.0
367
		 * @param array    $personal_data Array of name value pairs to expose in the export.
368
		 * @param WC_Order $order An order object.
369
		 */
370
		$personal_data = apply_filters( 'woocommerce_privacy_export_download_personal_data', $personal_data, $download );
371
372
		return $personal_data;
373
	}
374
375
	/**
376
	 * Finds and exports payment tokens by email address for a customer.
377
	 *
378
	 * @since 3.4.0
379
	 * @param string $email_address The user email address.
380
	 * @param int    $page  Page.
381
	 * @return array An array of personal data in name value pairs
382
	 */
383
	public static function customer_tokens_exporter( $email_address, $page ) {
384
		$user           = get_user_by( 'email', $email_address ); // Check if user has an ID in the DB to load stored personal data.
385
		$data_to_export = array();
386
387
		if ( ! $user instanceof WP_User ) {
0 ignored issues
show
The class WP_User does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
388
			return array(
389
				'data' => $data_to_export,
390
				'done' => true,
391
			);
392
		}
393
394
		$tokens = WC_Payment_Tokens::get_tokens( array(
395
			'user_id' => $user->ID,
396
			'limit'   => 10,
397
			'page'    => $page,
398
		) );
399
400
		if ( 0 < count( $tokens ) ) {
401
			foreach ( $tokens as $token ) {
402
				$data_to_export[] = array(
403
					'group_id'    => 'woocommerce_tokens',
404
					'group_label' => __( 'Payment Tokens', 'woocommerce' ),
405
					'item_id'     => 'token-' . $token->get_id(),
406
					'data'        => array(
407
						array(
408
							'name'  => __( 'Token', 'woocommerce' ),
409
							'value' => $token->get_display_name(),
410
						),
411
					),
412
				);
413
			}
414
			$done = 10 > count( $tokens );
415
		} else {
416
			$done = true;
417
		}
418
419
		return array(
420
			'data' => $data_to_export,
421
			'done' => $done,
422
		);
423
	}
424
}
425