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

1,172 lines 44.5 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.7
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.7' );
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 <?php
376
377 // If the blog is setup to use a right-to-left language and the user runs IE/Edge browser
378 // we inform them that it is not compatible:
379 if ( is_rtl() && preg_match( '/MSIE|Trident|Edge/', $_SERVER['HTTP_USER_AGENT'] ) ) {
380 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>';
381 }
382
383 ?>
384 <div class="wrap">
385 <h1>WPTerm</h1>
386
387 <h2 class="nav-tab-wrapper wp-clearfix">
388 <a href="?page=wpterm&wptermtab=terminal" class="nav-tab nav-tab-active"><?php _e( 'Terminal', 'wpterm' ) ?></a>
389 <a href="?page=wpterm&wptermtab=settings" class="nav-tab"><?php _e( 'Settings', 'wpterm' ) ?></a>
390 <a href="?page=wpterm&wptermtab=about" class="nav-tab"><?php _e( 'About', 'wpterm' ) ?></a>
391 <a href="?page=wpterm&wptermtab=donate" class="nav-tab"><?php _e( 'Donate', 'wpterm' ) ?></a>
392 </h2>
393
394 <table style="width:100%;padding-top:4px">
395 <tr>
396 <td width="100%">
397 <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>
398 </td>
399 </tr>
400 </table>
401
402 <div>
403 <p class="alignleft">
404 <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') ?>">
405 </p>
406 <p class="alignright">
407 <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">
408 &nbsp;&nbsp;&nbsp;
409 <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">
410 &nbsp;&nbsp;&nbsp;
411 <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">
412 </p>
413 </div>
414
415 </div>
416 <?php
417 }
418
419 /* ================================================================== */
420
421 function wpterm_menu_settings() {
422
423 // Display the settings page:
424
425 // Save settings?
426 if ( isset( $_POST['save-settings'] ) ) {
427 // Verify security nonce:
428 if ( empty( $_POST['wptermnonce'] ) || ! wp_verify_nonce( $_POST['wptermnonce'], 'save_settings' ) ) {
429 wp_nonce_ays( 'save_settings' );
430 }
431 wpterm_menu_save_settings();
432 echo '<div class="updated notice is-dismissible"><p>' . __('Your changes have been saved.', 'wpterm') .'</p></div>';
433 }
434
435 // Fetch, verify and sanitize the current settings:
436 $wpterm_options = wpterm_menu_get_settings();
437
438 ?>
439 <div class="wrap">
440 <h1>WPTerm</h1>
441
442 <h2 class="nav-tab-wrapper wp-clearfix">
443 <a href="?page=wpterm&wptermtab=terminal" class="nav-tab"><?php _e( 'Terminal', 'wpterm' ) ?></a>
444 <a href="?page=wpterm&wptermtab=settings" class="nav-tab nav-tab-active"><?php _e( 'Settings', 'wpterm' ) ?></a>
445 <a href="?page=wpterm&wptermtab=about" class="nav-tab"><?php _e( 'About', 'wpterm' ) ?></a>
446 <a href="?page=wpterm&wptermtab=donate" class="nav-tab"><?php _e( 'Donate', 'wpterm' ) ?></a>
447 </h2>
448
449 <br />
450
451 <form method="post">
452
453 <h3><?php _e('Fonts and Colors', 'wpterm') ?></h3>
454
455 <table class="form-table">
456
457 <tr>
458 <th scope="row"><?php _e('Font color', 'wpterm') ?></th>
459 <td>
460 <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" />
461 <p>
462 <span class="description">
463 <?php printf ( __( 'Hexadecimal value (e.g., %s) or CSS color name (e.g., <code>red</code>).', 'wpterm' ), '<code>ffffff</code>' ) ?>
464 </span>
465 </p>
466 </td>
467 </tr>
468
469 <tr>
470 <th scope="row"><?php _e('Background color', 'wpterm') ?></th>
471 <td>
472 <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" />
473 <p>
474 <span class="description">
475 <?php printf ( __( 'Hexadecimal value (e.g., %s) or CSS color name (e.g., <code>red</code>).', 'wpterm' ), '<code>3465A4</code>' ) ?>
476 </span>
477 </p>
478 </td>
479 </tr>
480
481 <tr>
482 <th scope="row"><?php _e('Font size', 'wpterm') ?></th>
483 <td>
484 <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
485 &nbsp;&nbsp;&nbsp;&nbsp;
486 <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>
487 <p>
488 <span class="description">
489 <?php _e('From 9 to 20px.', 'wpterm') ?>
490 </span>
491 </p>
492 </td>
493 </tr>
494
495 <tr>
496 <th scope="row"><?php _e('Font family', 'wpterm') ?></th>
497 <td>
498 <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" />
499 <p>
500 <span class="description">
501 <?php _e( 'Multiple values must be comma separated (e.g., <code>Consolas,Monaco,monospace</code>)', 'wpterm' ) ?>
502 </span>
503 </p>
504 </td>
505 </tr>
506
507 <?php
508 if (! empty( $wpterm_options['bold-font'] ) ) {
509 $font_weight = 'font-weight:bold;';
510 } else {
511 $font_weight = 'font-weight:normal;';
512 }
513 ?>
514 <tr>
515 <th scope="row"><?php _e('Test', 'wpterm') ?></th>
516 <td>
517 <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>
518 </td>
519 </tr>
520
521 </table>
522
523 <br />
524
525 <h3><?php _e('Terminal', 'wpterm') ?></h3>
526
527 <table class="form-table">
528
529 <tr>
530 <th scope="row"><?php _e('Use the following PHP function for command execution', 'wpterm') ?></th>
531 <td>
532 <p>
533 <label>
534 <input type="radio" name="php-function" value="exec"<?php checked( $wpterm_options['php-function'], 'exec' ) ?> /><code>exec</code>
535 </label>
536 </p>
537 <p>
538 <label>
539 <input type="radio" name="php-function" value="shell_exec"<?php checked( $wpterm_options['php-function'], 'shell_exec' ) ?> /><code>shell_exec</code>
540 </label>
541 </p>
542 <p>
543 <label>
544 <input type="radio" name="php-function" value="system"<?php checked( $wpterm_options['php-function'], 'system' ) ?> /><code>system</code>
545 </label>
546 </p>
547 <p>
548 <label>
549 <input type="radio" name="php-function" value="passthru"<?php checked( $wpterm_options['php-function'], 'passthru' ) ?> /><code>passthru</code>
550 </label>
551 </p>
552 <p>
553 <label>
554 <input type="radio" name="php-function" value="popen"<?php checked( $wpterm_options['php-function'], 'popen' ) ?> /><code>popen</code>
555 </label>
556 </p>
557 </td>
558 </tr>
559
560
561 <tr>
562 <th scope="row"><?php _e('Emulate pseudo-Tab completion?', 'wpterm') ?></th>
563 <td>
564 <p>
565 <label>
566 <input type="radio" name="tab-completion" value="1"<?php checked( $wpterm_options['tab-completion'], 1 ) ?> /><?php _e( 'Yes', 'wpterm' ) ?>
567 </label>
568 </p>
569 <p>
570 <label>
571 <input type="radio" name="tab-completion" value="0"<?php checked( $wpterm_options['tab-completion'], 0 ) ?> /><?php _e( 'No', 'wpterm' ) ?>
572 </label>
573 </p>
574 </td>
575 </tr>
576
577 <?php
578 // Retrieve user info:
579 $userinfo = posix_getpwuid( posix_getuid() );
580 ?>
581 <tr>
582 <th scope="row"><?php _e('Default working directory', 'wpterm') ?></th>
583 <td>
584 <p>
585 <label>
586 <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>' ) ?>
587 </label>
588 </p>
589 <span class="description"><?php printf( __( "Tip: to go back to that directory, type %s.", "wpterm" ), '<code>cd $ABSPATH</code>' ) ?></span>
590
591 <p>
592 <label>
593 <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>' ) ?>
594 </label>
595 </p>
596 </td>
597 </tr>
598
599 <tr>
600 <th scope="row"><?php _e('Scrollback', 'wpterm') ?></th>
601 <td>
602 <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>
603 <br>
604 <span class="description">
605 <?php _e('Max 3,000 lines.', 'wpterm') ?>
606 </span>
607 </td>
608 </tr>
609
610 <tr>
611 <th scope="row"><?php _e('Welcome message', 'wpterm') ?></th>
612 <td>
613 <p>
614 <label>
615 <input type="radio" name="welcome-message" value="wpterm"<?php checked( $wpterm_options['welcome-message'], 'wpterm' ) ?> />WPTerm
616 </label>
617 </p>
618 <p>
619 <label>
620 <input type="radio" name="welcome-message" value="cowsay"<?php checked( $wpterm_options['welcome-message'], 'cowsay' ) ?> />Cowsay
621 </label>
622 </p>
623 <p>
624 <label>
625 <input type="radio" name="welcome-message" value="tux"<?php checked( $wpterm_options['welcome-message'], 'tux' ) ?> />Tux
626 </label>
627 </p>
628 </td>
629 </tr>
630
631 <?php
632 // IE up to 11 isn't compatible with our 'Audible bell':
633 if ( isset( $_SERVER["HTTP_USER_AGENT"] ) && strpos( $_SERVER["HTTP_USER_AGENT"], '; rv:11' ) !== false ) {
634 $disabled = ' disabled="disabled"';
635 } else {
636 $disabled = '';
637 }
638 ?>
639 <tr>
640 <th scope="row"><?php _e('Terminal bell', 'wpterm') ?></th>
641 <td>
642 <p><label id="visual-bell">
643 <input type="checkbox" onchange="bell_preview(this, 'visual');" name="visual-bell"<?php checked( $wpterm_options['visual-bell'], 1 ) ?> /><?php _e( 'Visual bell', 'wpterm' ) ?>
644 </label></p>
645 <p><label>
646 <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' ) ?>
647 </label></p>
648 </td>
649 </tr>
650
651 </table>
652
653 <br />
654 <br />
655
656 <input class="button-primary" type="submit" name="save-settings" value="<?php _e('Save Settings', 'wpterm') ?>" />
657
658 <?php wp_nonce_field('save_settings', 'wptermnonce', 0); ?>
659
660 </form>
661
662 </div>
663
664 <?php
665
666 }
667
668 /* ================================================================== */
669
670 function wpterm_menu_get_settings() {
671
672 // Retrieve the current settings:
673
674 $wpterm_options = get_option( 'wpterm_options' );
675
676 if ( empty( $wpterm_options['font-color'] ) ) {
677 $wpterm_options['font-color'] = 'ffffff';
678 } else {
679 $wpterm_options['font-color'] = preg_replace( '/\W/', '', $wpterm_options['font-color'] );
680 }
681 if ( ctype_xdigit( $wpterm_options['font-color'] ) ) {
682 $wpterm_options['font-color-val'] = '#' . $wpterm_options['font-color'];
683 } else {
684 $wpterm_options['font-color-val'] = $wpterm_options['font-color'];
685 }
686
687 if ( empty( $wpterm_options['background-color'] ) ) {
688 $wpterm_options['background-color'] = '3465A4';
689 } else {
690 $wpterm_options['background-color'] = preg_replace( '/\W/', '', $wpterm_options['background-color'] );
691 }
692 if ( ctype_xdigit( $wpterm_options['background-color'] ) ) {
693 $wpterm_options['background-color-val'] = '#' . $wpterm_options['background-color'];
694 } else {
695 $wpterm_options['background-color-val'] = $wpterm_options['background-color'];
696 }
697
698 if (! isset( $wpterm_options['font-size'] ) || ! preg_match( '/^(?:9|1[0-9]|20)$/', $wpterm_options['font-size'] ) ) {
699 $wpterm_options['font-size'] = 13;
700 }
701
702
703 if (! empty( $wpterm_options['bold-font'] ) ) {
704 $wpterm_options['bold-font'] = 1;
705 } else {
706 $wpterm_options['bold-font'] = 0;
707 }
708
709 if (! empty( $wpterm_options['font-family'] ) ) {
710 $wpterm_options['font-family'] = preg_replace( '/[^\'" ,a-zA-Z]/', '', $wpterm_options['font-family'] );
711 $wpterm_options['font-family'] = trim( $wpterm_options['font-family'], ' ,' );
712 }
713 if ( empty( $wpterm_options['font-family'] ) ) {
714 $wpterm_options['font-family'] = 'Consolas,Monaco,monospace';
715 }
716
717 if ( empty( $wpterm_options['welcome-message'] ) || ! preg_match( '/^(?:wpterm|cowsay|tux)$/', $wpterm_options['welcome-message'] ) ) {
718 $wpterm_options['welcome-message'] = 'wpterm';
719 }
720
721 if ( empty( $wpterm_options['php-function'] ) || ! preg_match( '/^(?:exec|shell_exec|system|passthru|popen)$/', $wpterm_options['php-function'] ) ) {
722 // WPTerm <1.1.2:
723 if ( @$wpterm_options['php-function'] == 'backtick' ) {
724 $wpterm_options['php-function'] = 'shell_exec';
725 } else {
726 $wpterm_options['php-function'] = 'exec';
727 }
728 }
729
730 if (! isset( $wpterm_options['tab-completion'] ) || $wpterm_options['tab-completion'] == 1 ) {
731 // Default value:
732 $wpterm_options['tab-completion'] = 1;
733 } else {
734 $wpterm_options['tab-completion'] = 0;
735 }
736
737
738 if (! isset( $wpterm_options['user-home'] ) || $wpterm_options['user-home'] == 'abspath' ) {
739 $wpterm_options['user-home'] = 'abspath';
740 } else {
741 $wpterm_options['user-home'] = 'homedir';
742 }
743
744
745 if (! empty( $wpterm_options['scrollback'] ) ) {
746 $wpterm_options['scrollback'] = (int) $wpterm_options['scrollback'];
747 if ( $wpterm_options['scrollback'] < 1 || $wpterm_options['scrollback'] > 3000 ) {
748 $wpterm_options['scrollback'] = 512;
749 }
750 } else {
751 $wpterm_options['scrollback'] = 512;
752 }
753
754
755 if (! isset( $wpterm_options['visual-bell'] ) || $wpterm_options['visual-bell'] == 1 ) {
756 $wpterm_options['visual-bell'] = 1;
757 } else {
758 $wpterm_options['visual-bell'] = 0;
759 }
760
761 if (! empty( $wpterm_options['audible-bell'] ) ) {
762 $wpterm_options['audible-bell'] = 1;
763 } else {
764 $wpterm_options['audible-bell'] = 0;
765 }
766
767
768 return $wpterm_options;
769
770 }
771
772 /* ================================================================== */
773
774 function wpterm_menu_save_settings() {
775
776 // Check and save the terminal settings:
777
778 $wpterm_options = get_option( 'wpterm_options' );
779
780
781 if ( empty( $_POST['font-color'] ) ) {
782 $wpterm_options['font-color'] = 'ffffff';
783 } else {
784 // Make sure $_POST['font-color'] contains only word characters:
785 $wpterm_options['font-color'] = preg_replace( '/\W/', '', $_POST['font-color'] );
786 }
787
788 if ( empty( $_POST['background-color'] ) ) {
789 $wpterm_options['background-color'] = '3465A4';
790 } else {
791 // Make sure $_POST['background-color'] contains only word characters:
792 $wpterm_options['background-color'] = preg_replace( '/\W/', '', $_POST['background-color'] );
793 }
794
795 // Make sure $_POST['font-size'] is an integer between 9 and 20,
796 // otherwise set it to 13, its default value:
797 if (! isset( $_POST['font-size'] ) || ! preg_match( '/^(?:9|1[0-9]|20)$/', $_POST['font-size'] ) ) {
798 $wpterm_options['font-size'] = 13;
799 } else {
800 $wpterm_options['font-size'] = (int)$_POST['font-size'];
801 }
802
803 if (! empty( $_POST['bold-font'] ) ) {
804 $wpterm_options['bold-font'] = 1;
805 } else {
806 $wpterm_options['bold-font'] = 0;
807 }
808
809 // Make sure $_POST['font-family'] contains only letters, commas, spaces, single and double quotes:
810 if (! empty( $_POST['font-family'] ) ) {
811 $wpterm_options['font-family'] = preg_replace( '/[^\'" ,a-zA-Z]/', '', $_POST['font-family'] );
812 $wpterm_options['font-family'] = trim( $wpterm_options['font-family'], ' ,' );
813 }
814 if ( empty( $_POST['font-family'] ) ) {
815 $wpterm_options['font-family'] = 'Consolas,Monaco,monospace';
816 }
817
818 // Make sure the value of $_POST['welcome-message'] is 'wpterm', 'cowsay' or 'tux',
819 // otherwise set it to 'wpterm', its default value:
820 if ( empty( $_POST['welcome-message'] ) || ! preg_match( '/^(?:wpterm|cowsay|tux)$/', $_POST['welcome-message'] ) ) {
821 $wpterm_options['welcome-message'] = 'wpterm';
822 } else {
823 $wpterm_options['welcome-message'] = htmlspecialchars( $_POST['welcome-message'] );
824 }
825
826 // Make sure the value of $_POST['php-function'] is 'exec', 'shell_exec', 'system', 'popen' or 'passthru',
827 // otherwise set it to 'exec', its default value:
828 if ( empty( $_POST['php-function'] ) || ! preg_match( '/^(?:exec|shell_exec|system|passthru|popen)$/', $_POST['php-function'] ) ) {
829 $wpterm_options['php-function'] = 'exec';
830 } else {
831 $wpterm_options['php-function'] = htmlspecialchars( $_POST['php-function'] );
832 }
833
834 if ( empty( $_POST['tab-completion'] ) || $_POST['tab-completion'] != 1 ) {
835 $wpterm_options['tab-completion'] = 0;
836 } else {
837 $wpterm_options['tab-completion'] = 1;
838 }
839
840 // Make sure the value of $_POST['user-home'] is 'abspath' or 'homedir',
841 // otherwise set it to 'abspath', its default value:
842 if ( empty( $_POST['user-home'] ) || ! preg_match( '/^(?:abspath|homedir)$/', $_POST['user-home'] ) ) {
843 $wpterm_options['user-home'] = 'abspath';
844 } else {
845 $wpterm_options['user-home'] = htmlspecialchars( $_POST['user-home'] );
846 }
847
848 // Make sure $_POST['scrollback'] is an integer between 1 and 3,000,
849 // otherwise set it to 512, its default value:
850 if (! empty( $_POST['scrollback'] ) ) {
851 $wpterm_options['scrollback'] = (int) $_POST['scrollback'];
852 if ( $wpterm_options['scrollback'] < 1 || $wpterm_options['scrollback'] > 3000 ) {
853 $wpterm_options['scrollback'] = 512;
854 }
855 } else {
856 $wpterm_options['scrollback'] = 512;
857 }
858
859
860 if (! empty( $_POST['audible-bell'] ) ) {
861 $wpterm_options['audible-bell'] = 1;
862 } else {
863 $wpterm_options['audible-bell'] = 0;
864 }
865 if (! empty( $_POST['visual-bell'] ) ) {
866 $wpterm_options['visual-bell'] = 1;
867 } else {
868 $wpterm_options['visual-bell'] = 0;
869 }
870
871
872 // Save current version too (we'll likely need it when updating the plugin):
873 $wpterm_options['version'] = WPTERM_VERSION;
874
875 update_option( 'wpterm_options', $wpterm_options );
876
877 }
878
879 /* ================================================================== */
880
881 function wpterm_menu_about() {
882
883 if ( file_exists( plugin_dir_path(__FILE__) . 'LICENSE.TXT' ) ) {
884 $gpl3 = file_get_contents( plugin_dir_path(__FILE__) . 'LICENSE.TXT' );
885 } else {
886 $gpl3 = __( 'Error: cannot open LICENSE.TXT!', 'wpterm' );
887 }
888 ?>
889 <div class="wrap">
890 <h1>WPTerm</h1>
891
892 <h2 class="nav-tab-wrapper wp-clearfix">
893 <a href="?page=wpterm&wptermtab=terminal" class="nav-tab"><?php _e( 'Terminal', 'wpterm' ) ?></a>
894 <a href="?page=wpterm&wptermtab=settings" class="nav-tab"><?php _e( 'Settings', 'wpterm' ) ?></a>
895 <a href="?page=wpterm&wptermtab=about" class="nav-tab nav-tab-active"><?php _e( 'About', 'wpterm' ) ?></a>
896 <a href="?page=wpterm&wptermtab=donate" class="nav-tab"><?php _e( 'Donate', 'wpterm' ) ?></a>
897 </h2>
898
899 <div class="card">
900 <h1>WPTerm v<?php echo WPTERM_VERSION ?></h1>
901 <h3>&copy; <?php echo date( 'Y' ) ?> Jerome Bruandet</h3>
902 <strong><?php _e('From the same author:', 'wpterm' ) ?></strong>
903 <ul>
904 <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>
905 <li><a href="https://wordpress.org/plugins/ninjascanner/">NinjaScanner</a>: <?php _e('A lightweight, fast and powerful antivirus scanner for WordPress.', 'wpterm' ) ?></li>
906 <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>
907 </ul>
908 <br />
909 <br />
910 <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>
911 <input id="wpterm-license-button" type="button" class="button-secondary" value="<?php _e('View license', 'wpterm' ) ?>" onClick="show_license();" />
912 <br />&nbsp;
913 </div>
914 </div>
915 <?php
916 }
917
918 /* ================================================================== */
919
920 function wpterm_menu_donate() {
921
922 // Donate menu:
923
924 ?>
925 <div class="wrap">
926 <h1><?php _e('Donate', 'wpterm' ) ?></h1>
927
928 <h2 class="nav-tab-wrapper wp-clearfix">
929 <a href="?page=wpterm&wptermtab=terminal" class="nav-tab"><?php _e( 'Terminal', 'wpterm' ) ?></a>
930 <a href="?page=wpterm&wptermtab=settings" class="nav-tab"><?php _e( 'Settings', 'wpterm' ) ?></a>
931 <a href="?page=wpterm&wptermtab=about" class="nav-tab"><?php _e( 'About', 'wpterm' ) ?></a>
932 <a href="?page=wpterm&wptermtab=donate" class="nav-tab nav-tab-active"><?php _e( 'Donate', 'wpterm' ) ?></a>
933 </h2>
934
935 <div class="card">
936 <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>
937 <hr />
938 <h3><?php _e('PayPal donation', 'wpterm' ) ?></h3>
939 <br />
940 <form name="_xclick" action="https://www.paypal.com/cgi-bin/webscr" method="post">
941 <input type="hidden" name="cmd" value="_xclick" />
942 <input type="hidden" name="business" value="wordpress<?php echo '@' ?>bruandet<?php echo '.' ?>net" />
943 <input type="hidden" name="item_name" value="WPTerm donation" />
944 <input type="hidden" name="currency_code" value="USD" />
945 <label><strong><?php _e('Amount: USD', 'wpterm' ) ?></strong> <input type="number" name="amount" value="5" min="1" /></label>
946 <p>
947 <input type="image" src="<?php echo plugins_url() ?>/wpterm/images/pp.png" border="0" name="submit" />
948 </form>
949 <hr />
950 <h3><?php _e('Bitcoin donation', 'wpterm' ) ?></h3>
951 <br />
952 <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>
953 <br />&nbsp;
954 <hr />
955 <h3><?php _e('Rate it', 'wpterm' ) ?></h3>
956 <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>
957 <br />&nbsp;
958 <hr />
959 <p><?php _e('Thanks!', 'wpterm' ) ?></p>
960 </div>
961 </div>
962 <?php
963 }
964
965
966 /* ================================================================== */
967
968 add_action( 'wp_ajax_wptermajax', 'wptermajax_callback' );
969
970 function wptermajax_callback() {
971
972 // The terminal AJAX callback function:
973
974 if (! current_user_can( 'activate_plugins' ) ) { wp_die(0); }
975
976 // Check AJAX security nonce:
977 if ( check_ajax_referer( 'wpterm_menu_terminal', 'wpterm_ajax_nonce', false ) ) {
978
979 // Path to return in case of fatal error:
980 $if_error = htmlspecialchars( rtrim( ABSPATH, '/' ) ) . '::';
981
982 // If the password protection is enabled, check the password:
983 if (! wpterm_is_allowed( 'ajax' ) ) {
984 echo $if_error . __( 'WPTerm: error, your password has expired. Reload this page to renew it.', 'wpterm');
985 wp_die();
986 }
987
988 if ( empty( $_POST['cmd'] ) || empty( $_POST['cwd'] ) || empty( $_POST['exec'] ) || empty( $_POST['abs'] ) ) {
989 echo $if_error . __( 'WPTerm error: missing command, path, function or abspath', 'wpterm' );
990 wp_die();
991 }
992 // Make sure the max number of lines to returned to WPTerm
993 // is a digit, otherwise set it to 512, its default value:
994 if ( empty( $_POST['scrollback'] ) || ! ctype_digit( $_POST['scrollback'] ) ) {
995 $scrollback = 512;
996 } else {
997 $scrollback = (int)$_POST['scrollback'];
998 }
999 // We don't want WordPress to escape strings with slashes:
1000 $cmd = stripslashes( trim( $_POST['cmd'] ) );
1001 $cwd = stripslashes( trim( $_POST['cwd'] ) );
1002 $abs = stripslashes( trim( $_POST['abs'] ) );
1003 // Set the ABSPATH variable, go to the current working directory,
1004 // run the command, redirect STDERR to STDOUT and return the current
1005 // working directory (it may have been changed e.g., `cd /foo/bar`):
1006 $command = sprintf( "ABSPATH=%s;cd %s;%s 2>&1;echo [-{-`pwd`-}-]", $abs, $cwd, $cmd );
1007
1008 // Run the command:
1009 list( $res, $ret_var ) = @run_command( $command, trim( $_POST['exec'] ) );
1010
1011 // Split the PWD and the data returned by the command:
1012 if ( preg_match( '`^(.+)?\[-{-(/.*?)-}-\]`s', $res, $match ) ) {
1013 // Turn the string into an array...
1014 $res_array = explode( "\n", $match[1] );
1015 // ...keep only the last $_POST['scrollback'] lines and re-create the string...
1016 $res_str = implode( "\n", array_slice( $res_array, -$_POST['scrollback'] ) );
1017 // ...and return it to WPTerm terminal:
1018 echo rtrim( $match[2] . '::' . $res_str );
1019 } else {
1020 if (! empty( $ret_var ) ) {
1021 echo $if_error . sprintf( __( 'WPTerm: error %s', 'wpterm' ), (int) $ret_var );
1022 } else {
1023 echo $if_error . __( 'WPTerm: unknown error. Are you allowed to run PHP program execution functions?', 'wpterm' );
1024 }
1025 }
1026 } else {
1027 echo '/::' . __( 'WPTerm: error, security nonces do not match. Try to reload this page to renew them.', 'wpterm');
1028 }
1029 wp_die();
1030
1031 }
1032
1033 /* ================================================================== */
1034
1035 function run_command( $command, $function ) {
1036
1037 $ret_var = '';
1038 $res = '';
1039
1040 // Select which method to use to run the command:
1041
1042 if ( $function == 'shell_exec' || $function == 'backtick' ) {
1043 $res = shell_exec( $command );
1044
1045 } elseif ( $function == 'system' ) {
1046 ob_start();
1047 system( $command, $ret_var );
1048 $res = ob_get_contents();
1049 ob_end_clean();
1050
1051 } elseif ( $function == 'passthru' ) {
1052 ob_start();
1053 passthru( $command, $ret_var );
1054 $res = ob_get_contents();
1055 ob_end_clean();
1056
1057 } elseif ( $function == 'popen' ) {
1058 if ( ( $handle = popen( $command , 'r' ) ) !== false ) {
1059 while (! feof( $handle ) ) {
1060 $res .= fgets( $handle );
1061 }
1062 pclose( $handle );
1063 }
1064
1065 } else {
1066 if ( exec( $command, $res, $ret_var ) ) {
1067 $res = implode( "\n", $res );
1068 }
1069 }
1070
1071 return array( $res, $ret_var );
1072
1073 }
1074
1075 /* ================================================================== */
1076
1077 function wpterm_is_allowed( $is_ajax = null ) {
1078
1079 // Check if a password was set:
1080 if (! defined( 'WPTERM_PASSWORD' ) ) {
1081 // No, let it go:
1082 return true;
1083 }
1084
1085 // Check if the user session exists:
1086 if ( empty( $_SESSION['wptermpwd'] ) ) {
1087 // Return if this is an AJAX call (a warning
1088 // will be displayed from the terminal prompt):
1089 if ( isset( $is_ajax ) ) { return false; }
1090 // Display the password form:
1091 if( ! wpterm_password_prompt(1) ) {
1092 return false;
1093 }
1094 }
1095 // Check if passwords match:
1096 if ( $_SESSION['wptermpwd'] != WPTERM_PASSWORD ) {
1097 // Password does not match, clear it:
1098 unset( $_SESSION['wptermpwd'] );
1099 if ( isset( $is_ajax ) ) { return false; }
1100 // Display the password form:
1101 if (! wpterm_password_prompt(2) ) {
1102 return false;
1103 }
1104 }
1105
1106 // Okay, go ahead!
1107 return true;
1108
1109 }
1110
1111 /* ================================================================== */
1112
1113 function wpterm_password_prompt( $err = 0 ) {
1114
1115 // Display the password form:
1116
1117 // Password form submitted?
1118 if ( isset( $_POST['wptermpwd'] ) ) {
1119 // Verify security nonce:
1120 if ( empty( $_POST['wptermnonce'] ) || ! wp_verify_nonce( $_POST['wptermnonce'], 'wpterm_password' ) ) {
1121 wp_nonce_ays( 'wpterm_password' );
1122 }
1123 // Verify password:
1124 if ( sha1( $_POST['wptermpwd'] ) === WPTERM_PASSWORD ) {
1125 $_SESSION['wptermpwd'] = sha1( $_POST['wptermpwd'] );
1126 return true;
1127 } else {
1128 $err = 3;
1129 }
1130 }
1131
1132 if ( $err == 3 ) {
1133 ?>
1134 <div class="error notice is-dismissible"><p><?php _e( 'Wrong password, please try again.', 'wpterm' ) ?></p></div>
1135 <?php
1136 } else {
1137 ?>
1138 <div class="notice-info notice is-dismissible"><p><?php printf( __( 'A password is required to access WPTerm (#%s).', 'wpterm' ), (int) $err ) ?></p></div>
1139 <?php
1140 }
1141 ?>
1142
1143 <div class="wrap">
1144 <h1>WPTerm</h1>
1145
1146 <h2 class="nav-tab-wrapper wp-clearfix" style="cursor:not-allowed">
1147 <a class="nav-tab"><?php _e( 'Terminal', 'wpterm' ) ?></a>
1148 <a class="nav-tab"><?php _e( 'Settings', 'wpterm' ) ?></a>
1149 <a class="nav-tab"><?php _e( 'About', 'wpterm' ) ?></a>
1150 <a class="nav-tab"><?php _e( 'Donate', 'wpterm' ) ?></a>
1151 </h2>
1152
1153 <div class="card">
1154
1155 <form method="post">
1156 <h3><?php _e( 'Enter your WPTerm password:', 'wpterm' ) ?></h3>
1157 <p><input class="input" type="password" name="wptermpwd" placeholder="Password" autofocus /></p>
1158 <p><input type="submit" class="button-secondary" /></p>
1159 <?php wp_nonce_field('wpterm_password', 'wptermnonce', 0); ?>
1160 </form>
1161
1162 </div>
1163 </div>
1164 <?php
1165
1166 return false;
1167
1168 }
1169
1170 /* ================================================================== */
1171 // EOF
1172