PluginProbe
WPTerm / 1.1.6
WPTerm v1.1.6
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.1.6, at wpterm.php

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