Issues (865)

Security Analysis    4 potential vulnerabilities

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

  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.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  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.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  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.
  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.
  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.
  Code Injection (1)
Code Injection enables an attacker to execute arbitrary code on the server.
  Variable Injection (2)
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
  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.
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  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.
  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.
  Cross-Site Scripting (1)
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.
  Header Injection
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.

data-stores/class-getpaid-item-data-store.php (3 issues)

Labels
1
<?php
2
/**
3
 * GetPaid_Item_Data_Store class file.
4
 *
5
 */
6
if ( ! defined( 'ABSPATH' ) ) {
7
	exit;
8
}
9
10
/**
11
 * Item Data Store: Stored in CPT.
12
 *
13
 * @version  1.0.19
14
 */
15
class GetPaid_Item_Data_Store extends GetPaid_Data_Store_WP {
16
17
	/**
18
	 * Data stored in meta keys, but not considered "meta" for an item.
19
	 *
20
	 * @since 1.0.19
21
	 * @var array
22
	 */
23
	protected $internal_meta_keys = array(
24
		'_wpinv_price',
25
		'_wpinv_vat_rule',
26
		'_wpinv_vat_class',
27
		'_wpinv_type',
28
		'_wpinv_custom_id',
29
		'_wpinv_custom_name',
30
		'_wpinv_custom_singular_name',
31
		'_wpinv_editable',
32
		'_wpinv_dynamic_pricing',
33
		'_minimum_price',
34
		'_wpinv_is_recurring',
35
		'_wpinv_recurring_period',
36
		'_wpinv_recurring_interval',
37
		'_wpinv_recurring_limit',
38
		'_wpinv_free_trial',
39
		'_wpinv_trial_period',
40
		'_wpinv_trial_interval',
41
	);
42
43
	/**
44
	 * A map of meta keys to data props.
45
	 *
46
	 * @since 1.0.19
47
	 *
48
	 * @var array
49
	 */
50
	protected $meta_key_to_props = array(
51
		'_wpinv_price'                => 'price',
52
		'_wpinv_vat_rule'             => 'vat_rule',
53
		'_wpinv_vat_class'            => 'vat_class',
54
		'_wpinv_type'                 => 'type',
55
		'_wpinv_custom_id'            => 'custom_id',
56
		'_wpinv_custom_name'          => 'custom_name',
57
		'_wpinv_custom_singular_name' => 'custom_singular_name',
58
		'_wpinv_editable'             => 'is_editable',
59
		'_wpinv_dynamic_pricing'      => 'is_dynamic_pricing',
60
		'_minimum_price'              => 'minimum_price',
61
		'_wpinv_custom_name'          => 'custom_name',
62
		'_wpinv_is_recurring'         => 'is_recurring',
63
		'_wpinv_recurring_period'     => 'recurring_period',
64
		'_wpinv_recurring_interval'   => 'recurring_interval',
65
		'_wpinv_recurring_limit'      => 'recurring_limit',
66
		'_wpinv_free_trial'           => 'is_free_trial',
67
		'_wpinv_trial_period'         => 'trial_period',
68
		'_wpinv_trial_interval'       => 'trial_interval',
69
		'_wpinv_version'              => 'version',
70
	);
71
72
	/*
73
	|--------------------------------------------------------------------------
74
	| CRUD Methods
75
	|--------------------------------------------------------------------------
76
	*/
77
78
	/**
79
	 * Method to create a new item in the database.
80
	 *
81
	 * @param WPInv_Item $item Item object.
82
	 */
83
	public function create( &$item ) {
84
		$item->set_version( WPINV_VERSION );
85
		$item->set_date_created( current_time( 'mysql' ) );
86
87
		// Create a new post.
88
		$id = wp_insert_post(
89
			apply_filters(
90
				'getpaid_new_item_data',
91
				array(
92
					'post_date'    => $item->get_date_created( 'edit' ),
93
					'post_type'    => 'wpi_item',
94
					'post_status'  => $this->get_post_status( $item ),
95
					'ping_status'  => 'closed',
96
					'post_author'  => $item->get_author( 'edit' ),
97
					'post_title'   => $item->get_name( 'edit' ),
98
					'post_parent'  => $item->get_parent_id(),
99
					'post_excerpt' => $item->get_description( 'edit' ),
100
				)
101
			),
102
			true
103
		);
104
105
		if ( $id && ! is_wp_error( $id ) ) {
106
			$item->set_id( $id );
0 ignored issues
show
It seems like $id can also be of type WP_Error; however, parameter $id of GetPaid_Data::set_id() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

106
			$item->set_id( /** @scrutinizer ignore-type */ $id );
Loading history...
107
			$this->update_post_meta( $item );
108
			$item->save_meta_data();
109
			$item->apply_changes();
110
			$this->clear_caches( $item );
111
			do_action( 'getpaid_new_item', $item );
112
			return true;
113
		}
114
115
		if ( is_wp_error( $id ) ) {
116
			$item->last_error = $id->get_error_message();
117
		}
118
119
		return false;
120
	}
121
122
	/**
123
	 * Method to read an item from the database.
124
	 *
125
	 * @param WPInv_Item $item Item object.
126
	 *
127
	 */
128
	public function read( &$item ) {
129
130
		$item->set_defaults();
131
		$item_object = get_post( $item->get_id() );
132
133
		if ( ! $item->get_id() || ! $item_object || $item_object->post_type != 'wpi_item' ) {
134
			$item->last_error = __( 'Invalid item.', 'invoicing' );
135
			$item->set_id( 0 );
136
			return false;
137
		}
138
139
		$item->set_props(
140
			array(
141
				'parent_id'     => $item_object->post_parent,
142
				'date_created'  => 0 < $item_object->post_date ? $item_object->post_date : null,
143
				'date_modified' => 0 < $item_object->post_modified ? $item_object->post_modified : null,
144
				'status'        => $item_object->post_status,
145
				'name'          => $item_object->post_title,
146
				'description'   => $item_object->post_excerpt,
147
				'author'        => $item_object->post_author,
148
			)
149
		);
150
151
		$this->read_object_data( $item, $item_object );
0 ignored issues
show
It seems like $item_object can also be of type array; however, parameter $post_object of GetPaid_Data_Store_WP::read_object_data() does only seem to accept WP_Post, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

151
		$this->read_object_data( $item, /** @scrutinizer ignore-type */ $item_object );
Loading history...
152
		$item->read_meta_data();
153
		$item->set_object_read( true );
154
		do_action( 'getpaid_read_item', $item );
155
156
	}
157
158
	/**
159
	 * Method to update an item in the database.
160
	 *
161
	 * @param WPInv_Item $item Item object.
162
	 */
163
	public function update( &$item ) {
164
		$item->save_meta_data();
165
		$item->set_version( WPINV_VERSION );
166
167
		if ( null === $item->get_date_created( 'edit' ) ) {
0 ignored issues
show
The condition null === $item->get_date_created('edit') is always false.
Loading history...
168
			$item->set_date_created( current_time( 'mysql' ) );
169
		}
170
171
		// Grab the current status so we can compare.
172
		$previous_status = get_post_status( $item->get_id() );
173
174
		$changes = $item->get_changes();
175
176
		// Only update the post when the post data changes.
177
		if ( array_intersect( array( 'date_created', 'date_modified', 'status', 'parent_id', 'description', 'name', 'author' ), array_keys( $changes ) ) ) {
178
			$post_data = array(
179
				'post_date'     => $item->get_date_created( 'edit' ),
180
				'post_status'   => $item->get_status( 'edit' ),
181
				'post_parent'   => $item->get_parent_id( 'edit' ),
182
				'post_excerpt'  => $item->get_description( 'edit' ),
183
				'post_modified' => $item->get_date_modified( 'edit' ),
184
				'post_title'    => $item->get_name( 'edit' ),
185
				'post_author'   => $item->get_author( 'edit' ),
186
			);
187
188
			/**
189
			 * When updating this object, to prevent infinite loops, use $wpdb
190
			 * to update data, since wp_update_post spawns more calls to the
191
			 * save_post action.
192
			 *
193
			 * This ensures hooks are fired by either WP itself (admin screen save),
194
			 * or an update purely from CRUD.
195
			 */
196
			if ( doing_action( 'save_post' ) ) {
197
				$GLOBALS['wpdb']->update( $GLOBALS['wpdb']->posts, $post_data, array( 'ID' => $item->get_id() ) );
198
				clean_post_cache( $item->get_id() );
199
			} else {
200
				wp_update_post( array_merge( array( 'ID' => $item->get_id() ), $post_data ) );
201
			}
202
			$item->read_meta_data( true ); // Refresh internal meta data, in case things were hooked into `save_post` or another WP hook.
203
		}
204
		$this->update_post_meta( $item );
205
		$item->apply_changes();
206
		$this->clear_caches( $item );
207
208
		// Fire a hook depending on the status - this should be considered a creation if it was previously draft status.
209
		$new_status = $item->get_status( 'edit' );
210
211
		if ( $new_status !== $previous_status && in_array( $previous_status, array( 'new', 'auto-draft', 'draft' ), true ) ) {
212
			do_action( 'getpaid_new_item', $item );
213
		} else {
214
			do_action( 'getpaid_update_item', $item );
215
		}
216
217
	}
218
219
	/*
220
	|--------------------------------------------------------------------------
221
	| Additional Methods
222
	|--------------------------------------------------------------------------
223
	*/
224
225
	/**
226
	 * Helper method that updates all the post meta for an item based on it's settings in the WPInv_Item class.
227
	 *
228
	 * @param WPInv_Item $item WPInv_Item object.
229
	 * @since 1.0.19
230
	 */
231
	protected function update_post_meta( &$item ) {
232
233
		// Ensure that we have a custom id.
234
        if ( ! $item->get_custom_id() ) {
235
            $item->set_custom_id( $item->get_id() );
236
		}
237
238
		parent::update_post_meta( $item );
239
	}
240
241
}
242