PluginProbe
WPTerm / 1.1.3
WPTerm v1.1.3
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.3, at wpterm.php

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