Issues (4296)

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-give-background-updater.php (33 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
 * Background Updater
4
 *
5
 * Uses https://github.com/A5hleyRich/wp-background-processing to handle DB
6
 * updates in the background.
7
 *
8
 * @class    Give_Background_Updater
9
 * @version  2.0.0
10
 * @package  Give/Classes
11
 * @category Class
12
 * @author   WordImpress
13
 */
14
if ( ! defined( 'ABSPATH' ) ) {
15
	exit;
16
}
17
18
/**
19
 * Give_Background_Updater Class.
20
 */
21
class Give_Background_Updater extends WP_Background_Process {
22
23
	/**
24
	 * @var string
25
	 */
26
	protected $action = 'give_db_updater';
27
28
	/**
29
	 * Dispatch updater.
30
	 *
31
	 * Updater will still run via cron job if this fails for any reason.
32
	 */
33
	public function dispatch() {
34
		if ( give_test_ajax_works() ) {
35
			parent::dispatch();
36
		} elseif ( wp_doing_ajax() ) {
37
			$this->maybe_handle();
38
		}
39
	}
40
41
42
	/**
43
	 * Get all batches.
44
	 *
45
	 * @since  2.0
46
	 * @access public
47
	 * @return stdClass
48
	 */
49
	public function get_all_batch() {
50
		return parent::get_batch();
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (get_batch() instead of get_all_batch()). Are you sure this is correct? If so, you might want to change this to $this->get_batch().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
51
	}
52
53
	/**
54
	 * Is queue empty
55
	 *
56
	 * @since 2.0.3
57
	 *
58
	 * @return bool
59
	 */
60
	public function has_queue() {
61
		return ( ! parent::is_queue_empty() );
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (is_queue_empty() instead of has_queue()). Are you sure this is correct? If so, you might want to change this to $this->is_queue_empty().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
62
	}
63
64
65
	/**
66
	 * Lock process
67
	 *
68
	 * Lock the process so that multiple instances can't run simultaneously.
69
	 * Override if applicable, but the duration should be greater than that
70
	 * defined in the time_exceeded() method.
71
	 *
72
	 *
73
	 * @since 2.0.3
74
	 */
75
	protected function lock_process() {
76
		// Check if admin want to pause upgrade.
77
		if( get_option('give_pause_upgrade') ) {
0 ignored issues
show
Space after opening control structure is required
Loading history...
No space before opening parenthesis is prohibited
Loading history...
Expected 1 spaces after opening bracket; 0 found
Loading history...
Expected 1 spaces before closing bracket; 0 found
Loading history...
78
			self::flush_cache();
79
80
			delete_option( 'give_paused_batches' );
81
82
			Give_Updates::get_instance()->__pause_db_update( true );
83
84
			delete_option('give_pause_upgrade');
0 ignored issues
show
Expected 1 spaces after opening bracket; 0 found
Loading history...
Expected 1 spaces before closing bracket; 0 found
Loading history...
85
86
			/**
87
			 * Fire action when pause db updates
88
			 *
89
			 * @since 2.0.1
90
			 */
91
			do_action( 'give_pause_db_upgrade', Give_Updates::get_instance() );
92
93
			wp_die();
94
		}
95
0 ignored issues
show
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
96
97
		$this->start_time = time(); // Set start time of current process.
98
99
		$lock_duration = ( property_exists( $this, 'queue_lock_time' ) ) ? $this->queue_lock_time : 60; // 1 minute
100
		$lock_duration = apply_filters( $this->identifier . '_queue_lock_time', $lock_duration );
101
102
		set_site_transient( $this->identifier . '_process_lock', microtime(), $lock_duration );
103
	}
104
105
	/**
106
	 * Handle cron healthcheck
107
	 *
108
	 * Restart the background process if not already running
109
	 * and data exists in the queue.
110
	 */
111
	public function handle_cron_healthcheck() {
112
		if ( $this->is_process_running() || $this->is_paused_process()  ) {
113
			// Background process already running.
114
			return;
115
		}
116
117
		if ( $this->is_queue_empty() ) {
118
			// No data to process.
119
			$this->clear_scheduled_event();
120
121
			return;
122
		}
123
124
		$this->handle();
125
	}
126
127
	/**
128
	 * Schedule fallback event.
129
	 */
130
	protected function schedule_event() {
131
		if ( ! wp_next_scheduled( $this->cron_hook_identifier ) && ! $this->is_paused_process() ) {
132
			wp_schedule_event( time() + 10, $this->cron_interval_identifier, $this->cron_hook_identifier );
133
		}
134
	}
135
136
	/**
137
	 * Task
138
	 *
139
	 * Override this method to perform any actions required on each
140
	 * queue item. Return the modified item for further processing
141
	 * in the next pass through. Or, return false to remove the
142
	 * item from the queue.
143
	 *
144
	 * @param array $update Update info
145
	 *
146
	 * @return mixed
147
	 */
148
	protected function task( $update ) {
149
		// Pause upgrade immediately if admin pausing upgrades.
150
		if( $this->is_paused_process() ) {
0 ignored issues
show
Space after opening control structure is required
Loading history...
No space before opening parenthesis is prohibited
Loading history...
151
			wp_die();
152
		}
153
154
		if ( empty( $update ) ) {
155
			return false;
156
		}
157
158
		// Delete cache.
159
		self::flush_cache();
160
161
		/* @var  Give_Updates $give_updates */
162
		$give_updates  = Give_Updates::get_instance();
163
		$resume_update = get_option(
164
			'give_doing_upgrade',
165
0 ignored issues
show
There should be no empty lines in a multi-line function call.
Loading history...
166
			// Default update.
167
			array(
168
				'update_info'      => $update,
169
				'step'             => 1,
170
				'update'           => 1,
171
				'heading'          => sprintf( 'Update %s of {update_count}', 1 ),
172
				'percentage'       => $give_updates->percentage,
173
				'total_percentage' => 0,
174
			)
175
		);
176
177
		// Continuously skip update if previous update does not complete yet.
178
		if (
179
			$resume_update['update_info']['id'] !== $update['id'] &&
180
			! give_has_upgrade_completed( $resume_update['update_info']['id'] )
181
		) {
182
			return $update;
183
		}
184
185
		// Set params.
186
		$resume_update['update_info'] = $update;
187
		$give_updates->step           = absint( $resume_update['step'] );
188
		$give_updates->update         = absint( $resume_update['update'] );
189
		$is_parent_update_completed   = $give_updates->is_parent_updates_completed( $update );
190
0 ignored issues
show
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
191
192
		// Skip update if dependency update does not complete yet.
193
		if ( empty( $is_parent_update_completed ) ) {
194
			// @todo: set error when you have only one update with invalid dependency
195
			if ( ! is_null( $is_parent_update_completed ) ) {
196
				return $update;
197
			}
198
199
			return false;
200
		}
201
0 ignored issues
show
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
202
203
		// Pause upgrade immediately if found following:
204
		// 1. Running update number greater then total update count
205
		// 2. Processing percentage greater then 100%
206
		if( (
0 ignored issues
show
Space after opening control structure is required
Loading history...
No space before opening parenthesis is prohibited
Loading history...
207
			101 < $resume_update['total_percentage'] ) ||
208
		    ( $give_updates->get_total_db_update_count() < $resume_update['update'] ) ||
209
		    ! in_array( $resume_update['update_info']['id'], $give_updates->get_update_ids() )
210
		) {
211
			if( ! $this->is_paused_process() ){
0 ignored issues
show
Space after opening control structure is required
Loading history...
No space before opening parenthesis is prohibited
Loading history...
212
				$give_updates->__pause_db_update(true);
0 ignored issues
show
Expected 1 spaces after opening bracket; 0 found
Loading history...
Expected 1 spaces before closing bracket; 0 found
Loading history...
213
			}
214
215
			update_option( 'give_upgrade_error', 1, false );
216
217
			$log_data = 'Update Task' . "\n";
218
			$log_data .= "Total update count: {$give_updates->get_total_db_update_count()}\n";
219
			$log_data .= 'Update IDs: ' . print_r( $give_updates->get_update_ids() , true );
0 ignored issues
show
The use of function print_r() is discouraged
Loading history...
220
			$log_data .= 'Update: ' . print_r( $resume_update , true );
0 ignored issues
show
The use of function print_r() is discouraged
Loading history...
221
222
			Give()->logs->add( 'Update Error', $log_data, 0, 'update' );
223
224
			wp_die();
225
		}
226
227
		// Disable cache.
228
		Give_Cache::disable();
229
230
		try{
231
			// Run update.
232
			if ( is_array( $update['callback'] ) ) {
233
				$update['callback'][0]->$update['callback'][1]();
234
			} else {
235
				$update['callback']();
236
			}
237
		} catch ( Exception $e ){
238
239
			if( ! $this->is_paused_process() ){
0 ignored issues
show
Space after opening control structure is required
Loading history...
No space before opening parenthesis is prohibited
Loading history...
240
				$give_updates->__pause_db_update(true);
0 ignored issues
show
Expected 1 spaces after opening bracket; 0 found
Loading history...
Expected 1 spaces before closing bracket; 0 found
Loading history...
241
			}
242
243
			$log_data = 'Update Task' . "\n";
244
			$log_data .= print_r( $resume_update, true ) . "\n\n";
0 ignored issues
show
The use of function print_r() is discouraged
Loading history...
245
			$log_data .= "Error\n {$e->getMessage()}";
246
247
			Give()->logs->add( 'Update Error', $log_data, 0, 'update' );
248
			update_option( 'give_upgrade_error', 1, false );
249
250
			wp_die();
251
		}
252
253
		// Set update info.
254
		$doing_upgrade_args = array(
255
			'update_info'      => $update,
256
			'step'             => ++ $give_updates->step,
257
			'update'           => $give_updates->update,
258
			'heading'          => sprintf( 'Update %s of %s', $give_updates->update, get_option( 'give_db_update_count' ) ),
259
			'percentage'       => $give_updates->percentage,
260
			'total_percentage' => $give_updates->get_db_update_processing_percentage(),
261
		);
262
263
		// Cache upgrade.
264
		update_option( 'give_doing_upgrade', $doing_upgrade_args, false );
265
266
		// Enable cache.
267
		Give_Cache::enable();
268
269
		// Check if current update completed or not.
270
		if ( give_has_upgrade_completed( $update['id'] ) ) {
271
			return false;
272
		}
273
274
		return $update;
275
	}
276
277
	/**
278
	 * Complete
279
	 *
280
	 * Override if applicable, but ensure that the below actions are
281
	 * performed, or, call parent::complete().
282
	 */
283
	public function complete() {
284
		if ( $this->is_paused_process() ) {
285
			return false;
286
		}
287
288
		parent::complete();
289
290
		delete_option( 'give_pause_upgrade' );
291
		delete_option( 'give_upgrade_error' );
292
		delete_option( 'give_db_update_count' );
293
		delete_option( 'give_doing_upgrade' );
294
		add_option( 'give_show_db_upgrade_complete_notice', 1, '', false );
295
296
		// Flush cache.
297
		Give_Cache::flush_cache( true );
298
299
		if ( $cache_keys = Give_Cache::get_options_like( '' ) ) {
300
			Give_Cache::delete( $cache_keys );
301
		}
302
	}
303
304
	/**
305
	 * Get memory limit
306
	 *
307
	 * @return int
308
	 */
309
	protected function get_memory_limit() {
310
		if ( function_exists( 'ini_get' ) ) {
311
			$memory_limit = ini_get( 'memory_limit' );
312
		} else {
313
			// Sensible default.
314
			$memory_limit = '128M';
315
		}
316
317
		if ( ! $memory_limit || '-1' === $memory_limit ) {
318
			// Unlimited, set to 32GB.
319
			$memory_limit = '32000M';
320
		}
321
322
		return intval( $memory_limit ) * 1024 * 1024;
323
	}
324
325
	/**
326
	 * Maybe process queue
327
	 *
328
	 * Checks whether data exists within the queue and that
329
	 * the process is not already running.
330
	 */
331
	public function maybe_handle() {
332
		// Don't lock up other requests while processing
333
		session_write_close();
0 ignored issues
show
The use of PHP session function session_write_close() is prohibited.
Loading history...
334
335
		if ( $this->is_process_running() || $this->is_paused_process() ) {
336
			// Background process already running.
337
			wp_die();
338
		}
339
340
		if ( $this->is_queue_empty() ) {
341
			// No data to process.
342
			wp_die();
343
		}
344
345
		check_ajax_referer( $this->identifier, 'nonce' );
346
347
		$this->handle();
348
349
		wp_die();
350
	}
351
352
	/**
353
	 * Handle
354
	 *
355
	 * Pass each queue item to the task handler, while remaining
356
	 * within server memory and time limit constraints.
357
	 */
358
	protected function handle() {
359
		$this->lock_process();
360
361
		do {
362
			$batch = $this->get_batch();
363
364
			foreach ( $batch->data as $key => $value ) {
365
				$task = $this->task( $value );
366
367
				if ( false !== $task ) {
368
					$batch->data[ $key ] = $task;
369
				} else {
370
					unset( $batch->data[ $key ] );
371
				}
372
373
				if ( $this->time_exceeded() || $this->memory_exceeded() ) {
374
					// Batch limits reached.
375
					break;
376
				}
377
			}
378
379
			// Update or delete current batch.
380
			if ( ! empty( $batch->data ) ) {
381
				$this->update( $batch->key, $batch->data );
382
			} else {
383
				$this->delete( $batch->key );
384
			}
385
		} while ( ! $this->time_exceeded() && ! $this->memory_exceeded() && ! $this->is_queue_empty() );
386
387
		$this->unlock_process();
388
389
		// Start next batch or complete process.
390
		if ( ! $this->is_queue_empty() ) {
391
392
			// Dispatch only if ajax works.
393
			if( give_test_ajax_works() ) {
0 ignored issues
show
Space after opening control structure is required
Loading history...
No space before opening parenthesis is prohibited
Loading history...
394
				$this->dispatch();
395
			}
396
		} else {
397
			$this->complete();
398
		}
399
400
		wp_die();
401
	}
402
403
404
	/**
405
	 * Check if backgound upgrade paused or not.
406
	 *
407
	 * @since 2.0
408
	 * @access public
409
	 * @return bool
410
	 */
411
	public function is_paused_process(){
412
		// Delete cache.
413
		wp_cache_delete( 'give_paused_batches', 'options' );
414
415
		$paused_batches = get_option('give_paused_batches');
0 ignored issues
show
Expected 1 spaces after opening bracket; 0 found
Loading history...
Expected 1 spaces before closing bracket; 0 found
Loading history...
416
417
		return ! empty( $paused_batches );
418
	}
419
420
421
	/**
422
	 * Get identifier
423
	 *
424
	 * @since  2.0
425
	 * @access public
426
	 * @return mixed|string
427
	 */
428
	public function get_identifier() {
429
		return $this->identifier;
430
	}
431
432
	/**
433
	 * Get cron identifier
434
	 *
435
	 * @since  2.0
436
	 * @access public
437
	 * @return mixed|string
438
	 */
439
	public function get_cron_identifier() {
440
		return $this->cron_hook_identifier;
441
	}
442
443
444
	/**
445
	 * Flush background update related cache to prevent task to go to stalled state.
446
	 *
447
	 * @since 2.0.3
448
	 */
449
	public static function flush_cache() {
450
451
		$options = array(
452
			'give_completed_upgrades',
453
			'give_doing_upgrade',
454
			'give_paused_batches',
455
			'give_upgrade_error',
456
			'give_db_update_count',
457
			'give_doing_upgrade',
458
			'give_pause_upgrade',
459
			'give_show_db_upgrade_complete_notice',
460
		);
461
0 ignored issues
show
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
462
463
		foreach ( $options as $option ) {
464
			wp_cache_delete( $option, 'options' );
465
		}
466
	}
467
}
468