Issues (8)

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.

src/Admin/SettingsPage.php (2 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
 * WP PHP Console
4
 *
5
 * This source file is subject to the GNU General Public License v3.0
6
 * that is bundled with this package in the file license.txt.
7
 * It is also available through the world-wide-web at this URL:
8
 * http://www.gnu.org/licenses/gpl-3.0.html
9
 *
10
 * @author    Fulvio Notarstefano <[email protected]>
11
 * @copyright Copyright (c) 2014-2020 Fulvio Notarstefano
12
 * @license   http://www.gnu.org/licenses/gpl-3.0.html GNU General Public License v3.0
13
 */
14
15
namespace WP_PHP_Console\Admin;
16
17
use WP_PHP_Console\Plugin;
18
use WP_PHP_Console\Settings;
19
20
defined( 'ABSPATH' ) or exit;
21
22
/**
23
 * WP PHP Console settings page handler.
24
 *
25
 * @since 1.6.0
26
 */
27
class SettingsPage {
28
29
30
	/** @var string the plugin's settings page slug */
31
	private $page_id;
32
33
	/** @var string the plugin's settings option key name */
34
	private $option_key;
35
36
	/** @var array settings options */
37
	private $options;
38
39
40
	/**
41
	 * Registers settings and admin menu.
42
	 *
43
	 * @since 1.6.0
44
	 */
45
	public function __construct() {
46
47
		$this->page_id    = str_replace( '-', '_', Plugin::ID );
48
		$this->option_key = Settings::get_settings_key();
49
		$this->options    = Settings::get_settings();
50
51
		add_action( 'admin_menu', function() { $this->register_settings_page(); } );
52
		add_action( 'admin_init', function() { $this->register_settings(); } );
53
	}
54
55
56
	/**
57
	 * Adds a plugin Settings menu.
58
	 *
59
	 * @since 1.6.0
60
	 */
61
	private function register_settings_page() {
62
63
		add_options_page(
64
			Plugin::NAME,
65
			Plugin::NAME,
66
			'manage_options',
67
			$this->page_id,
68
			[ $this, 'output_settings_page' ]
69
		);
70
	}
71
72
73
	/**
74
	 * Registers the plugin settings.
75
	 *
76
	 * @since 1.6.0
77
	 */
78
	private function register_settings() {
79
80
		register_setting(
81
			$this->option_key,
82
			$this->option_key,
83
			[ $this, 'sanitize_field' ]
84
		);
85
86
		add_settings_section(
87
			$this->option_key,
88
			__( 'Settings', 'wp-php-console' ),
89
			[ $this, 'output_settings_instructions' ],
90
			$this->page_id
91
		);
92
93
		$settings_fields = [
94
			'password' => [
95
				'label' => esc_html__( 'Password', 'wp-php-console' ),
96
				'args'  => [
97
					'id'       => 'password',
98
					'type'     => 'password',
99
					'required' => true,
100
				]
101
			],
102
			'ssl' => [
103
				'label' => esc_html__( 'Allow only on SSL', 'wp-php-console' ),
104
				'args'  => [
105
					'id'   => 'ssl',
106
					'type' => 'checkbox',
107
				]
108
			],
109
			'ip' => [
110
				'label' => esc_html__( 'Allowed IP Masks', 'wp-php-console' ),
111
				'args'  => [
112
					'id'   => 'ip',
113
					'type' => 'text',
114
				]
115
			],
116
			'register' => [
117
				'label' => esc_html__( 'Register PC Class', 'wp-php-console' ),
118
				'args'  => [
119
					'id'   => 'register',
120
					'type' => 'checkbox',
121
				]
122
			],
123
			'stack' => [
124
				'label' => esc_html__( 'Show Call Stack', 'wp-php-console' ),
125
				'args'  => [
126
					'id'   => 'stack',
127
					'type' => 'checkbox',
128
				]
129
			],
130
			'short' => [
131
				'label' => esc_html__( 'Short Path Names', 'wp-php-console' ),
132
				'args'  => [
133
					'id'   => 'short',
134
					'type' => 'checkbox',
135
				]
136
			],
137
		];
138
139
		foreach ( $settings_fields as $key => $field ) {
140
			add_settings_field(
141
				$this->page_id . '['. $key . ']',
142
				$field['label'],
143
				[ $this, 'output_input_field' ],
144
				$this->page_id,
145
				$this->option_key,
146
				$field['args']
147
			);
148
		}
149
	}
150
151
152
	/**
153
	 * Outputs settings page additional info.
154
	 *
155
	 * Prints more details on the plugin settings page.
156
	 *
157
	 * @internal callback method
158
	 *
159
	 * @since 1.6.0
160
	 */
161
	public function output_settings_instructions() {
162
163
		?>
164
		<p><?php printf(
165
				/* translators: Placeholder: %s refers to the PHP Console library, pointing to its GitHub repository */
166
				_x( 'This plugin allows you to use %s within your WordPress installation for testing, debugging and development purposes.', 'PHP Console, the PHP Library', 'wp-php-console' ),
167
				'<a href="' . esc_url( Plugin::get_php_console_repository_url() ) . '" target="_blank">PHP Console</a>'
168
			);
169
		?></p>
170
		<h4><?php esc_html_e( 'Usage instructions:', 'wp-php-console' ); ?></h4>
171
		<ol>
172
			<?php
173
174
			$instructions = [
175
				sprintf(
176
					/* translators: Placeholder: %s - the Google Chrome PHP Console extension download link */
177
					_x( 'Make sure you have downloaded and installed the %s.', 'PHP Console, the Chrome Extension', 'wp-php-console' ),
178
					/* translators: Placeholder: %s - PHP Console extension name */
179
					'<a href="' . esc_url( Plugin::get_php_console_chrome_extension_web_store_url() ) . '" target="_blank">' . sprintf( __( '%s extension for Google Chrome', 'wp-php-console' ), 'PHP Console' ) . '</a>'
180
				),
181
				sprintf(
182
					/* translators: Placeholders: %1$s - opening PHP <a> link tag, %2$s - closing PHP </a> link tag */
183
					__( 'If the Chrome extension is unavailable from the web store, you may %1$sdownload and install it from the source%2$s.', 'wp-php-console' ),
184
					'<a href="' . esc_url( Plugin::get_php_console_chrome_extension_repository_url() ) . '" target="_blank">',
185
					'</a>'
186
				),
187
				esc_html__( 'Set a password for the eval terminal in the options below and hit "Save Changes".', 'wp-php-console' ),
188
				esc_html__( 'Reload any page of your installation and click on the key icon in your Chrome browser address bar, enter your password and access the terminal.', 'wp-php-console' ),
189
				esc_html__( 'From the eval terminal you can execute any PHP or WordPress specific function, including functions from your plugins and active theme.', 'wp-php-console' ),
190
				sprintf(
191
					/* translators: Placeholders: %1$s - PHP code snippet example, %2$s - Chrome javascript console shortcut */
192
					__( 'In your PHP code, you can call PHP Console debug statements like %1$s to display PHP variables in the browser\'s JavaScript-console (e.g. %2$s) and optionally filter selected tags through the browser\'s Remote PHP Eval Terminal screen\'s "Ignore Debug options".', 'wp-php-console' ),
193
					'<code>debug(&#36;var, &#36;tag)</code>',
194
					'<code>CTRL+SHIFT+J</code>'
195
				),
196
			];
197
198
			foreach ( $instructions as $list_item ) :
199
				?><li><?php echo $list_item; ?></li><?php
200
			endforeach;
201
202
			?>
203
		</ol>
204
		<hr>
205
		<?php
206
	}
207
208
209
	/**
210
	 * Gets the field ID.
211
	 *
212
	 * @since 1.6.0
213
	 *
214
	 * @param array $field field arguments
215
	 * @return string
216
	 */
217
	private function get_field_id( array $field ) {
218
219
		return $this->page_id . '-' . $field['id'];
220
	}
221
222
223
	/**
224
	 * Gets the field name.
225
	 *
226
	 * @since 1.6.0
227
	 *
228
	 * @param array $field field arguments
229
	 * @return string
230
	 */
231
	private function get_field_name( array $field ) {
232
233
		return str_replace( '-', '_', $this->page_id . '[' . $field['id'] . ']' );
234
	}
235
236
237
	/**
238
	 * Gets the field current value.
239
	 *
240
	 * @since 1.6.0
241
	 *
242
	 * @param array $field field arguments
243
	 * @return int|string|bool
244
	 */
245
	private function get_field_value( array $field ) {
246
247
		return $this->options[ $field['id'] ];
248
	}
249
250
251
	/**
252
	 * Outputs an input field.
253
	 *
254
	 * @internal callback method
255
	 *
256
	 * @since 1.6.0
257
	 *
258
	 * @param array $args
259
	 */
260
	public function output_input_field( array $args = [] ) {
261
262
		if ( empty( $args ) ) {
263
			return;
264
		}
265
266
		switch ( $args['type'] ) {
267
			case 'password' :
268
			case 'text' :
269
				$this->output_input_text_field( $args );
270
				break;
271
			case 'checkbox' :
272
				$this->output_checkbox_field( $args );
273
			break;
274
		}
275
	}
276
277
278
	/**
279
	 * Outputs a text input field.
280
	 *
281
	 * @since 1.6.0
282
	 *
283
	 * @param array $args
284
	 */
285
	private function output_input_text_field( $args = [] ) {
286
287
		?>
288
		<label>
289
			<input
290
				type="<?php echo isset( $args['type'] ) ? esc_attr( $args['type'] ) : 'text'; ?>"
291
				id="<?php echo esc_attr( $this->get_field_id( $args ) ); ?>"
292
				name="<?php echo esc_attr( $this->get_field_name( $args ) ); ?>"
293
				value="<?php echo esc_attr( $this->get_field_value( $args ) ); ?>"
294
			>
295
			<?php if ( ! empty( $args['required'] ) ) : ?>
296
				<span style="color:red;" title="<?php esc_attr_e( 'Required', 'wp-php-console' ); ?>">*</span>
297
			<?php endif; ?>
298
		</label>
299
		<?php
300
301
		switch ( $args['id'] ) :
302
303
			case 'ip' :
304
				$this->output_ip_field_instructions();
305
				break;
306
307
			case 'password' :
308
				$this->output_password_field_instructions();
309
				break;
310
311
		endswitch;
312
	}
313
314
315
	/**
316
	 * Outputs the "Password" field instructions.
317
	 *
318
	 * @since 1.6.0
319
	 */
320
	private function output_password_field_instructions() {
321
322
		?>
323
		<p class="description"><?php esc_html_e( 'The password for the eval terminal. If empty, the connector will not work.', 'wp-php-console' ); ?></p>
324
		<?php
325
	}
326
327
328
	/**
329
	 * Outputs the "IP range" field instructions.
330
	 *
331
	 * @since 1.6.0
332
	 */
333
	private function output_ip_field_instructions() {
334
335
		?>
336
		<p class="description"><?php esc_html_e( 'You may specify any of the following, to give access to specific IPs to the eval terminal:', 'wp-php-console' ); ?></p>
337
		<ol>
338
			<li><span class="description"><?php printf(
339
					/* translators: Placeholders: %1$s - a single IP address, %2$s link to Varying Vagrant Vagrants project repository */
340
					__( 'An IP address (for example %1$s, %2$s default IP address).', 'wp-php-console' ),
341
					'<code>192.168.50.4</code>',
342
					'<a href="https://github.com/Varying-Vagrant-Vagrants/VVV">Varying Vagrant Vagrants</a>'
343
				); ?></span></li>
344
			<li><span class="description"><?php printf(
345
					/* translators: Placeholders: %1$s a range of IP addresses, %2$s - comma separated IP addresses */
346
					__( 'A range of addresses (%1$s) or multiple addresses, comma separated (%2$s).', 'wp-php-console' ),
347
					'<code>192.168.*.*</code>',
348
					'<code>192.168.10.25,192.168.10.28</code>'
349
				); ?></span></li>
350
		</ol>
351
		<?php
352
	}
353
354
355
	/**
356
	 * Outputs a checkbox input field.
357
	 *
358
	 * @since 1.6.0
359
	 *
360
	 * @param array $args
361
	 */
362
	public function output_checkbox_field( array $args = [] ) {
363
364
		$field_id = esc_attr( $this->get_field_id( $args ) );
365
366
		?>
367
		<label>
368
			<input
369
				type="checkbox"
370
				id="<?php echo $field_id; ?>"
371
				name="<?php echo esc_attr( $this->get_field_name( $args ) ); ?>"
372
				value="1"
373
				<?php checked( (bool) $this->get_field_value( $args ) ); ?>
374
			><?php esc_html_e( 'Yes', 'wp-php-console' ); ?>
375
		</label>
376
		<?php
377
378
		switch ( $args['id'] ) :
379
380
			case 'register' :
381
				$this->output_register_pc_class_field_instructions();
382
				break;
383
384
			case 'short' :
385
				$this->output_show_short_paths_field_instructions();
386
				break;
387
388
			case 'ssl' :
389
				$this->output_ssl_field_instructions();
390
				break;
391
392
			case 'stack' :
393
				$this->output_show_call_stack_field_instructions();
394
				break;
395
396
		endswitch;
397
	}
398
399
400
	/**
401
	 * Outputs the "SSL option" field instructions.
402
	 *
403
	 * @since 1.6.0
404
	 */
405
	private function output_ssl_field_instructions() {
406
407
		?>
408
		<p class="description"><?php esc_html_e( 'Enable this option if you want the eval terminal to work only on a SSL connection.', 'wp-php-console' ); ?></p>
409
		<?php
410
	}
411
412
413
	/**
414
	 * Outputs the "Register PC class" field instructions.
415
	 *
416
	 * @since 1.6.0
417
	 */
418 View Code Duplication
	private function output_register_pc_class_field_instructions() {
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...
419
420
		?>
421
		<p class="description"><?php
422
			esc_html_e( 'Enable to register PC class in the global namespace.', 'wp-php-console' );
423
			echo '<br>';
424
			printf(
425
				/* translators: Placeholders: %1$s, %2$s and %3$s are PHP code snippets examples */
426
				__( 'Allows to write %1$s or %2$s instructions in PHP to inspect %3$s in the JavaScript console.', 'wp-php-console' ),
427
				'<code>PC::debug(&#36;var, &#36;tag)</code>',
428
				'<code>PC::magic_tag(&#36;var)</code>',
429
				'<code>&#36;var</code>'
430
			); ?></p>
431
		<?php
432
	}
433
434
435
	/**
436
	 * Outputs the "Show Call Stack" field instructions.
437
	 *
438
	 * @since 1.6.0
439
	 */
440
	private function output_show_call_stack_field_instructions() {
441
442
		?>
443
		<p class="description"><?php esc_html_e( 'Enable to see the full call stack when PHP Console writes to the browser JavaScript console.', 'wp-php-console' ); ?></p>
444
		<?php
445
	}
446
447
448
	/**
449
	 * Outputs the "Show Short Paths" field field instructions.
450
	 *
451
	 * @since 1.6.0
452
	 */
453 View Code Duplication
	private function output_show_short_paths_field_instructions() {
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...
454
455
		?>
456
		<p class="description"><?php
457
			esc_html_e( 'Enable to shorten the length of PHP Console error sources and traces paths in browser JavaScript console for better readability.', 'wp-php-console' );
458
			echo '<br>';
459
			printf(
460
				/* translators: Placeholders: %1$s - long server path, %2$s - shortened server path */
461
				__( 'Paths like %1$s will be displayed as %2$s', 'wp-php-console' ),
462
				'<code>/server/path/to/document/root/WP/wp-admin/admin.php:31</code>',
463
				'<code>/WP/wp-admin/admin.php:31</code>'
464
			); ?></p>
465
		<?php
466
	}
467
468
469
	/**
470
	 * Sanitizes user input in the settings page.
471
	 *
472
	 * @internal callback method
473
	 *
474
	 * @since 1.6.0
475
	 *
476
	 * @param array $option user input
477
	 * @return array sanitized input
478
	 */
479
	public function sanitize_field( $option ) {
480
481
		$input = wp_parse_args( $option, [
482
			'ip'       => '',
483
			'password' => '',
484
			'register' => false,
485
			'short'    => false,
486
			'ssl'      => false,
487
			'stack'    => false,
488
		] );
489
490
		return [
491
			'ip'       => sanitize_text_field( $input['ip'] ),
492
			'password' => sanitize_text_field( $input['password'] ),
493
			'register' => ! empty( $input['register'] ),
494
			'short'    => ! empty( $input['short'] ),
495
			'ssl'      => ! empty( $input['ssl'] ),
496
			'stack'    => ! empty( $input['stack'] ),
497
		];
498
	}
499
500
501
	/**
502
	 * Outputs the settings page.
503
	 *
504
	 * @internal callback method
505
	 *
506
	 * @since 1.6.0
507
	 */
508
	public function output_settings_page() {
509
510
		?>
511
		<div class="wrap">
512
			<h2><?php echo Plugin::NAME; ?></h2>
513
			<hr />
514
			<form method="post" action="options.php">
515
				<?php
516
517
				settings_fields( $this->option_key );
518
519
				do_settings_sections( $this->page_id );
520
521
				submit_button();
522
523
				?>
524
			</form>
525
		</div>
526
		<?php
527
	}
528
529
530
}
531