PluginProbe
WPTerm / 1.2
WPTerm v1.2
1.3 trunk 1.1.1 1.1.2 1.1.3 1.1.4 1.1.5 1.1.6 1.1.7 1.1.8 1.1.9 1.2
wpterm / wpterm.php

wpterm.php in WPTerm 1.2, at wpterm.php

1,192 lines 44.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /*
3 Plugin Name: WPTerm
4 Plugin URI: https://nintechnet.com/bruandet/
5 Description: An xterm-like plugin to run non-interactive shell commands.
6 Author: Jerome Bruandet
7 Version: 1.2
8 Author URI: https://nintechnet.com/
9 Text Domain: wpterm
10 Domain Path: /languages
11 License: GPLv3 or later
12 Network: true
13 *
14 +=====================================================================+
15 | __ ______ _____ |
16 | \ \ / / _ \_ _|__ _ __ _ __ ___ |
17 | \ \ /\ / /| |_) || |/ _ \ '__| '_ ` _ \ |
18 | \ V V / | __/ | | __/ | | | | | | | |
19 | \_/\_/ |_| |_|\___|_| |_| |_| |_| |
20 | |
21 | (c) Jerome Bruandet ~ https://nintechnet.com/ |
22 +=====================================================================+
23 */
24 define( 'WPTERM_VERSION', '1.2' );
25
26 /* ================================================================== */
27
28 if (! defined( 'ABSPATH' ) ) { die( 'Forbidden' ); }
29
30 /* ================================================================== */
31 // Force WP to load our translation files.
32
33 $wpterm_locale = array( 'fr_FR' );
34 $this_locale = get_locale();
35 if ( in_array( $this_locale, $wpterm_locale ) ) {
36 if ( file_exists( __DIR__ . "/languages/wpterm-{$this_locale}.mo" ) ) {
37 unload_textdomain( 'wpterm' );
38 load_textdomain( 'wpterm', __DIR__ . "/languages/wpterm-{$this_locale}.mo" );
39 }
40 }
41
42 /* ================================================================== */
43 // Start a session if the user is an admin and WPTerm password
44 // protection is enabled.
45
46 function wpterm_session() {
47
48 if ( current_user_can( 'install_plugins' ) && defined( 'WPTERM_PASSWORD' ) &&
49 is_main_site() ) {
50
51 if (! headers_sent() ) {
52 if (! function_exists('session_status') ) {
53 if (! session_id() ) {
54 session_start();
55 }
56 } else {
57 if ( session_status() !== PHP_SESSION_ACTIVE ) {
58 session_start();
59 }
60 }
61 }
62 }
63 }
64
65 add_action( 'admin_init', 'wpterm_session' );
66
67 /* ================================================================== */
68
69 function wpterm_activate() {
70
71 // Make sure the user meets the requirements to run WPTerm:
72
73 if ( PATH_SEPARATOR == ';' ) {
74 exit( __( 'WPTerm is not compatible with Microsoft Windows.', 'wpterm' ) );
75 }
76
77 global $wp_version;
78 if ( version_compare( $wp_version, '3.3', '<' ) ) {
79 exit( sprintf( __( 'WPTerm requires WordPress 3.3 or greater but your current version is %s.', 'wpterm' ), htmlspecialchars( $wp_version ) ) );
80 }
81
82 if ( version_compare( PHP_VERSION, '5.3.0', '<' ) ) {
83 exit( sprintf( __( 'WPTerm requires PHP 5.3 or greater but your current version is %s.', 'wpterm' ), PHP_VERSION ) );
84 }
85
86 }
87
88 register_activation_hook( __FILE__, 'wpterm_activate' );
89
90 /* ================================================================== */
91
92 function wpterm_settings_link( $links ) {
93
94 // Display the link in the "Plugins" page:
95 if (! current_user_can( 'install_plugins' ) || ! is_main_site() ) {
96 return $links;
97 }
98
99 $links[] = '<a href="'. get_admin_url( null, 'tools.php?page=wpterm' ) .
100 '">' . __( 'Terminal', 'wpterm' ) . '</a>';
101 return $links;
102 }
103
104 add_filter( 'plugin_action_links_' . plugin_basename(__FILE__), 'wpterm_settings_link' );
105
106 /* ================================================================== */
107
108 function wpterm_js_insert() {
109
110 // Insert our JS and CSS files in the footer for the admin...
111 if (! current_user_can( 'install_plugins' ) || ! is_main_site() ) {
112 return;
113 }
114 // ...when viewing WPTerm pages only:
115 if (! empty( $_GET['page'] ) && $_GET['page'] == 'wpterm' ) {
116
117 // Load terminal JS code only if we are requesting the terminal tab:
118 if (! empty( $_GET['wptermtab'] ) && $_GET['wptermtab'] == 'terminal' ) {
119 wp_enqueue_script(
120 'wpterm_script2',
121 plugin_dir_url( __FILE__ ) . 'wpterm-terminal.js',
122 array( 'jquery' )
123 );
124
125 } else {
126 wp_enqueue_script(
127 'wpterm_script',
128 plugin_dir_url( __FILE__ ) . 'wpterm.js',
129 array( 'jquery' )
130 );
131 }
132
133 wp_enqueue_style(
134 'wpterm_style',
135 plugin_dir_url( __FILE__ ) . 'wpterm.css'
136 );
137 }
138 }
139
140 add_action( 'admin_footer', 'wpterm_js_insert' );
141
142 /* ================================================================== */
143
144 function wpterm_admin_menu() {
145
146 // Append WPTerm menu to the "Tools" menu:
147 if (! is_main_site() ) { return;}
148
149 global $menu_hook;
150
151 require_once( plugin_dir_path(__FILE__) . 'wpterm-help.php' );
152
153 $menu_hook = add_submenu_page(
154 'tools.php',
155 'WPTerm',
156 'WPTerm',
157 // In a multisite environment, only the
158 // superadmin will be able to access WPTerm:
159 'install_plugins',
160 'wpterm',
161 'wpterm_main_menu'
162 );
163
164 // Load contextual help:
165 add_action( 'load-' . $menu_hook, 'wpterm_help' );
166
167 }
168
169 add_action( 'admin_menu', 'wpterm_admin_menu' );
170
171 /* ================================================================== */
172
173 function wpterm_main_menu() {
174
175 // Show the selected tab and page:
176
177 // If the terminal is password protected,
178 // check if the user is authenticated:
179 if (! wpterm_is_allowed() ) { return; }
180
181 $tab = array ( 'terminal', 'settings', 'about', 'donate' );
182 // Make sure $_GET['wptermtab']'s value is okay,
183 // otherwise set it to its default 'terminal' value:
184 if (! isset( $_GET['wptermtab'] ) || ! in_array( $_GET['wptermtab'], $tab ) ) {
185 $_GET['wptermtab'] = 'terminal';
186 }
187 $wpterm_menu = "wpterm_menu_{$_GET['wptermtab']}";
188 $wpterm_menu();
189
190 }
191
192 /* ================================================================== */
193
194 function wpterm_get_blogtimezone() {
195
196 // Get the timezone:
197
198 // From WordPress...
199 $tzstring = get_option( 'timezone_string' );
200 if (! $tzstring ) {
201 // ...or PHP?
202 $tzstring = ini_get( 'date.timezone' );
203 if (! $tzstring ) {
204 // Set it to UTC if we cannot find it:
205 $tzstring = 'UTC';
206 }
207 }
208 date_default_timezone_set( $tzstring );
209 }
210
211 /* ================================================================== */
212
213 function wpterm_menu_terminal() {
214
215 // Display the terminal:
216
217 // Fetch our options:
218 $wpterm_options = wpterm_menu_get_settings();
219
220 // Retrieve the current user info (name, home dir etc):
221 $userinfo = posix_getpwuid( posix_getuid() );
222
223 // Get current working directory:
224 if ( $wpterm_options['user-home'] == 'abspath' ) {
225 // WP current dir (a.k.a. ABSPATH):
226 $cwd = htmlspecialchars( rtrim( ABSPATH, '/' ) );
227 } else {
228 // Linux home dir:
229 $cwd = htmlspecialchars( rtrim( $userinfo['dir'], '/' ) );
230 }
231
232 // Get the blog timezone:
233 wpterm_get_blogtimezone();
234
235 $last_login = '';
236 $kernel_info = '';
237
238 // Get/set last login:
239 if (! empty( $wpterm_options['last_login'] ) ) {
240 list ( $time, $user, $ip ) = explode( ':', $wpterm_options['last_login'], 3 );
241 // Try to get hostname from its IP:
242 if (! $host = gethostbyaddr( $ip ) ) {
243 $host = $ip;
244 }
245 $date = date_i18n( 'D M d H:i:s Y', $time );
246 // We'll display this along the "welcome" message:
247 $last_login = sprintf(
248 __( 'Last login: %s, %s from %s', 'wpterm' ),
249 htmlspecialchars( $user ),
250 $date,
251 htmlspecialchars( $host ) . '\n'
252 );
253 }
254
255 // Get the current user (system and WordPress) + his/her IP:
256 $current_user = wp_get_current_user();
257 $wpuser = htmlspecialchars( $current_user->user_login );
258 $user = htmlspecialchars( $userinfo['name'] );
259 $ip = htmlspecialchars( $_SERVER['REMOTE_ADDR'] );
260 $time = time();
261
262 // We refuse to run if we're root (unless stated otherwise):
263 if ( $user == 'root' && ! defined( 'THOU_SHALT_NOT_RUN_AS_ROOT' ) ) {
264 ?>
265 <div class="error notice is-dismissible"><p><?php _e( 'Sorry, but I refuse to run as the <code>root</code> user.', 'wpterm' ) ?></p></div>
266 <div class="wrap"><h1>WPTerm</h1></div>
267 <?php
268 return;
269 }
270
271 // Display a one-time notice if we just installed WPTerm
272 // (this notice can be displayed again by entering `notice`
273 // at the terminal prompt):
274 $notice = __( "Thanks for using WPTerm!", "wpterm") . " ";
275 $notice.= __( "This is a one-time notice, please read it carefully:", "wpterm") . "<br />";
276 $notice.= "<ol>";
277 $notice.= "<li>" . __( "Just like a terminal, WPTerm lets you do almost everything you want (e.g., changing file permissions, viewing network connections or current processes etc). That's great, but if you aren't familiar with Unix shell commands, you can also damage your blog.", "wpterm") . "<br />" . __( "Therefore, each time you use WPTerm, please follow this rule of thumb: <strong>if you don't know what you're doing, don't do it!</strong>", "wpterm") . "</li>";
278 $notice.= "<li>" . __( 'Take the time to password protect the access to WPTerm. Click on the contextual "Help" menu tab located in the upper right corner to get more details about how to enable this feature.', "wpterm" ) . "</li>";
279 $notice.= "<li>" . __( "Do not try to run interactive commands, you can't (most would not run anyway because the TERM environment variable is not set). If you run one by mistake and are stuck at the prompt, press CTRL-C.", "wpterm" ) . "</li>";
280 $notice.= "</ol>";
281 $notice.= __( "If you want to read this notice again, type <code>notice</code> from WPTerm prompt.", "wpterm" );
282 if ( empty( $wpterm_options['version'] ) ) {
283 $style = '';
284 } else {
285 $style = 'style="display:none" ';
286 }
287 // Display notice:
288 ?>
289 <div <?php echo $style; ?>id="wpterm-warning" class="error notice"><?php echo $notice ?><p style="text-align:center"><a onclick="jQuery('#wpterm-warning').slideUp();"><?php _e( "Click to hide", "wpterm" ) ?></a></p></div>
290 <?php
291
292 // Save options to the database:
293 $wpterm_options['last_login'] = "$time:$wpuser:$ip";
294 $wpterm_options['version'] = WPTERM_VERSION;
295 update_option( 'wpterm_options', $wpterm_options );
296
297 // Greeting + help command (in english only, no i18n):
298 $greeting['cowsay'] = ' _________________________________\n/ ';
299 $greeting['cowsay'].= " Welcome and thank you for using" . ' \x5c\n| ';
300 $greeting['cowsay'].= " WPTerm :)" . ' |\n\x5c ';
301 $greeting['cowsay'].= " If you need help, type 'help'. " . ' /\n';
302 $greeting['cowsay'].= ' ---------------------------------\n \x5c';
303 $greeting['cowsay'].= ' ^__^ v' . WPTERM_VERSION . '\n';
304 $greeting['cowsay'].= ' \x5c (oo)\x5c_______\n';
305 $greeting['cowsay'].= ' (__)\x5c )\x5c/\x5c\n';
306 $greeting['cowsay'].= ' ||----w |\n';
307 $greeting['cowsay'].= ' || ||\n';
308 $greeting['wpterm'] = ' __ ______ _____\n';
309 $greeting['wpterm'].= ' \x5c \x5c / / _ \x5c_ _|__ _ __ _ __ ___\n';
310 $greeting['wpterm'].= ' \x5c \x5c /\x5c / /| |_) || |/ _ \x5c \'__| \'_ ` _ \x5c\n';
311 $greeting['wpterm'].= ' \x5c V V / | __/ | | __/ | | | | | | |\n';
312 $greeting['wpterm'].= ' \x5c_/\x5c_/ |_| |_|\x5c___|_| |_| |_| |_| v' .
313 WPTERM_VERSION . '\n';
314 $greeting['wpterm'].= ' If you need help, type \'help\'.\n\n';
315 $greeting['tux'] = ' .--. [------------------------------]\n';
316 $greeting['tux'].= ' |o_o | WPTerm v' . WPTERM_VERSION . '\n';
317 $greeting['tux'].= ' |:_/ |\n';
318 $greeting['tux'].= ' // \x5c \x5c Welcome and thank you for\n';
319 $greeting['tux'].= ' (| | ) using WPTerm :)\n';
320 $greeting['tux'].= ' /\'\x5c_ _/`\x5c If you need help, type \'help\'.\n';
321 $greeting['tux'].= ' \x5c___)-(___/ [------------------------------]\n';
322
323 // Try to get the kernel info:
324 list( $uname, $null ) = @run_command( 'uname -a', $wpterm_options['php-function'] );
325 if (! empty( $uname ) ) {
326 $kernel_info = htmlspecialchars( trim( $uname ) ) . '\n';
327 } else {
328 // Maybe we are running on a shared hosting account that has
329 // PHP program execution functions disabled?
330 ?>
331 <div class="error notice is-dismissible"><p><?php printf( __( "I was unable to run a shell command. Make sure that you are allowed to run %sPHP program execution functions%s, otherwise WPTerm will not function.", "wpterm" ), '<a href="http://php.net/manual/en/ref.exec.php">', '</a>' ) ?></p></div>
332 <?php
333 }
334
335 // Security nonce used for the terminal (AJAX):
336 $wpterm_ajax_nonce = wp_create_nonce( 'wpterm_menu_terminal' );
337
338 ?>
339 <style>
340 .terminal-user {
341 <?php
342 if (! empty( $wpterm_options['bold-font'] ) ) {
343 echo "font-weight:bold;\n";
344 }
345 ?>
346 background-color:<?php echo $wpterm_options['background-color-val'] ?>;
347 color:<?php echo $wpterm_options['font-color-val'] ?>;
348 font-family:<?php echo $wpterm_options['font-family'] ?>;
349 font-size:<?php echo $wpterm_options['font-size'] ?>px;
350 }
351 </style>
352 <script>
353 var wpterm_ajax_nonce = "<?php echo $wpterm_ajax_nonce ?>";
354 var prompt = "<?php echo "$user:$cwd" ?> $ ";
355 var user = "<?php echo $user ?>";
356 var cwd = "<?php echo $cwd ?>";
357 var abspath = "<?php echo htmlspecialchars( rtrim( ABSPATH, '/' ) ) ?>";
358 var exec = "<?php echo htmlspecialchars( $wpterm_options['php-function'] ) ?>";
359 var last_login = "<?php echo $kernel_info . $greeting[$wpterm_options['welcome-message']] . $last_login ?>";
360 var in_progress = "<?php echo esc_js( __( 'Operations in progress, please wait.', 'wpterm' ) ) .'\n'.
361 esc_js( __( 'If you want to cancel, press CTRL+C.', 'wpterm' ) ) ?>";
362 var op_cancelled = "<?php echo esc_js( __( 'operation cancelled', 'wpterm' ) ) ?>";
363 var iptables = "<?php echo esc_js( __( 'if you want a good firewall, install NinjaFirewall (WP Edition):', 'wp-shell' ) );
364 echo '\n https://wordpress.org/plugins/ninjafirewall/'; ?>";
365 var emul_tab = <?php echo (int) $wpterm_options['tab-completion'] ?>;
366 var emul_tab_msg = "<?php echo esc_js( __( 'Tab completion is disabled. You can enable it from the Settings page', 'wpterm' ) ) ?>";
367 var logout_url = "<?php echo html_entity_decode( wp_logout_url() ); ?>";
368 var logout_msg = "<?php echo esc_js( __( 'Log out of WordPress?', 'wpterm' ) ) ?>";
369 var unknown_err = "<?php echo esc_js( __( 'WPTerm: error, no data received', 'wpterm' ) ) ?>";
370 var version = "<?php echo '\nWPTerm v' . WPTERM_VERSION ?>";
371 var scrollback = <?php echo (int) $wpterm_options['scrollback'] ?>;
372 var visual_bell = <?php echo (int) $wpterm_options['visual-bell'] ?>;
373 var audible_bell = <?php echo (int) $wpterm_options['audible-bell'] ?>;
374 var wrap_on = "<?php echo esc_js( __( "Line wrapping is enabled", "wpterm" ) ) ?>";
375 var wrap_off = "<?php echo esc_js( __( "Line wrapping is disabled", "wpterm" ) ) ?>";
376 </script>
377 <?php
378
379 // If the blog is setup to use a right-to-left language and the user runs IE/Edge browser
380 // we inform them that it is not compatible:
381 if ( is_rtl() && preg_match( '/MSIE|Trident|Edge/', $_SERVER['HTTP_USER_AGENT'] ) ) {
382 echo '<div class="notice-warning notice is-dismissible"><p>' . __('Because your current locale is RTL (Right To Left script), the terminal will not work well with your IE/Edge browser. Consider using another browser that is compatible (Firefox, Chrome, Opera or Safari).', 'wpterm') .'</p></div>';
383 }
384
385 ?>
386 <div class="wrap">
387 <h1>WPTerm</h1>
388
389 <h2 class="nav-tab-wrapper wp-clearfix">
390 <a href="?page=wpterm&wptermtab=terminal" class="nav-tab nav-tab-active"><?php _e( 'Terminal', 'wpterm' ) ?></a>
391 <a href="?page=wpterm&wptermtab=settings" class="nav-tab"><?php _e( 'Settings', 'wpterm' ) ?></a>
392 <a href="?page=wpterm&wptermtab=about" class="nav-tab"><?php _e( 'About', 'wpterm' ) ?></a>
393 <a href="?page=wpterm&wptermtab=donate" class="nav-tab"><?php _e( 'Info', 'wpterm' ) ?></a>
394 </h2>
395
396 <table style="width:100%;padding-top:4px">
397 <tr>
398 <td width="100%">
399 <textarea dir="auto" ondragstart="return false;" id="terminal" class="terminal terminal-user" onMouseOver="this.focus();" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" wrap="soft"></textarea>
400 </td>
401 </tr>
402 </table>
403
404 <div>
405 <p class="alignleft">
406 <img id="progress_gif" style="display:none" src="<?php echo plugins_url() ?>/wpterm/images/wpterm-progress.gif" width="51" height="13" title="<?php _e('Operations in progress, please wait.', 'wpterm') ?>">
407 </p>
408 <p class="alignright">
409 <img onClick="line_wrapping(this);" onTouchStart="line_wrapping(this);" id="wrap-line" border="0" src="<?php echo plugins_url() ?>/wpterm/images/wpterm-wrap.png" width="20" height="20" title="<?php _e( "Line wrapping is enabled", "wpterm" ) ?>" style="cursor:pointer">
410 &nbsp;&nbsp;&nbsp;
411 <img onClick="font_size(-1);" onTouchStart="font_size(-1);" border="0" src="<?php echo plugins_url() ?>/wpterm/images/wpterm-fontminus.png" width="21" height="20" title="<?php _e( "Decrease font size", "wpterm" ) ?>" style="cursor:pointer">
412 &nbsp;&nbsp;&nbsp;
413 <img onClick="font_size(1);" onTouchStart="font_size(1);" border="0" src="<?php echo plugins_url() ?>/wpterm/images/wpterm-fontplus.png" width="21" height="20" title="<?php _e( "Increase font size", "wpterm" ) ?>" style="cursor:pointer">
414 </p>
415 </div>
416
417 </div>
418 <?php
419 }
420
421 /* ================================================================== */
422
423 function wpterm_menu_settings() {
424
425 // Display the settings page:
426
427 // Save settings?
428 if ( isset( $_POST['save-settings'] ) ) {
429 // Verify security nonce:
430 if ( empty( $_POST['wptermnonce'] ) || ! wp_verify_nonce( $_POST['wptermnonce'], 'save_settings' ) ) {
431 wp_nonce_ays( 'save_settings' );
432 }
433 wpterm_menu_save_settings();
434 echo '<div class="updated notice is-dismissible"><p>' . __('Your changes have been saved.', 'wpterm') .'</p></div>';
435 }
436
437 // Fetch, verify and sanitize the current settings:
438 $wpterm_options = wpterm_menu_get_settings();
439
440 ?>
441 <div class="wrap">
442 <h1>WPTerm</h1>
443
444 <h2 class="nav-tab-wrapper wp-clearfix">
445 <a href="?page=wpterm&wptermtab=terminal" class="nav-tab"><?php _e( 'Terminal', 'wpterm' ) ?></a>
446 <a href="?page=wpterm&wptermtab=settings" class="nav-tab nav-tab-active"><?php _e( 'Settings', 'wpterm' ) ?></a>
447 <a href="?page=wpterm&wptermtab=about" class="nav-tab"><?php _e( 'About', 'wpterm' ) ?></a>
448 <a href="?page=wpterm&wptermtab=donate" class="nav-tab"><?php _e( 'Info', 'wpterm' ) ?></a>
449 </h2>
450
451 <br />
452
453 <form method="post">
454
455 <h3><?php _e('Fonts and Colors', 'wpterm') ?></h3>
456
457 <table class="form-table">
458
459 <tr>
460 <th scope="row"><?php _e('Font color', 'wpterm') ?></th>
461 <td>
462 <input type="text" name="font-color" value="<?php echo htmlspecialchars( $wpterm_options['font-color'] ) ?>" oninput="wpterm_preview('color', 'color', this.value)" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" />
463 <p>
464 <span class="description">
465 <?php printf ( __( 'Hexadecimal value (e.g., %s) or CSS color name (e.g., <code>red</code>).', 'wpterm' ), '<code>ffffff</code>' ) ?>
466 </span>
467 </p>
468 </td>
469 </tr>
470
471 <tr>
472 <th scope="row"><?php _e('Background color', 'wpterm') ?></th>
473 <td>
474 <input type="text" name="background-color" value="<?php echo htmlspecialchars( $wpterm_options['background-color'] ) ?>" oninput="wpterm_preview('color', 'background', this.value)" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" />
475 <p>
476 <span class="description">
477 <?php printf ( __( 'Hexadecimal value (e.g., %s) or CSS color name (e.g., <code>red</code>).', 'wpterm' ), '<code>3465A4</code>' ) ?>
478 </span>
479 </p>
480 </td>
481 </tr>
482
483 <tr>
484 <th scope="row"><?php _e('Font size', 'wpterm') ?></th>
485 <td>
486 <input type="number" class="small-text" name="font-size" step="1" min="9" max="20" value="<?php echo (int) $wpterm_options['font-size'] ?>" oninput="wpterm_preview('fontsize', 0, this.value);" /> px
487 &nbsp;&nbsp;&nbsp;&nbsp;
488 <label><input type="checkbox" id="bold_font" onchange="wpterm_preview('fontweight', 'bold_font', this.value);" name="bold-font"<?php checked( $wpterm_options['bold-font'], 1 ) ?> /><?php _e( 'Bold fonts', 'wpterm' ) ?></label>
489 <p>
490 <span class="description">
491 <?php _e('From 9 to 20px.', 'wpterm') ?>
492 </span>
493 </p>
494 </td>
495 </tr>
496
497 <tr>
498 <th scope="row"><?php _e('Font family', 'wpterm') ?></th>
499 <td>
500 <input type="text" class="regular-text" name="font-family" value="<?php echo htmlspecialchars( $wpterm_options['font-family'] ) ?>" oninput="wpterm_preview('fontface', 0, this.value)" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" />
501 <p>
502 <span class="description">
503 <?php _e( 'Multiple values must be comma separated (e.g., <code>Consolas,Monaco,monospace</code>)', 'wpterm' ) ?>
504 </span>
505 </p>
506 </td>
507 </tr>
508
509 <?php
510 if (! empty( $wpterm_options['bold-font'] ) ) {
511 $font_weight = 'font-weight:bold;';
512 } else {
513 $font_weight = 'font-weight:normal;';
514 }
515 ?>
516 <tr>
517 <th scope="row"><?php _e('Test', 'wpterm') ?></th>
518 <td>
519 <textarea autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" id="textarea-test" rows="3" style="width:20em;resize:both;padding:10px;color:<?php echo htmlspecialchars( $wpterm_options['font-color-val'] ) ?>;background-color:<?php echo htmlspecialchars( $wpterm_options['background-color-val'] ) ?>;font-size:<?php echo (int) $wpterm_options['font-size'] ?>px;font-family:<?php echo htmlspecialchars( $wpterm_options['font-family'] ) ?>;<?php echo $font_weight ?>"><?php echo "ABCDEFGHIJKLMNOPQRSTUVWXYZ\nabcdefghijklmnopqrstuvwxyz\n0123456789" ?></textarea>
520 </td>
521 </tr>
522
523 </table>
524
525 <br />
526
527 <h3><?php _e('Terminal', 'wpterm') ?></h3>
528
529 <table class="form-table">
530
531 <tr>
532 <th scope="row"><?php _e('Use the following PHP function for command execution', 'wpterm') ?></th>
533 <td>
534 <p>
535 <label>
536 <input type="radio" name="php-function" value="exec"<?php checked( $wpterm_options['php-function'], 'exec' ) ?> /><code>exec</code>
537 </label>
538 </p>
539 <p>
540 <label>
541 <input type="radio" name="php-function" value="shell_exec"<?php checked( $wpterm_options['php-function'], 'shell_exec' ) ?> /><code>shell_exec</code>
542 </label>
543 </p>
544 <p>
545 <label>
546 <input type="radio" name="php-function" value="system"<?php checked( $wpterm_options['php-function'], 'system' ) ?> /><code>system</code>
547 </label>
548 </p>
549 <p>
550 <label>
551 <input type="radio" name="php-function" value="passthru"<?php checked( $wpterm_options['php-function'], 'passthru' ) ?> /><code>passthru</code>
552 </label>
553 </p>
554 <p>
555 <label>
556 <input type="radio" name="php-function" value="popen"<?php checked( $wpterm_options['php-function'], 'popen' ) ?> /><code>popen</code>
557 </label>
558 </p>
559 </td>
560 </tr>
561
562
563 <tr>
564 <th scope="row"><?php _e('Emulate pseudo-Tab completion?', 'wpterm') ?></th>
565 <td>
566 <p>
567 <label>
568 <input type="radio" name="tab-completion" value="1"<?php checked( $wpterm_options['tab-completion'], 1 ) ?> /><?php _e( 'Yes', 'wpterm' ) ?>
569 </label>
570 </p>
571 <p>
572 <label>
573 <input type="radio" name="tab-completion" value="0"<?php checked( $wpterm_options['tab-completion'], 0 ) ?> /><?php _e( 'No', 'wpterm' ) ?>
574 </label>
575 </p>
576 </td>
577 </tr>
578
579 <?php
580 // Retrieve user info:
581 $userinfo = posix_getpwuid( posix_getuid() );
582 ?>
583 <tr>
584 <th scope="row"><?php _e('Default working directory', 'wpterm') ?></th>
585 <td>
586 <p>
587 <label>
588 <input type="radio" name="user-home" value="abspath"<?php checked( $wpterm_options['user-home'], 'abspath' ) ?> /><?php printf( __( 'WordPress ABSPATH (%s)', 'wpterm' ), '<code>'. htmlspecialchars( ABSPATH ) .'</code>' ) ?>
589 </label>
590 </p>
591 <span class="description"><?php printf( __( "Tip: to go back to that directory, type %s.", "wpterm" ), '<code>cd $ABSPATH</code>' ) ?></span>
592
593 <p>
594 <label>
595 <input type="radio" name="user-home" value="homedir"<?php checked( $wpterm_options['user-home'], 'homedir' ) ?> /><?php printf( __( 'User home directory (%s)', 'wpterm' ), '<code>'. htmlspecialchars( $userinfo['dir'] ) .'</code>' ) ?>
596 </label>
597 </p>
598 </td>
599 </tr>
600
601 <tr>
602 <th scope="row"><?php _e('Scrollback', 'wpterm') ?></th>
603 <td>
604 <label><?php printf( __( "Limit scrollback to %s lines", "wpterm" ) , '<input type="number" class="small-text" name="scrollback" step="1" min="1" max="3000" value="' . (int) $wpterm_options['scrollback'] .'" />' ) ?></label>
605 <br>
606 <span class="description">
607 <?php _e('Max 3,000 lines.', 'wpterm') ?>
608 </span>
609 </td>
610 </tr>
611
612 <tr>
613 <th scope="row"><?php _e('Welcome message', 'wpterm') ?></th>
614 <td>
615 <p>
616 <label>
617 <input type="radio" name="welcome-message" value="wpterm"<?php checked( $wpterm_options['welcome-message'], 'wpterm' ) ?> />WPTerm
618 </label>
619 </p>
620 <p>
621 <label>
622 <input type="radio" name="welcome-message" value="cowsay"<?php checked( $wpterm_options['welcome-message'], 'cowsay' ) ?> />Cowsay
623 </label>
624 </p>
625 <p>
626 <label>
627 <input type="radio" name="welcome-message" value="tux"<?php checked( $wpterm_options['welcome-message'], 'tux' ) ?> />Tux
628 </label>
629 </p>
630 </td>
631 </tr>
632
633 <?php
634 // IE up to 11 isn't compatible with our 'Audible bell':
635 if ( isset( $_SERVER["HTTP_USER_AGENT"] ) && strpos( $_SERVER["HTTP_USER_AGENT"], '; rv:11' ) !== false ) {
636 $disabled = ' disabled="disabled"';
637 } else {
638 $disabled = '';
639 }
640 ?>
641 <tr>
642 <th scope="row"><?php _e('Terminal bell', 'wpterm') ?></th>
643 <td>
644 <p><label id="visual-bell">
645 <input type="checkbox" onchange="bell_preview(this, 'visual');" name="visual-bell"<?php checked( $wpterm_options['visual-bell'], 1 ) ?> /><?php _e( 'Visual bell', 'wpterm' ) ?>
646 </label></p>
647 <p><label>
648 <input type="checkbox"<?php echo $disabled ?> onchange="bell_preview(this, 'beep');" name="audible-bell"<?php checked( $wpterm_options['audible-bell'], 1 ) ?> /><?php _e( 'Audible bell', 'wpterm' ) ?>
649 </label></p>
650 </td>
651 </tr>
652
653 </table>
654
655 <br />
656 <br />
657
658 <input class="button-primary" type="submit" name="save-settings" value="<?php _e('Save Settings', 'wpterm') ?>" />
659
660 <?php wp_nonce_field('save_settings', 'wptermnonce', 0); ?>
661
662 </form>
663
664 </div>
665
666 <?php
667
668 }
669
670 /* ================================================================== */
671
672 function wpterm_menu_get_settings() {
673
674 // Retrieve the current settings:
675
676 $wpterm_options = get_option( 'wpterm_options' );
677
678 if ( empty( $wpterm_options['font-color'] ) ) {
679 $wpterm_options['font-color'] = 'ffffff';
680 } else {
681 $wpterm_options['font-color'] = preg_replace( '/\W/', '', $wpterm_options['font-color'] );
682 }
683 if ( ctype_xdigit( $wpterm_options['font-color'] ) ) {
684 $wpterm_options['font-color-val'] = '#' . $wpterm_options['font-color'];
685 } else {
686 $wpterm_options['font-color-val'] = $wpterm_options['font-color'];
687 }
688
689 if ( empty( $wpterm_options['background-color'] ) ) {
690 $wpterm_options['background-color'] = '3465A4';
691 } else {
692 $wpterm_options['background-color'] = preg_replace( '/\W/', '', $wpterm_options['background-color'] );
693 }
694 if ( ctype_xdigit( $wpterm_options['background-color'] ) ) {
695 $wpterm_options['background-color-val'] = '#' . $wpterm_options['background-color'];
696 } else {
697 $wpterm_options['background-color-val'] = $wpterm_options['background-color'];
698 }
699
700 if (! isset( $wpterm_options['font-size'] ) || ! preg_match( '/^(?:9|1[0-9]|20)$/', $wpterm_options['font-size'] ) ) {
701 $wpterm_options['font-size'] = 13;
702 }
703
704
705 if (! empty( $wpterm_options['bold-font'] ) ) {
706 $wpterm_options['bold-font'] = 1;
707 } else {
708 $wpterm_options['bold-font'] = 0;
709 }
710
711 if (! empty( $wpterm_options['font-family'] ) ) {
712 $wpterm_options['font-family'] = preg_replace( '/[^\'" ,a-zA-Z]/', '', $wpterm_options['font-family'] );
713 $wpterm_options['font-family'] = trim( $wpterm_options['font-family'], ' ,' );
714 }
715 if ( empty( $wpterm_options['font-family'] ) ) {
716 $wpterm_options['font-family'] = 'Consolas,Monaco,monospace';
717 }
718
719 if ( empty( $wpterm_options['welcome-message'] ) || ! preg_match( '/^(?:wpterm|cowsay|tux)$/', $wpterm_options['welcome-message'] ) ) {
720 $wpterm_options['welcome-message'] = 'wpterm';
721 }
722
723 if ( empty( $wpterm_options['php-function'] ) || ! preg_match( '/^(?:exec|shell_exec|system|passthru|popen)$/', $wpterm_options['php-function'] ) ) {
724 // WPTerm <1.1.2:
725 if ( @$wpterm_options['php-function'] == 'backtick' ) {
726 $wpterm_options['php-function'] = 'shell_exec';
727 } else {
728 $wpterm_options['php-function'] = 'exec';
729 }
730 }
731
732 if (! isset( $wpterm_options['tab-completion'] ) || $wpterm_options['tab-completion'] == 1 ) {
733 // Default value:
734 $wpterm_options['tab-completion'] = 1;
735 } else {
736 $wpterm_options['tab-completion'] = 0;
737 }
738
739
740 if (! isset( $wpterm_options['user-home'] ) || $wpterm_options['user-home'] == 'abspath' ) {
741 $wpterm_options['user-home'] = 'abspath';
742 } else {
743 $wpterm_options['user-home'] = 'homedir';
744 }
745
746
747 if (! empty( $wpterm_options['scrollback'] ) ) {
748 $wpterm_options['scrollback'] = (int) $wpterm_options['scrollback'];
749 if ( $wpterm_options['scrollback'] < 1 || $wpterm_options['scrollback'] > 3000 ) {
750 $wpterm_options['scrollback'] = 512;
751 }
752 } else {
753 $wpterm_options['scrollback'] = 512;
754 }
755
756
757 if (! isset( $wpterm_options['visual-bell'] ) || $wpterm_options['visual-bell'] == 1 ) {
758 $wpterm_options['visual-bell'] = 1;
759 } else {
760 $wpterm_options['visual-bell'] = 0;
761 }
762
763 if (! empty( $wpterm_options['audible-bell'] ) ) {
764 $wpterm_options['audible-bell'] = 1;
765 } else {
766 $wpterm_options['audible-bell'] = 0;
767 }
768
769
770 return $wpterm_options;
771
772 }
773
774 /* ================================================================== */
775
776 function wpterm_menu_save_settings() {
777
778 // Check and save the terminal settings:
779
780 $wpterm_options = get_option( 'wpterm_options' );
781
782
783 if ( empty( $_POST['font-color'] ) ) {
784 $wpterm_options['font-color'] = 'ffffff';
785 } else {
786 // Make sure $_POST['font-color'] contains only word characters:
787 $wpterm_options['font-color'] = preg_replace( '/\W/', '', $_POST['font-color'] );
788 }
789
790 if ( empty( $_POST['background-color'] ) ) {
791 $wpterm_options['background-color'] = '3465A4';
792 } else {
793 // Make sure $_POST['background-color'] contains only word characters:
794 $wpterm_options['background-color'] = preg_replace( '/\W/', '', $_POST['background-color'] );
795 }
796
797 // Make sure $_POST['font-size'] is an integer between 9 and 20,
798 // otherwise set it to 13, its default value:
799 if (! isset( $_POST['font-size'] ) || ! preg_match( '/^(?:9|1[0-9]|20)$/', $_POST['font-size'] ) ) {
800 $wpterm_options['font-size'] = 13;
801 } else {
802 $wpterm_options['font-size'] = (int)$_POST['font-size'];
803 }
804
805 if (! empty( $_POST['bold-font'] ) ) {
806 $wpterm_options['bold-font'] = 1;
807 } else {
808 $wpterm_options['bold-font'] = 0;
809 }
810
811 // Make sure $_POST['font-family'] contains only letters, commas, spaces, single and double quotes:
812 if (! empty( $_POST['font-family'] ) ) {
813 $wpterm_options['font-family'] = preg_replace( '/[^\'" ,a-zA-Z]/', '', $_POST['font-family'] );
814 $wpterm_options['font-family'] = trim( $wpterm_options['font-family'], ' ,' );
815 }
816 if ( empty( $_POST['font-family'] ) ) {
817 $wpterm_options['font-family'] = 'Consolas,Monaco,monospace';
818 }
819
820 // Make sure the value of $_POST['welcome-message'] is 'wpterm', 'cowsay' or 'tux',
821 // otherwise set it to 'wpterm', its default value:
822 if ( empty( $_POST['welcome-message'] ) || ! preg_match( '/^(?:wpterm|cowsay|tux)$/', $_POST['welcome-message'] ) ) {
823 $wpterm_options['welcome-message'] = 'wpterm';
824 } else {
825 $wpterm_options['welcome-message'] = htmlspecialchars( $_POST['welcome-message'] );
826 }
827
828 // Make sure the value of $_POST['php-function'] is 'exec', 'shell_exec', 'system', 'popen' or 'passthru',
829 // otherwise set it to 'exec', its default value:
830 if ( empty( $_POST['php-function'] ) || ! preg_match( '/^(?:exec|shell_exec|system|passthru|popen)$/', $_POST['php-function'] ) ) {
831 $wpterm_options['php-function'] = 'exec';
832 } else {
833 $wpterm_options['php-function'] = htmlspecialchars( $_POST['php-function'] );
834 }
835
836 if ( empty( $_POST['tab-completion'] ) || $_POST['tab-completion'] != 1 ) {
837 $wpterm_options['tab-completion'] = 0;
838 } else {
839 $wpterm_options['tab-completion'] = 1;
840 }
841
842 // Make sure the value of $_POST['user-home'] is 'abspath' or 'homedir',
843 // otherwise set it to 'abspath', its default value:
844 if ( empty( $_POST['user-home'] ) || ! preg_match( '/^(?:abspath|homedir)$/', $_POST['user-home'] ) ) {
845 $wpterm_options['user-home'] = 'abspath';
846 } else {
847 $wpterm_options['user-home'] = htmlspecialchars( $_POST['user-home'] );
848 }
849
850 // Make sure $_POST['scrollback'] is an integer between 1 and 3,000,
851 // otherwise set it to 512, its default value:
852 if (! empty( $_POST['scrollback'] ) ) {
853 $wpterm_options['scrollback'] = (int) $_POST['scrollback'];
854 if ( $wpterm_options['scrollback'] < 1 || $wpterm_options['scrollback'] > 3000 ) {
855 $wpterm_options['scrollback'] = 512;
856 }
857 } else {
858 $wpterm_options['scrollback'] = 512;
859 }
860
861
862 if (! empty( $_POST['audible-bell'] ) ) {
863 $wpterm_options['audible-bell'] = 1;
864 } else {
865 $wpterm_options['audible-bell'] = 0;
866 }
867 if (! empty( $_POST['visual-bell'] ) ) {
868 $wpterm_options['visual-bell'] = 1;
869 } else {
870 $wpterm_options['visual-bell'] = 0;
871 }
872
873
874 // Save current version too (we'll likely need it when updating the plugin):
875 $wpterm_options['version'] = WPTERM_VERSION;
876
877 update_option( 'wpterm_options', $wpterm_options );
878
879 }
880
881 /* ================================================================== */
882
883 function wpterm_menu_about() {
884
885 if ( file_exists( plugin_dir_path(__FILE__) . 'LICENSE.TXT' ) ) {
886 $gpl3 = file_get_contents( plugin_dir_path(__FILE__) . 'LICENSE.TXT' );
887 } else {
888 $gpl3 = __( 'Error: cannot open LICENSE.TXT!', 'wpterm' );
889 }
890 ?>
891 <div class="wrap">
892 <h1>WPTerm</h1>
893
894 <h2 class="nav-tab-wrapper wp-clearfix">
895 <a href="?page=wpterm&wptermtab=terminal" class="nav-tab"><?php _e( 'Terminal', 'wpterm' ) ?></a>
896 <a href="?page=wpterm&wptermtab=settings" class="nav-tab"><?php _e( 'Settings', 'wpterm' ) ?></a>
897 <a href="?page=wpterm&wptermtab=about" class="nav-tab nav-tab-active"><?php _e( 'About', 'wpterm' ) ?></a>
898 <a href="?page=wpterm&wptermtab=donate" class="nav-tab"><?php _e( 'Info', 'wpterm' ) ?></a>
899 </h2>
900
901 <div class="card">
902 <h1>WPTerm v<?php echo WPTERM_VERSION ?></h1>
903 <h3>&copy; <?php echo date( 'Y' ) ?> Jerome Bruandet</h3>
904 <strong><?php _e('From the same author:', 'wpterm' ) ?></strong>
905 <ul>
906 <li><a href="https://wordpress.org/plugins/ninjafirewall/">NinjaFirewall (WP Edition)</a>: <?php _e('A true Web Application Firewall to protect and secure WordPress.', 'wpterm' ) ?></li>
907 <li><a href="https://wordpress.org/plugins/ninjascanner/">NinjaScanner</a>: <?php _e('A lightweight, fast and powerful antivirus scanner for WordPress.', 'wpterm' ) ?></li>
908 <li><a href="https://wordpress.org/plugins/dashboard-cleaner/">Dashboard Cleaner</a>: <?php _e('Reclaim your admin dashboard: Get rid of annoying banners, unwanted ads and other nuisances.', 'wpterm' ) ?></li>
909 </ul>
910 <br />
911 <br />
912 <textarea id="wpterm-license" class="small-text code" style="display:none" cols="60" rows="8" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"><?php echo htmlspecialchars( $gpl3 ) ?></textarea>
913 <input id="wpterm-license-button" type="button" class="button-secondary" value="<?php _e('View license', 'wpterm' ) ?>" onClick="show_license();" />
914 <br />&nbsp;
915 </div>
916 </div>
917 <?php
918 }
919
920 /* ================================================================== */
921
922 function wpterm_menu_donate() {
923
924 // Donate menu:
925
926 ?>
927 <div class="wrap">
928 <h1><?php _e('Info', 'wpterm' ) ?></h1>
929
930 <h2 class="nav-tab-wrapper wp-clearfix">
931 <a href="?page=wpterm&wptermtab=terminal" class="nav-tab"><?php _e( 'Terminal', 'wpterm' ) ?></a>
932 <a href="?page=wpterm&wptermtab=settings" class="nav-tab"><?php _e( 'Settings', 'wpterm' ) ?></a>
933 <a href="?page=wpterm&wptermtab=about" class="nav-tab"><?php _e( 'About', 'wpterm' ) ?></a>
934 <a href="?page=wpterm&wptermtab=donate" class="nav-tab nav-tab-active"><?php _e( 'Info', 'wpterm' ) ?></a>
935 </h2>
936
937 <div class="card">
938 <p><?php _e('<strong>WPTerm</strong> is open-source and free. If you like it and want to support it, you can either donate or rate it on wordpress.org.', 'wpterm' ) ?></p>
939 <hr />
940 <h3><?php _e('Bitcoin donation', 'wpterm' ) ?></h3>
941 <br />
942 <a href="bitcoin:13GH1yAU22ukKQ4AxhtBnb8eiNRtzbqsUC?message=WPTerm%20donation"><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIYAAACGCAIAAACXG2XGAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4QYCCjMiGBn+rgAAAzJJREFUeNrtncFyg0AMQ6HD//9yeu10GsZG0jaGpzMhBMUSttfL/nq9NvBJOLZt2/fdft6fTL87/7tjKp9VrseF0H374l/5aYASKAEVL3Fpbldb3/lHwg8qXvXu/JVjjPeNKEG4AJSM95KuNygaWtH0yvkVD0vkGeJ9I0oQLgAlt/KSBLrP9a58ons9ifoVUYJwASjBSzz+kfCGbg3q5/Hp+hVRgnABKHm6l7g0tOsB3XzC1dtXfM5434gShAtAyXgvSdd2Ep5R8bD0mjHjfSNKEC4AJeOwLy7gdDU30c9Q/IwoQbgAlIC/vaRSI+rqeKI+1l3TtXJOxfW9zJcgXABKJuLYav0DxTOUfkbCwxRPcuVYJ+cnShAuACUjvUR5Hk9ovct7up+tXL8y21j0HqIE4QJQMtJLXNrdrWsptbVurpCeI1HWEfz6XUQJwgWgZHxe0p3PcPWxuzPwykzJyhyFKEG4AJQ8xUu6sxquPsfKWcVEbuG6BvolCBeAkuk4WxP8X/uIpHvvrvXESr5C7x3hAlDyRC9R+t5KfpDwBlddrtubIUoQLgAlT/SStF53j1F8qNsXcc2mXMhjiBKEC0DJSC9J5xldfxJn/ZblT6EcjihBuACUjM9LXPWldH9eyQkS8yuuHI4oQbgAlEzEcUFPXTpbWRuWyBVca39DfRqiBOECUDLeSxJ75VY0VJn1S7wfZfF+jkQJwgWgZLyXJJ67FY1O5A2u7+2+P5goQbgAlDzFS5TZurTmrswhVta7iBKEC0DJ3bxE0fGKx6TzDNd+J4l9Yi7U1ogShAtAyThceX9J91k+nXO45ldWvvvk5HqIEoQLQMlIL4l/h6nvvSAnaHmPklednJMoQbgAlIzDsWX23VL2gnT5h5IbuTzywnUSJQgXgJKRXpLQVkVzK9fTff9jYg8V1z6PRAnCBaDkbl6i5ASuPEZ571ZX95Uevuv3EiUIF4CSO3uJC0r/I72vopJPhOp1RAnCBaAEL7mo0a7eu6L1rvMofRSiBOECUHI3L1k5A+iaZ0zkOq4eD/0ShAtAyV1xNl+iIL1HZCIfUnzCtf6YGhfCBaBkqpdwFz4K3/F65gVuLsNPAAAAAElFTkSuQmCC"><br />13GH1yAU22ukKQ4AxhtBnb8eiNRtzbqsUC</a>
943 <br />&nbsp;
944 <hr />
945 <h3><?php _e('Rate it', 'wpterm' ) ?></h3>
946 <a href="https://wordpress.org/support/view/plugin-reviews/wpterm?rate=5#postform"><img title="<?php _e('Rate it', 'wpterm' ) ?>" border="0" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHQAAAAcCAIAAAA/XwxHAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3woMCgQevC7e8gAAActJREFUaN7tmb9LAmEYx9/XM1OLNDMCB8MLQRCHoKGprbW1pcWh/yKabHVsjIj+gKgGh1q1oMEIIoIup8Ph0lOvO7F7720QuZI6fd9q6X2+2/G+H57j88D7gxdTShHkb+IDBSAX5EJ+LJfS5p7RbHGVE4tll0sV82G383BIODZCwVgfcxsbBaPtoHah02gB+6tyqWI+HjoIIaRZj4zNFI1llNtv4+CLrZmisaxy3Tb2w9JM0ViEEEL42xsa1W3ttGc82ZZCTMW2FGLVv5iLp30h2R+SpbAshWT/9NpkPOdDgrGYVS7qEXVTuztxGFoVC+ZuookUFo5lXhYCUuI4ll7F41YKBNIXg0qisTxr7tRE6mw2uTROKX/yfDa1jMVlOTY0HJ/MXEYX5kZsiwtHscz68NIjGstzWsCLoexB0GOitBHJbkkYWL6jGKkTj3WeqI7HsGgsq1xqXRGv8ec3qwssn1ziGLeenXp5MxrA8sntEr3mApH8zMr9/EoxHIm6v6M/U2C/uj+PilN7LSO1hOqVvKHVHHfAtLWiXomqJaSW920H2OGMIde+ble3P5f5GNPWinp1p2cDOxwMr79/F3hDA7kgFwJyQe6/yDsZhxXHUCuqgQAAAABJRU5ErkJggg==" width="116" height="28"><br /><?php _e('Rate it on WordPress.org', 'wpterm' ) ?></a>
947 <br />&nbsp;
948 <hr />
949 <p><?php _e('Thanks!', 'wpterm' ) ?></p>
950 </div>
951 </div>
952 <?php
953 }
954
955
956 /* ================================================================== */
957
958 add_action( 'wp_ajax_wptermajax', 'wptermajax_callback' );
959
960 function wptermajax_callback() {
961
962 // The terminal AJAX callback function:
963
964 if (! current_user_can( 'install_plugins' ) || ! is_main_site() ) { wp_die(0); }
965
966 // Check AJAX security nonce:
967 if ( check_ajax_referer( 'wpterm_menu_terminal', 'wpterm_ajax_nonce', false ) ) {
968
969 // Path to return in case of fatal error:
970 $if_error = htmlspecialchars( rtrim( ABSPATH, '/' ) ) . '::';
971
972 // If the password protection is enabled, check the password:
973 if (! wpterm_is_allowed( 'ajax' ) ) {
974 echo $if_error . __( 'WPTerm: error, your password has expired. Reload this page to renew it.', 'wpterm');
975 wp_die();
976 }
977
978 if ( empty( $_POST['cmd'] ) || empty( $_POST['cwd'] ) || empty( $_POST['exec'] ) || empty( $_POST['abs'] ) ) {
979 echo $if_error . __( 'WPTerm error: missing command, path, function or abspath', 'wpterm' );
980 wp_die();
981 }
982 // Make sure the max number of lines to returned to WPTerm
983 // is a digit, otherwise set it to 512, its default value:
984 if ( empty( $_POST['scrollback'] ) || ! ctype_digit( $_POST['scrollback'] ) ) {
985 $scrollback = 512;
986 } else {
987 $scrollback = (int)$_POST['scrollback'];
988 }
989 // We don't want WordPress to escape strings with slashes:
990 $cmd = stripslashes( base64_decode( trim( $_POST['cmd'] ) ) );
991 $cwd = stripslashes( trim( $_POST['cwd'] ) );
992 $abs = stripslashes( trim( $_POST['abs'] ) );
993 // Set the ABSPATH variable, go to the current working directory,
994 // run the command, redirect STDERR to STDOUT and return the current
995 // working directory (it may have been changed e.g., `cd /foo/bar`):
996 $command = sprintf( "ABSPATH=%s;cd %s;%s 2>&1;echo [-{-`pwd`-}-]", $abs, $cwd, $cmd );
997
998 // Run the command:
999 list( $res, $ret_var ) = @run_command( $command, trim( $_POST['exec'] ) );
1000
1001 // Split the PWD and the data returned by the command:
1002 if ( preg_match( '`^(.+)?\[-{-(/.*?)-}-\]`s', $res, $match ) ) {
1003 // Turn the string into an array...
1004 $res_array = explode( "\n", $match[1] );
1005 // ...keep only the last $_POST['scrollback'] lines and re-create the string...
1006 $res_str = implode( "\n", array_slice( $res_array, -$_POST['scrollback'] ) );
1007 // ...and return it to WPTerm terminal:
1008 echo rtrim( $match[2] . '::' . $res_str );
1009 } else {
1010 if (! empty( $ret_var ) ) {
1011 echo $if_error . sprintf( __( 'WPTerm: error %s', 'wpterm' ), (int) $ret_var );
1012 } else {
1013 echo $if_error . __( 'WPTerm: unknown error. Are you allowed to run PHP program execution functions?', 'wpterm' );
1014 }
1015 }
1016 } else {
1017 echo '/::' . __( 'WPTerm: error, security nonces do not match. Try to reload this page to renew them.', 'wpterm');
1018 }
1019 wp_die();
1020
1021 }
1022
1023 /* ================================================================== */
1024
1025 function run_command( $command, $function ) {
1026
1027 $ret_var = '';
1028 $res = '';
1029
1030 // Select which method to use to run the command:
1031
1032 if ( $function == 'shell_exec' || $function == 'backtick' ) {
1033 $res = shell_exec( $command );
1034
1035 } elseif ( $function == 'system' ) {
1036 ob_start();
1037 system( $command, $ret_var );
1038 $res = ob_get_contents();
1039 ob_end_clean();
1040
1041 } elseif ( $function == 'passthru' ) {
1042 ob_start();
1043 passthru( $command, $ret_var );
1044 $res = ob_get_contents();
1045 ob_end_clean();
1046
1047 } elseif ( $function == 'popen' ) {
1048 if ( ( $handle = popen( $command , 'r' ) ) !== false ) {
1049 while (! feof( $handle ) ) {
1050 $res .= fgets( $handle );
1051 }
1052 pclose( $handle );
1053 }
1054
1055 } else {
1056 if ( exec( $command, $res, $ret_var ) ) {
1057 $res = implode( "\n", $res );
1058 }
1059 }
1060
1061 return array( $res, $ret_var );
1062
1063 }
1064
1065 /* ================================================================== */
1066
1067 function wpterm_is_allowed( $is_ajax = null ) {
1068
1069 // Check if a password was set:
1070 if (! defined( 'WPTERM_PASSWORD' ) ) {
1071 // No, let it go:
1072 return true;
1073 }
1074
1075 // Check if the user session exists:
1076 if ( empty( $_SESSION['wptermpwd'] ) ) {
1077 // Return if this is an AJAX call (a warning
1078 // will be displayed from the terminal prompt):
1079 if ( isset( $is_ajax ) ) { return false; }
1080 // Display the password form:
1081 if( ! wpterm_password_prompt(1) ) {
1082 return false;
1083 }
1084 }
1085 // Check if passwords match:
1086 if ( $_SESSION['wptermpwd'] != WPTERM_PASSWORD ) {
1087 // Password does not match, clear it:
1088 unset( $_SESSION['wptermpwd'] );
1089 if ( isset( $is_ajax ) ) { return false; }
1090 // Display the password form:
1091 if (! wpterm_password_prompt(2) ) {
1092 return false;
1093 }
1094 }
1095
1096 // Okay, go ahead!
1097 return true;
1098
1099 }
1100
1101 /* ================================================================== */
1102
1103 function wpterm_password_prompt( $err = 0 ) {
1104
1105 // Display the password form:
1106
1107 // Password form submitted?
1108 if ( isset( $_POST['wptermpwd'] ) ) {
1109 // Verify security nonce:
1110 if ( empty( $_POST['wptermnonce'] ) || ! wp_verify_nonce( $_POST['wptermnonce'], 'wpterm_password' ) ) {
1111 wp_nonce_ays( 'wpterm_password' );
1112 }
1113 // Verify password:
1114 if ( sha1( $_POST['wptermpwd'] ) === WPTERM_PASSWORD ) {
1115 $_SESSION['wptermpwd'] = sha1( $_POST['wptermpwd'] );
1116 return true;
1117 } else {
1118 $err = 3;
1119 }
1120 }
1121
1122 if ( $err == 3 ) {
1123 ?>
1124 <div class="error notice is-dismissible"><p><?php _e( 'Wrong password, please try again.', 'wpterm' ) ?></p></div>
1125 <?php
1126 } else {
1127 ?>
1128 <div class="notice-info notice is-dismissible"><p><?php printf( __( 'A password is required to access WPTerm (#%s).', 'wpterm' ), (int) $err ) ?></p></div>
1129 <?php
1130 }
1131 ?>
1132
1133 <div class="wrap">
1134 <h1>WPTerm</h1>
1135
1136 <h2 class="nav-tab-wrapper wp-clearfix" style="cursor:not-allowed">
1137 <a class="nav-tab"><?php _e( 'Terminal', 'wpterm' ) ?></a>
1138 <a class="nav-tab"><?php _e( 'Settings', 'wpterm' ) ?></a>
1139 <a class="nav-tab"><?php _e( 'About', 'wpterm' ) ?></a>
1140 <a class="nav-tab"><?php _e( 'Info', 'wpterm' ) ?></a>
1141 </h2>
1142
1143 <div class="card">
1144
1145 <form method="post">
1146 <h3><?php _e( 'Enter your WPTerm password:', 'wpterm' ) ?></h3>
1147 <p><input class="input" type="password" name="wptermpwd" placeholder="Password" autofocus /></p>
1148 <p><input type="submit" class="button-secondary" /></p>
1149 <?php wp_nonce_field('wpterm_password', 'wptermnonce', 0); ?>
1150 </form>
1151
1152 </div>
1153 </div>
1154 <?php
1155
1156 return false;
1157
1158 }
1159
1160 /* ================================================================== */
1161 // Write session to disk to prevent cURL time-out which may occur with
1162 // WordPress (since 4.9.2, see https://core.trac.wordpress.org/ticket/43358),
1163 // or plugins such as "Health Check".
1164
1165 add_filter( 'pre_http_request', 'wpterm_pre_http_request', 10, 3 );
1166
1167 function wpterm_pre_http_request( $preempt, $r, $url ) {
1168
1169 // NFW_DISABLE_SWC can be defined in wp-config.php (undocumented):
1170 if (! defined('NFW_DISABLE_SWC') && isset( $_SESSION ) ) {
1171 if ( function_exists( 'get_site_url' ) ) {
1172 $parse = parse_url( get_site_url() );
1173 $s_url = @$parse['scheme'] . "://{$parse['host']}";
1174 if ( strpos( $url, $s_url ) === 0 ) {
1175 @session_write_close();
1176 }
1177 }
1178 }
1179 return false;
1180 }
1181
1182 // Get rid of the Site Health php_sessions test, it returns a scary message
1183 // although everything is working as expected
1184 function wpterm_remove_php_sessions_test( $tests ) {
1185 unset( $tests['direct']['php_sessions'] );
1186 return $tests;
1187 }
1188 add_filter( 'site_status_tests', 'wpterm_remove_php_sessions_test' );
1189
1190 /* ================================================================== */
1191 // EOF
1192