Issues (4335)

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   GiveWP
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
				$object      = $update['callback'][0];
234
				$method_name = $update['callback'][1];
235
236
				$object->$method_name();
237
238
			} else {
239
				$update['callback']();
240
			}
241
		} catch ( Exception $e ){
242
243
			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...
244
				$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...
245
			}
246
247
			$log_data = 'Update Task' . "\n";
248
			$log_data .= print_r( $resume_update, true ) . "\n\n";
0 ignored issues
show
The use of function print_r() is discouraged
Loading history...
249
			$log_data .= "Error\n {$e->getMessage()}";
250
251
			Give()->logs->add( 'Update Error', $log_data, 0, 'update' );
252
			update_option( 'give_upgrade_error', 1, false );
253
254
			wp_die();
255
		}
256
257
		// Set update info.
258
		$doing_upgrade_args = array(
259
			'update_info'      => $update,
260
			'step'             => ++ $give_updates->step,
261
			'update'           => $give_updates->update,
262
			'heading'          => sprintf( 'Update %s of %s', $give_updates->update, get_option( 'give_db_update_count' ) ),
263
			'percentage'       => $give_updates->percentage,
264
			'total_percentage' => $give_updates->get_db_update_processing_percentage(),
265
		);
266
267
		// Cache upgrade.
268
		update_option( 'give_doing_upgrade', $doing_upgrade_args, false );
269
270
		// Enable cache.
271
		Give_Cache::enable();
272
273
		// Check if current update completed or not.
274
		if ( give_has_upgrade_completed( $update['id'] ) ) {
275
			return false;
276
		}
277
278
		return $update;
279
	}
280
281
	/**
282
	 * Complete
283
	 *
284
	 * Override if applicable, but ensure that the below actions are
285
	 * performed, or, call parent::complete().
286
	 */
287
	public function complete() {
288
		if ( $this->is_paused_process() ) {
289
			return false;
290
		}
291
292
		parent::complete();
293
294
		delete_option( 'give_pause_upgrade' );
295
		delete_option( 'give_upgrade_error' );
296
		delete_option( 'give_db_update_count' );
297
		delete_option( 'give_doing_upgrade' );
298
		add_option( 'give_show_db_upgrade_complete_notice', 1, '', false );
299
300
		// Flush cache.
301
		Give_Cache::flush_cache( true );
302
303
		if ( $cache_keys = Give_Cache::get_options_like( '' ) ) {
304
			Give_Cache::delete( $cache_keys );
305
		}
306
	}
307
308
	/**
309
	 * Get memory limit
310
	 *
311
	 * @return int
312
	 */
313
	protected function get_memory_limit() {
314
		if ( function_exists( 'ini_get' ) ) {
315
			$memory_limit = ini_get( 'memory_limit' );
316
		} else {
317
			// Sensible default.
318
			$memory_limit = '128M';
319
		}
320
321
		if ( ! $memory_limit || '-1' === $memory_limit ) {
322
			// Unlimited, set to 32GB.
323
			$memory_limit = '32000M';
324
		}
325
326
		return intval( $memory_limit ) * 1024 * 1024;
327
	}
328
329
	/**
330
	 * Maybe process queue
331
	 *
332
	 * Checks whether data exists within the queue and that
333
	 * the process is not already running.
334
	 */
335
	public function maybe_handle() {
336
		// Don't lock up other requests while processing
337
		session_write_close();
0 ignored issues
show
The use of PHP session function session_write_close() is prohibited.
Loading history...
338
339
		if ( $this->is_process_running() || $this->is_paused_process() ) {
340
			// Background process already running.
341
			wp_die();
342
		}
343
344
		if ( $this->is_queue_empty() ) {
345
			// No data to process.
346
			wp_die();
347
		}
348
349
		check_ajax_referer( $this->identifier, 'nonce' );
350
351
		$this->handle();
352
353
		wp_die();
354
	}
355
356
	/**
357
	 * Handle
358
	 *
359
	 * Pass each queue item to the task handler, while remaining
360
	 * within server memory and time limit constraints.
361
	 */
362
	protected function handle() {
363
		$this->lock_process();
364
365
		do {
366
			$batch = $this->get_batch();
367
368
			foreach ( $batch->data as $key => $value ) {
369
				$task = $this->task( $value );
370
371
				if ( false !== $task ) {
372
					$batch->data[ $key ] = $task;
373
				} else {
374
					unset( $batch->data[ $key ] );
375
				}
376
377
				if ( $this->time_exceeded() || $this->memory_exceeded() ) {
378
					// Batch limits reached.
379
					break;
380
				}
381
			}
382
383
			// Update or delete current batch.
384
			if ( ! empty( $batch->data ) ) {
385
				$this->update( $batch->key, $batch->data );
386
			} else {
387
				$this->delete( $batch->key );
388
			}
389
		} while ( ! $this->time_exceeded() && ! $this->memory_exceeded() && ! $this->is_queue_empty() );
390
391
		$this->unlock_process();
392
393
		// Start next batch or complete process.
394
		if ( ! $this->is_queue_empty() ) {
395
396
			// Dispatch only if ajax works.
397
			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...
398
				$this->dispatch();
399
			}
400
		} else {
401
			$this->complete();
402
		}
403
404
		wp_die();
405
	}
406
407
408
	/**
409
	 * Check if backgound upgrade paused or not.
410
	 *
411
	 * @since 2.0
412
	 * @access public
413
	 * @return bool
414
	 */
415
	public function is_paused_process(){
416
		// Delete cache.
417
		wp_cache_delete( 'give_paused_batches', 'options' );
418
419
		$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...
420
421
		return ! empty( $paused_batches );
422
	}
423
424
425
	/**
426
	 * Get identifier
427
	 *
428
	 * @since  2.0
429
	 * @access public
430
	 * @return mixed|string
431
	 */
432
	public function get_identifier() {
433
		return $this->identifier;
434
	}
435
436
	/**
437
	 * Get cron identifier
438
	 *
439
	 * @since  2.0
440
	 * @access public
441
	 * @return mixed|string
442
	 */
443
	public function get_cron_identifier() {
444
		return $this->cron_hook_identifier;
445
	}
446
447
448
	/**
449
	 * Flush background update related cache to prevent task to go to stalled state.
450
	 *
451
	 * @since 2.0.3
452
	 */
453
	public static function flush_cache() {
454
455
		$options = array(
456
			'give_completed_upgrades',
457
			'give_doing_upgrade',
458
			'give_paused_batches',
459
			'give_upgrade_error',
460
			'give_db_update_count',
461
			'give_pause_upgrade',
462
			'give_show_db_upgrade_complete_notice',
463
		);
464
0 ignored issues
show
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
465
466
		foreach ( $options as $option ) {
467
			wp_cache_delete( $option, 'options' );
468
		}
469
	}
470
}
471