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