Issues (1282)

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/database/class-give-db-logs.php (4 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
 * Donors DB
4
 *
5
 * @package     Give
6
 * @subpackage  Classes/Give_DB_Logs
7
 * @copyright   Copyright (c) 2016, GiveWP
8
 * @license     https://opensource.org/licenses/gpl-license GNU Public License
9
 * @since       2.0
10
 */
11
12
// Exit if accessed directly.
13
if ( ! defined( 'ABSPATH' ) ) {
14
	exit;
15
}
16
17
/**
18
 * Give_DB_Logs Class
19
 *
20
 * This class is for interacting with the log database table.
21
 *
22
 * @since 2.0
23
 */
24
class Give_DB_Logs extends Give_DB {
25
26
	/**
27
	 * Give_DB_Logs constructor.
28
	 *
29
	 * Set up the Give DB Donor class.
30
	 *
31
	 * @since  2.0
32
	 * @access public
33
	 */
34
	public function __construct() {
35
		/* @var WPDB $wpdb */
36
		global $wpdb;
37
38
		$this->table_name  = $wpdb->prefix . 'give_logs';
39
		$this->primary_key = 'ID';
40
		$this->version     = '1.0';
41
42
		parent::__construct();
43
	}
44
45
	/**
46
	 * Get columns and formats
47
	 *
48
	 * @since  2.0
49
	 * @access public
50
	 *
51
	 * @return array  Columns and formats.
52
	 */
53
	public function get_columns() {
54
		return array(
55
			'ID'           => '%d',
56
			'log_title'    => '%s',
57
			'log_content'  => '%s',
58
			'log_parent'   => '%d',
59
			'log_type'     => '%s',
60
			'log_date'     => '%s',
61
			'log_date_gmt' => '%s',
62
		);
63
	}
64
65
	/**
66
	 * Get default column values
67
	 *
68
	 * @since  2.0
69
	 * @access public
70
	 *
71
	 * @return array  Default column values.
72
	 */
73
	public function get_column_defaults() {
74
		$log_create_date     = current_time( 'mysql', 0 );
75
		$log_create_date_gmt = get_gmt_from_date( $log_create_date );
76
77
		return array(
78
			'ID'           => 0,
79
			'log_title'    => '',
80
			'log_content'  => '',
81
			'log_parent'   => 0,
82
			'log_type'     => '',
83
			'log_date'     => $log_create_date,
84
			'log_date_gmt' => $log_create_date_gmt,
85
		);
86
	}
87
88
	/**
89
	 * Add a log
90
	 *
91
	 * @since  2.0
92
	 * @access public
93
	 *
94
	 * @param  array $data
95
	 *
96
	 * @return bool|int
97
	 */
98
	public function add( $data = array() ) {
99
		// Valid table columns.
100
		$table_columns = array_keys( $this->get_columns() );
101
102
		// Filter data.
103
		foreach ( $data as $table_column => $column_data ) {
104
			if ( ! in_array( $table_column, $table_columns ) ) {
105
				unset( $data[ $table_column ] );
106
			}
107
		}
108
109
		// Set default values.
110
		$current_log_data = wp_parse_args( $data, $this->get_column_defaults() );
111
112
		// Log parent should be an int.
113
		$current_log_data['log_parent'] = absint( $current_log_data['log_parent'] );
114
115
		// Get log.
116
		$existing_log = $this->get_log_by( $current_log_data['ID'] );
117
118
		// Update an existing log.
119
		if ( $existing_log ) {
120
121
			// Create new log data from existing and new log data.
122
			$current_log_data = array_merge( $current_log_data, $existing_log );
123
124
			// Update log data.
125
			$this->update( $current_log_data['ID'], $current_log_data );
126
127
			$log_id = $current_log_data['ID'];
128
129
		} else {
130
			$log_id = $this->insert( $current_log_data, 'log' );
131
		}
132
133
		return $log_id;
134
	}
135
136
137
	/**
138
	 * Retrieves a single log from the database
139
	 *
140
	 * @since  2.0
141
	 * @access public
142
	 *
143
	 * @param int    $log_id
144
	 * @param string $by
145
	 *
146
	 * @return bool|null|array
147
	 */
148 View Code Duplication
	public function get_log_by( $log_id = 0, $by = 'id' ) {
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...
149
		/* @var WPDB $wpdb */
150
		global $wpdb;
151
		$log = null;
152
153
		// Make sure $log_id is int.
154
		$log_id = absint( $log_id );
155
156
		// Bailout.
157
		if ( empty( $log_id ) ) {
158
			return null;
159
		}
160
161
		switch ( $by ) {
162
			case 'id':
163
				$log = $wpdb->get_row(
164
					$wpdb->prepare(
165
						"SELECT * FROM $this->table_name WHERE ID = %s LIMIT 1",
166
						$log_id
167
					),
168
					ARRAY_A
169
				);
170
				break;
171
172
			default:
173
				$log = apply_filters( "give_get_log_by_{$by}", $log, $log_id );
174
		}
175
176
		return $log;
177
	}
178
179
	/**
180
	 * Retrieve logs from the database.
181
	 *
182
	 * @since  2.0
183
	 * @access public
184
	 *
185
	 * @param  array $args
186
	 *
187
	 * @return mixed
188
	 */
189
	public function get_logs( $args = array() ) {
190
		global $wpdb;
191
		$sql_query = $this->get_sql( $args );
192
193
		// Get log.
194
		if ( ! ( $logs = Give_Cache::get( 'give_logs', true, $sql_query ) ) ) {
195
			$logs = $wpdb->get_results( $sql_query );
196
			Give_Cache::set( 'give_logs', $logs, 3600, true, $sql_query );
197
		}
198
199
		return $logs;
200
	}
201
202
203
	/**
204
	 * Count the total number of logs in the database
205
	 *
206
	 * @since  2.0
207
	 * @access public
208
	 *
209
	 * @param  array $args
210
	 *
211
	 * @return int
212
	 */
213
	public function count( $args = array() ) {
214
		/* @var WPDB $wpdb */
215
		global $wpdb;
216
		$args['number'] = - 1;
217
		$args['fields'] = 'ID';
218
		$args['count']  = true;
219
220
		$sql_query = $this->get_sql( $args );
221
222
		if ( ! ( $count = Give_Cache::get( 'give_logs_count', true, $sql_query ) ) ) {
223
			$count = $wpdb->get_var( $sql_query );
224
			Give_Cache::set( 'give_logs_count', $count, 3600, true, $args );
225
		}
226
227
		return absint( $count );
228
	}
229
230
	/**
231
	 * Create the table
232
	 *
233
	 * @since  2.0
234
	 * @access public
235
	 *
236
	 * @return void
237
	 */
238 View Code Duplication
	public function create_table() {
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...
239
		global $wpdb;
240
		$charset_collate = $wpdb->get_charset_collate();
241
242
		$sql = "CREATE TABLE {$this->table_name} (
243
        ID bigint(20) NOT NULL AUTO_INCREMENT,
244
        log_title longtext NOT NULL,
245
        log_content longtext NOT NULL,
246
      	log_parent bigint(20) NOT NULL,
247
        log_type mediumtext NOT NULL,
248
        log_date datetime NOT NULL,
249
        log_date_gmt datetime NOT NULL,
250
        PRIMARY KEY  (ID)
251
        ) {$charset_collate};";
252
253
		require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
254
		dbDelta( $sql );
255
256
		update_option( $this->table_name . '_db_version', $this->version, false );
257
	}
258
259
260
	/**
261
	 * Get sql query from quaried array.
262
	 *
263
	 * @since  2.0
264
	 * @access public
265
	 *
266
	 * @param array $args
267
	 *
268
	 * @return string
269
	 */
270 View Code Duplication
	public function get_sql( $args = array() ) {
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...
271
		/* @var WPDB $wpdb */
272
		global $wpdb;
273
274
		$defaults = array(
275
			'number'  => 20,
276
			'offset'  => 0,
277
			'paged'   => 0,
278
			'orderby' => 'date',
279
			'order'   => 'DESC',
280
			'fields'  => 'all',
281
			'count'   => false,
282
		);
283
284
		$args = wp_parse_args( $args, $defaults );
285
286
		// validate params.
287
		$this->validate_params( $args );
288
289
		if ( $args['number'] < 1 ) {
290
			$args['number'] = 99999999999;
291
		}
292
293
		// Where clause for primary table.
294
		$where = '';
295
296
		// Get sql query for meta.
297
		if ( ! empty( $args['meta_query'] ) ) {
298
			$meta_query_object = new WP_Meta_Query( $args['meta_query'] );
299
			$meta_query        = $meta_query_object->get_sql( 'log', $this->table_name, 'id' );
300
			$where             = implode( '', $meta_query );
301
		}
302
303
		$where .= ' WHERE 1=1 ';
304
305
		// Set offset.
306
		if ( empty( $args['offset'] ) && ( 0 < $args['paged'] ) ) {
307
			$args['offset'] = $args['number'] * ( $args['paged'] - 1 );
308
		}
309
310
		// Set fields.
311
		$fields = "{$this->table_name}.*";
312
		if ( is_string( $args['fields'] ) && ( 'all' !== $args['fields'] ) ) {
313
			$fields = "{$this->table_name}.{$args['fields']}";
314
		}
315
316
		// Set count.
317
		if ( $args['count'] ) {
318
			$fields = "COUNT({$fields})";
319
		}
320
321
		// Specific logs.
322
		if ( ! empty( $args['ID'] ) ) {
323
324
			if ( ! is_array( $args['ID'] ) ) {
325
				$args['ID'] = explode( ',', $args['ID'] );
326
			}
327
			$log_ids = implode( ',', array_map( 'intval', $args['ID'] ) );
328
329
			$where .= " AND {$this->table_name}.ID IN( {$log_ids} ) ";
330
		}
331
332
		// Logs created for a specific date or in a date range
333
		if ( ! empty( $args['date_query'] ) ) {
334
			$date_query_object = new WP_Date_Query( $args['date_query'], "{$this->table_name}.log_date" );
335
			$where             .= $date_query_object->get_sql();
336
		}
337
338
		// Logs create for specific parent.
339
		if ( ! empty( $args['log_parent'] ) ) {
340
			if ( ! is_array( $args['log_parent'] ) ) {
341
				$args['log_parent'] = explode( ',', $args['log_parent'] );
342
			}
343
			$parent_ids = implode( ',', array_map( 'intval', $args['log_parent'] ) );
344
345
			$where .= " AND {$this->table_name}.log_parent IN( {$parent_ids} ) ";
346
		}
347
348
		// Logs create for specific type.
349
		// is_array check is for backward compatibility.
350
		if ( ! empty( $args['log_type'] ) && ! is_array( $args['log_type'] ) ) {
351
			if ( ! is_array( $args['log_type'] ) ) {
352
				$args['log_type'] = explode( ',', $args['log_type'] );
353
			}
354
355
			$log_types = implode( '\',\'', array_map( 'trim', $args['log_type'] ) );
356
357
			$where .= " AND {$this->table_name}.log_type IN( '{$log_types}' ) ";
358
		}
359
360
		$args['orderby'] = ! array_key_exists( $args['orderby'], $this->get_columns() ) ? 'log_date' : $args['orderby'];
361
362
		$args['orderby'] = esc_sql( $args['orderby'] );
363
		$args['order']   = esc_sql( $args['order'] );
364
365
		return $wpdb->prepare(
366
			"SELECT {$fields} FROM {$this->table_name} {$where} ORDER BY {$this->table_name}.{$args['orderby']} {$args['order']} LIMIT %d,%d;",
367
			absint( $args['offset'] ),
368
			absint( $args['number'] )
369
		);
370
	}
371
372
373
	/**
374
	 * Validate query params.
375
	 *
376
	 * @since  2.0
377
	 * @access private
378
	 *
379
	 * @param $args
380
	 *
381
	 * @return mixed
382
	 */
383 View Code Duplication
	private function validate_params( &$args ) {
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...
384
		// fields params
385
		$args['fields'] = 'ids' === $args['fields'] ?
386
			'ID' :
387
			$args['fields'];
388
		$args['fields'] = array_key_exists( $args['fields'], $this->get_columns() ) ?
389
			$args['fields'] :
390
			'all';
391
	}
392
}
393