Issues (234)

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/feeds/admin/google-admin.php (10 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
 * Google Calendar - Admin
4
 *
5
 * @package    SimpleCalendar/Feeds
6
 */
7
namespace SimpleCalendar\Feeds\Admin;
8
9
use SimpleCalendar\Admin\Metaboxes\Settings;
10
use SimpleCalendar\Admin\Notice;
11
use SimpleCalendar\Feeds\Google;
12
13
if ( ! defined( 'ABSPATH' ) ) {
14
	exit;
15
}
16
17
/**
18
 * Google Calendar feed admin.
19
 *
20
 * @since 3.0.0
21
 */
22
class Google_Admin {
23
24
	/**
25
	 * Google calendar feed object.
26
	 *
27
	 * @access private
28
	 * @var Google
29
	 */
30
	private $feed = null;
31
32
	/**
33
	 * Google Api Key.
34
	 *
35
	 * @access private
36
	 * @var string
37
	 */
38
	private $google_api_key = '';
39
40
	/**
41
	 * Google Calendar id.
42
	 *
43
	 * @access private
44
	 * @var string
45
	 */
46
	private $google_calendar_id = '';
47
48
	/**
49
	 * Hook in tabs.
50
	 *
51
	 * @since 3.0.0
52
	 *
53
	 * @param Google $feed
54
	 * @param string $google_api_key
55
	 * @param string $google_calendar_id
56
	 */
57
	public function __construct( Google $feed, $google_api_key, $google_calendar_id ) {
58
59
		$this->feed = $feed;
60
		$this->google_api_key = $google_api_key;
61
		$this->google_calendar_id = $google_calendar_id;
62
63
		$screen = simcal_is_admin_screen();
64
65 View Code Duplication
		if ( 'calendar' == $screen ) {
0 ignored issues
show
This code seems to be duplicated across 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...
66
			$this->test_api_key_connection( $this->google_calendar_id );
67
			add_filter( 'simcal_settings_meta_tabs_li', array( $this, 'add_settings_meta_tab_li' ), 10, 1 );
68
			add_action( 'simcal_settings_meta_panels', array( $this, 'add_settings_meta_panel' ), 10, 1 );
69
		}
70
71
		add_action( 'simcal_process_settings_meta', array( $this, 'process_meta' ), 10, 1 );
72
	}
73
74
	/**
75
	 * Feed settings page fields.
76
	 *
77
	 * @since  3.0.0
78
	 *
79
	 * @return array
80
	 */
81
	public function settings_fields() {
82
		return array(
83
			'name' => $this->feed->name,
84
			'description' => __( "To read events from your public Google Calendars you'll need create a Google API key and save it here.", 'google-calendar-events' ) .
85
			                 '<br/><br/>' .
86
			                 '<em style="font-size: 14px;">' .
87
			                 sprintf( __( '<strong>Note:</strong> Calendars configured to use the <strong><a href="%s" target="_blank">Google Calendar Pro add-on</a></strong> use a different method of authorization.', 'google-calendar-events' ),
88
				                 simcal_ga_campaign_url( simcal_get_url( 'addons' ), 'core-plugin', 'settings-link' )
89
			                 ) .
90
			                 '</em>',
91
			'fields' => array(
92
				'api_key' => array(
93
					'type'       => 'standard',
94
					'subtype'    => 'text',
95
					'class'      => array( 'simcal-wide-text regular-text', 'ltr' ),
96
					'title'      => __( 'Google API Key', 'google-calendar-events' ),
97
					'validation' => array( $this, 'check_google_api_key' ),
98
				),
99
			),
100
		);
101
	}
102
103
	/**
104
	 * Check if there's a Google API Key or a legacy key is being used.
105
	 *
106
	 * This method only checks if the api key setting is not empty.
107
	 * It is not currently possible to check or validate an API Key without performing a full request.
108
	 * On the settings page there are no known calendars to use for this so we can only check if there is a string.
109
	 *
110
	 * @since  3.0.0
111
	 *
112
	 * @param  string $api_key Google API key.
113
	 *
114
	 * @return true|string
115
	 */
116
	public function check_google_api_key( $api_key = '' ) {
117
118
		$message    = '';
0 ignored issues
show
$message is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
119
		$has_errors = false;
0 ignored issues
show
$has_errors is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
120
121
		if ( empty( $api_key ) ){
122
			$api_key = $this->google_api_key;
123
			if ( empty( $api_key ) ) {
124
				$settings = get_option( 'simple-calendar_settings_feeds' );
125
				$api_key = isset( $settings['google']['api_key'] ) ? esc_attr( $settings['google']['api_key'] ) : '';
0 ignored issues
show
$api_key is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
126
			}
127
		}
128
129
		$message = '<p class="description">' .
130
				   sprintf( __( '<a href="%s" target="_blank">Step-by-step instructions</a> ', 'google-calendar-events' ),
131
					   simcal_ga_campaign_url( simcal_get_url( 'docs' ) . '/google-api-key/', 'core-plugin', 'settings-link' )
132
				   ) .
133
				   '<br/>' .
134
				   sprintf( __( '<a href="%s" target="_blank">Google Developers Console</a> ', 'google-calendar-events' ),
135
					   simcal_get_url( 'gdev-console' )
136
				   ) .
137
				   '</p>';
138
139
		return $message;
140
	}
141
142
	/**
143
	 * Add a tab to the settings meta box.
144
	 *
145
	 * @since  3.0.0
146
	 *
147
	 * @param  array $tabs
148
	 *
149
	 * @return array
150
	 */
151
	public function add_settings_meta_tab_li( $tabs ) {
152
		return array_merge( $tabs, array(
153
			'google' => array(
154
				'label'   => $this->feed->name,
155
				'target'  => 'google-settings-panel',
156
				'class'   => array( 'simcal-feed-type', 'simcal-feed-type-google' ),
157
				'icon'    => 'simcal-icon-google',
158
			),
159
		) );
160
	}
161
162
	/**
163
	 * Add a panel to the settings meta box.
164
	 *
165
	 * @since 3.0.0
166
	 *
167
	 * @param int $post_id
168
	 */
169
	public function add_settings_meta_panel( $post_id ) {
170
171
		$inputs = array(
172
			$this->feed->type => array(
173
				'_google_calendar_id' => array(
174
					'type'        => 'standard',
175
					'subtype'     => 'text',
176
					'name'        => '_google_calendar_id',
177
					'id'          => '_google_calendar_id',
178
					'title'       => __( 'Calendar ID', 'google-calendar-events' ),
179
					'tooltip'     => __( 'Visit your Google Calendar account, copy your public calendar ID, then paste it here.', 'google-calendar-events' ),
180
					'placeholder' => __( 'Enter a valid Google Calendar ID from a public calendar', 'google-calendar-events' ),
181
					'escaping'    => array( $this->feed, 'esc_google_calendar_id' ),
182
					'validation'  => array( $this, 'test_api_key_connection' ),
183
				),
184
				'_google_events_search_query' => array(
185
					'type'        => 'standard',
186
					'subtype'     => 'text',
187
					'name'        => '_google_events_search_query',
188
					'id'          => '_google_events_search_query',
189
					'title'       => __( 'Search Query', 'google-calendar-events' ),
190
					'tooltip'     => __( 'Type in keywords if you only want display events that match these terms. You can use basic boolean search operators too.', 'google-calendar-events' ),
191
					'placeholder' => __( 'Filter events to display by search terms...', 'google-calendar-events' ),
192
				),
193
				'_google_events_recurring' => array(
194
					'type'    => 'select',
195
					'name'    => '_google_events_recurring',
196
					'id'      => '_google_events_recurring',
197
					'title'   => __( 'Recurring Events', 'google-calendar-events' ),
198
					'tooltip' => __( 'Events that are programmed to repeat themselves periodically.', 'google-calendar-events' ),
199
					'options' => array(
200
						'show' => __( 'Show all', 'google-calendar-events' ),
201
						'first-only' => __( 'Only show first occurrence', 'google-calendar-events' ),
202
					),
203
				),
204
				'_google_events_max_results' => array(
205
					'type'        => 'standard',
206
					'subtype'     => 'number',
207
					'name'        => '_google_events_max_results',
208
					'id'          => '_google_events_max_results',
209
					'title'       => __( 'Maximum Events', 'google-calendar-events' ),
210
					'tooltip'     => __( 'Google Calendar only allows to query for a maximum amount of 2500 events from a calendar each time.', 'google-calendar-events' ),
211
					'class'       => array(
212
						'simcal-field-small',
213
					),
214
					'default'     => '2500',
215
					'attributes' => array(
216
						'min'  => '0',
217
						'max'  => '2500',
218
					),
219
				),
220
			),
221
		);
222
223
		?>
224
		<div id="google-settings-panel" class="simcal-panel">
225
			<table>
226
				<thead>
227
					<tr><th colspan="2"><?php _e( 'Google Calendar Settings', 'google-calendar-events' ); ?></th></tr>
228
				</thead>
229
				<?php Settings::print_panel_fields( $inputs, $post_id ); ?>
230
			</table>
231
		</div>
232
		<?php
233
234
	}
235
236
	/**
237
	 * Test a connection to Google Calendar API.
238
	 *
239
	 * @since  3.0.0
240
	 *
241
	 * @param  string $google_calendar_id
242
	 *
243
	 * @return true|string
244
	 */
245
	public function test_api_key_connection( $google_calendar_id ) {
246
247
		global $post;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
248
249
		$post_id = isset( $post->ID ) ? $post->ID : 0;
250
		$feed = null;
251
		if ( $feed_type = wp_get_object_terms( $post_id, 'calendar_feed' ) ) {
252
			$feed = sanitize_title( current( $feed_type )->name );
253
		}
254
255
		$message = '';
256
		$error = '';
257
		$has_errors = false;
0 ignored issues
show
$has_errors is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
258
259
		$message .= '<p class="description">' .
260
					sprintf(
261
						__( 'Step 1: Set the Google Calendar you want to use as <strong>"public."</strong> <a href="%1s" target="_blank">Detailed instructions</a>', 'google-calendar-events' ) . '<br />' .
262
						__( 'Step 2: Copy and paste your Google Calendar ID here. <a href="%2s" target="_blank">Detailed instructions</a>', 'google-calendar-events' ),
263
						simcal_ga_campaign_url( simcal_get_url( 'docs' ) . '/make-google-calendar-public/', 'core-plugin', 'settings-link' ),
264
						simcal_ga_campaign_url( simcal_get_url( 'docs' ) . '/find-google-calendar-id/', 'core-plugin', 'settings-link' )
265
					) . '</p>';
266
267
		if ( $post_id > 0 && ! is_null( $feed ) && ! empty( $this->feed->type ) ) {
268
269
			$no_key_notice = new Notice( array(
270
					'id'          => array( 'calendar_' . $post_id => 'google-no-api-key' ),
271
					'type'        => 'error',
272
					'screen'      => 'calendar',
273
					'post'        => $post_id,
274
					'dismissable' => false,
275
					'content'     => '<p>' .
276
					                 '<i class="simcal-icon-warning"></i> ' .
277
					                 sprintf(
278
						                 __( 'Your Google Calendar events will not show up until you <a href="%s">create and save a Google API key</a>.', 'google-calendar-events' ),
279
						                 admin_url( 'edit.php?post_type=calendar&page=simple-calendar_settings&tab=feeds' )
280
					                 ) .
281
					                 '</p>',
282
				)
283
			);
284
285
			if ( empty( $this->google_api_key ) && ( $feed == $this->feed->type ) ) {
286
287
				$has_errors = true;
0 ignored issues
show
$has_errors is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
288
				$no_key_notice->add();
289
290
			} else {
291
292
				$no_key_notice->remove();
293
294
				try {
295
					$this->feed->make_request( $google_calendar_id );
296
				} catch ( \Exception $e ) {
297
					$error   = $e->getMessage();
298
					$message = ! empty( $error ) ? '<blockquote>' . $error . '</blockquote>' : '';
299
				}
300
301
				$error_notice = new Notice( array(
302
						'id'          => array( 'calendar_' . $post_id => 'google-error-response' ),
303
						'type'        => 'error',
304
						'screen'      => 'calendar',
305
						'post'        => $post_id,
306
						'dismissable' => false,
307
						'content'     => '<p>' .
308
						                 '<i class="simcal-icon-warning"></i> ' .
309
						                 __( 'While trying to retrieve events, Google returned an error:', 'google-calendar-events' ) .
310
						                 '<br>' . $message . '<br>' .
311
						                 __( 'Please ensure that both your Google Calendar ID and API Key are valid and that the Google Calendar you want to display is public.', 'google-calendar-events' ) .
312
						                 '</p>',
313
					)
314
				);
315
316
				if ( ! empty( $error ) && ( $feed == $this->feed->type ) ) {
317
					$error_notice->add();
318
					$has_errors = true;
0 ignored issues
show
$has_errors is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
319
				} else {
320
					$error_notice->remove();
321
					$has_errors = false;
0 ignored issues
show
$has_errors is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
322
				}
323
324
			}
325
326
		}
327
328
		return $message;
329
	}
330
331
	/**
332
	 * Process meta fields.
333
	 *
334
	 * @since 3.0.0
335
	 *
336
	 * @param int $post_id
337
	 */
338
	public function process_meta( $post_id ) {
0 ignored issues
show
process_meta uses the super-global variable $_POST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
339
340
		$calendar_id = isset( $_POST['_google_calendar_id'] ) ? base64_encode( trim( $_POST['_google_calendar_id'] ) ): '';
341
		update_post_meta( $post_id, '_google_calendar_id', $calendar_id );
342
343
		$search_query = isset( $_POST['_google_events_search_query'] ) ? sanitize_text_field( $_POST['_google_events_search_query'] ) : '';
344
		update_post_meta( $post_id, '_google_events_search_query', $search_query );
345
346
		$recurring = isset( $_POST['_google_events_recurring'] ) ? sanitize_key( $_POST['_google_events_recurring'] ) : 'show';
347
		update_post_meta( $post_id, '_google_events_recurring', $recurring );
348
349
		$max_results = isset( $_POST['_google_events_max_results'] ) ? absint( $_POST['_google_events_max_results'] ) : '2500';
350
		update_post_meta( $post_id, '_google_events_max_results', $max_results );
351
352
		$this->test_api_key_connection( $calendar_id );
353
	}
354
355
}
356