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.

api/class-wc-rest-tax-classes-controller.php (3 issues)

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
 * REST API Tax Classes controller
4
 *
5
 * Handles requests to the /taxes/classes endpoint.
6
 *
7
 * @author   WooThemes
8
 * @category API
9
 * @package  WooCommerce/API
10
 * @since    2.6.0
11
 */
12
13
if ( ! defined( 'ABSPATH' ) ) {
14
	exit;
15
}
16
17
/**
18
 * REST API Tax Classes controller class.
19
 *
20
 * @package WooCommerce/API
21
 * @extends WC_REST_Controller
22
 */
23
class WC_REST_Tax_Classes_Controller extends WC_REST_Controller {
24
25
	/**
26
	 * Endpoint namespace.
27
	 *
28
	 * @var string
29
	 */
30
	protected $namespace = 'wc/v1';
31
32
	/**
33
	 * Route base.
34
	 *
35
	 * @var string
36
	 */
37
	protected $rest_base = 'taxes/classes';
38
39
	/**
40
	 * Register the routes for tax classes.
41
	 */
42
	public function register_routes() {
43
		register_rest_route( $this->namespace, '/' . $this->rest_base, array(
44
			array(
45
				'methods'             => WP_REST_Server::READABLE,
46
				'callback'            => array( $this, 'get_items' ),
47
				'permission_callback' => array( $this, 'get_items_permissions_check' ),
48
				'args'                => $this->get_collection_params(),
49
			),
50
			array(
51
				'methods'             => WP_REST_Server::CREATABLE,
52
				'callback'            => array( $this, 'create_item' ),
53
				'permission_callback' => array( $this, 'create_item_permissions_check' ),
54
				'args'                => $this->get_endpoint_args_for_item_schema( WP_REST_Server::CREATABLE ),
55
			),
56
			'schema' => array( $this, 'get_public_item_schema' ),
57
		) );
58
59
		register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P<slug>\w[\w\s\-]*)', array(
60
			array(
61
				'methods'             => WP_REST_Server::DELETABLE,
62
				'callback'            => array( $this, 'delete_item' ),
63
				'permission_callback' => array( $this, 'delete_item_permissions_check' ),
64
				'args'                => array(
65
					'force' => array(
66
						'default'     => false,
67
						'description' => __( 'Required to be true, as resource does not support trashing.', 'woocommerce' ),
68
					),
69
				),
70
			),
71
			'schema' => array( $this, 'get_public_item_schema' ),
72
		) );
73
	}
74
75
	/**
76
	 * Check whether a given request has permission to read tax classes.
77
	 *
78
	 * @param  WP_REST_Request $request Full details about the request.
79
	 * @return WP_Error|boolean
80
	 */
81 View Code Duplication
	public function get_items_permissions_check( $request ) {
0 ignored issues
show
This method seems to be duplicated in 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...
82
		if ( ! wc_rest_check_manager_permissions( 'settings', 'read' ) ) {
83
			return new WP_Error( 'woocommerce_rest_cannot_view', __( 'Sorry, you cannot list resources.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) );
84
		}
85
86
		return true;
87
	}
88
89
	/**
90
	 * Check if a given request has access create tax classes.
91
	 *
92
	 * @param  WP_REST_Request $request Full details about the request.
93
	 * @return boolean
94
	 */
95 View Code Duplication
	public function create_item_permissions_check( $request ) {
0 ignored issues
show
This method seems to be duplicated in 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...
96
		if ( ! wc_rest_check_manager_permissions( 'settings', 'create' ) ) {
97
			return new WP_Error( 'woocommerce_rest_cannot_create', __( 'Sorry, you are not allowed to create resources.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) );
98
		}
99
100
		return true;
101
	}
102
103
	/**
104
	 * Check if a given request has access delete a tax.
105
	 *
106
	 * @param  WP_REST_Request $request Full details about the request.
107
	 * @return boolean
108
	 */
109 View Code Duplication
	public function delete_item_permissions_check( $request ) {
0 ignored issues
show
This method seems to be duplicated in 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...
110
		if ( ! wc_rest_check_manager_permissions( 'settings', 'delete' ) ) {
111
			return new WP_Error( 'woocommerce_rest_cannot_delete', __( 'Sorry, you are not allowed to delete this resource.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) );
112
		}
113
114
		return true;
115
	}
116
117
	/**
118
	 * Get all tax classes.
119
	 *
120
	 * @param WP_REST_Request $request
121
	 * @return array
122
	 */
123
	public function get_items( $request ) {
124
		$tax_classes = array();
125
126
		// Add standard class.
127
		$tax_classes[] = array(
128
			'slug' => 'standard',
129
			'name' => __( 'Standard Rate', 'woocommerce' ),
130
		);
131
132
		$classes = WC_Tax::get_tax_classes();
133
134
		foreach ( $classes as $class ) {
135
			$tax_classes[] = array(
136
				'slug' => sanitize_title( $class ),
137
				'name' => $class,
138
			);
139
		}
140
141
		$data = array();
142
		foreach ( $tax_classes as $tax_class ) {
143
			$class  = $this->prepare_item_for_response( $tax_class, $request );
144
			$class  = $this->prepare_response_for_collection( $class );
145
			$data[] = $class;
146
		}
147
148
		return rest_ensure_response( $data );
149
	}
150
151
	/**
152
	 * Create a single tax.
153
	 *
154
	 * @param WP_REST_Request $request Full details about the request.
155
	 * @return WP_Error|WP_REST_Response
156
	 */
157
	public function create_item( $request ) {
158
		$exists    = false;
159
		$classes   = WC_Tax::get_tax_classes();
160
		$tax_class = array(
161
			'slug' => sanitize_title( $request['name'] ),
162
			'name' => $request['name'],
163
		);
164
165
		// Check if class exists.
166
		foreach ( $classes as $key => $class ) {
167
			if ( sanitize_title( $class ) === $tax_class['slug'] ) {
168
				$exists = true;
169
				break;
170
			}
171
		}
172
173
		// Return error if tax class already exists.
174
		if ( $exists ) {
175
			return new WP_Error( 'woocommerce_rest_tax_class_exists', __( 'Cannot create existing resource.', 'woocommerce' ), array( 'status' => 400 ) );
176
		}
177
178
		// Add the new class.
179
		$classes[] = $tax_class['name'];
180
181
		update_option( 'woocommerce_tax_classes', implode( "\n", $classes ) );
182
183
		$this->update_additional_fields_for_object( $tax_class, $request );
184
185
		/**
186
		 * Fires after a tax class is created or updated via the REST API.
187
		 *
188
		 * @param stdClass        $tax_class Data used to create the tax class.
189
		 * @param WP_REST_Request $request   Request object.
190
		 * @param boolean         $creating  True when creating tax class, false when updating tax class.
191
		 */
192
		do_action( 'woocommerce_rest_insert_tax_class', (object) $tax_class, $request, true );
193
194
		$request->set_param( 'context', 'edit' );
195
		$response = $this->prepare_item_for_response( $tax_class, $request );
196
		$response = rest_ensure_response( $response );
197
		$response->set_status( 201 );
198
		$response->header( 'Location', rest_url( sprintf( '/%s/%s/%s', $this->namespace, $this->rest_base, $tax_class['slug'] ) ) );
199
200
		return $response;
201
	}
202
203
	/**
204
	 * Delete a single tax class.
205
	 *
206
	 * @param WP_REST_Request $request Full details about the request.
207
	 * @return WP_Error|WP_REST_Response
208
	 */
209
	public function delete_item( $request ) {
210
		global $wpdb;
211
212
		$force = isset( $request['force'] ) ? (bool) $request['force'] : false;
213
214
		// We don't support trashing for this type, error out.
215
		if ( ! $force ) {
216
			return new WP_Error( 'woocommerce_rest_trash_not_supported', __( 'Taxes do not support trashing.', 'woocommerce' ), array( 'status' => 501 ) );
217
		}
218
219
		$tax_class = array(
220
			'slug' => sanitize_title( $request['slug'] ),
221
			'name' => '',
222
		);
223
		$classes = WC_Tax::get_tax_classes();
224
		$deleted = false;
225
226
		foreach ( $classes as $key => $class ) {
227
			if ( sanitize_title( $class ) === $tax_class['slug'] ) {
228
				$tax_class['name'] = $class;
229
				unset( $classes[ $key ] );
230
				$deleted = true;
231
				break;
232
			}
233
		}
234
235
		if ( ! $deleted ) {
236
			return new WP_Error( 'woocommerce_rest_invalid_id', __( 'Invalid resource id.', 'woocommerce' ), array( 'status' => 400 ) );
237
		}
238
239
		update_option( 'woocommerce_tax_classes', implode( "\n", $classes ) );
240
241
		// Delete tax rate locations locations from the selected class.
242
		$wpdb->query( $wpdb->prepare( "
243
			DELETE locations.*
244
			FROM {$wpdb->prefix}woocommerce_tax_rate_locations AS locations
245
			INNER JOIN
246
				{$wpdb->prefix}woocommerce_tax_rates AS rates
247
				ON rates.tax_rate_id = locations.tax_rate_id
248
			WHERE rates.tax_rate_class = '%s'
249
		", $tax_class['slug'] ) );
250
251
		// Delete tax rates in the selected class.
252
		$wpdb->delete( $wpdb->prefix . 'woocommerce_tax_rates', array( 'tax_rate_class' => $tax_class['slug'] ), array( '%s' ) );
253
254
		$request->set_param( 'context', 'edit' );
255
		$response = $this->prepare_item_for_response( $tax_class, $request );
256
257
		/**
258
		 * Fires after a tax class is deleted via the REST API.
259
		 *
260
		 * @param stdClass         $tax_class The tax data.
261
		 * @param WP_REST_Response $response  The response returned from the API.
262
		 * @param WP_REST_Request  $request   The request sent to the API.
263
		 */
264
		do_action( 'woocommerce_rest_delete_tax', (object) $tax_class, $response, $request );
265
266
		return $response;
267
	}
268
269
	/**
270
	 * Prepare a single tax class output for response.
271
	 *
272
	 * @param array $tax_class Tax class data.
273
	 * @param WP_REST_Request $request Request object.
274
	 * @return WP_REST_Response $response Response data.
275
	 */
276
	public function prepare_item_for_response( $tax_class, $request ) {
277
		$data = $tax_class;
278
279
		$context = ! empty( $request['context'] ) ? $request['context'] : 'view';
280
		$data    = $this->add_additional_fields_to_object( $data, $request );
281
		$data    = $this->filter_response_by_context( $data, $context );
282
283
		// Wrap the data in a response object.
284
		$response = rest_ensure_response( $data );
285
286
		$response->add_links( $this->prepare_links() );
287
288
		/**
289
		 * Filter tax object returned from the REST API.
290
		 *
291
		 * @param WP_REST_Response $response  The response object.
292
		 * @param stdClass         $tax_class Tax object used to create response.
293
		 * @param WP_REST_Request  $request   Request object.
294
		 */
295
		return apply_filters( 'woocommerce_rest_prepare_tax', $response, (object) $tax_class, $request );
296
	}
297
298
	/**
299
	 * Prepare links for the request.
300
	 *
301
	 * @return array Links for the given tax class.
302
	 */
303
	protected function prepare_links() {
304
		$links = array(
305
			'collection' => array(
306
				'href' => rest_url( sprintf( '/%s/%s', $this->namespace, $this->rest_base ) ),
307
			),
308
		);
309
310
		return $links;
311
	}
312
313
	/**
314
	 * Get the Tax Classes schema, conforming to JSON Schema
315
	 *
316
	 * @return array
317
	 */
318
	public function get_item_schema() {
319
		$schema = array(
320
			'$schema'    => 'http://json-schema.org/draft-04/schema#',
321
			'title'      => 'tax_class',
322
			'type'       => 'object',
323
			'properties' => array(
324
				'slug' => array(
325
					'description' => __( 'Unique identifier for the resource.', 'woocommerce' ),
326
					'type'        => 'string',
327
					'context'     => array( 'view', 'edit' ),
328
					'readonly'    => true,
329
				),
330
				'name' => array(
331
					'description' => __( 'Tax class name.', 'woocommerce' ),
332
					'type'        => 'string',
333
					'context'     => array( 'view', 'edit' ),
334
					'required'    => true,
335
					'arg_options' => array(
336
						'sanitize_callback' => 'sanitize_text_field',
337
					),
338
				),
339
			),
340
		);
341
342
		return $this->add_additional_fields_schema( $schema );
343
	}
344
345
	/**
346
	 * Get the query params for collections.
347
	 *
348
	 * @return array
349
	 */
350
	public function get_collection_params() {
351
		return array(
352
			'context' => $this->get_context_param( array( 'default' => 'view' ) ),
353
		);
354
	}
355
}
356