PluginProbe
MainWP Key Maker / 1.0
MainWP Key Maker v1.0
trunk 0.1 0.2 1.0 1.1 1.2 1.3
mainwp-key-maker / mainwp-key-maker.php

mainwp-key-maker.php in MainWP Key Maker 1.0, at mainwp-key-maker.php

629 lines 19.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /*
3 Plugin Name: MainWP Key Maker
4 Plugin URI: https://mainwp.com/
5 Description: Easily convert a form into a "key" to use with the MainWP Bulk Settings Manager Extension
6 Author: MainWP
7 Author URI: https://mainwp.com
8 Version: 1.0
9 */
10
11 // If we made redirection in this session
12 $mainwp_key_maker_is_redirect = false;
13 // Store current user session id
14 $mainwp_key_maker_session_id = "";
15
16
17 if ( ! function_exists( "mainwp_key_maker_get_session_id" ) ) {
18 /**
19 * Get current user session id
20 */
21 function mainwp_key_maker_get_session_id() {
22 global $mainwp_key_maker_session_id;
23
24 // We use global so this happen only once
25 if (empty($mainwp_key_maker_session_id)) {
26 if ( defined( "AUTH_COOKIE" ) && isset( $_COOKIE[ AUTH_COOKIE ] )) {
27 // Different users can share one account - so use session id
28 $cookie_elements = explode( '|', $_COOKIE[ AUTH_COOKIE ] );
29 if ( isset( $cookie_elements[2] ) ) {
30 $mainwp_key_maker_session_id = substr( (string) $cookie_elements[2], 0, 30 );
31 }
32 } else if ( defined( "SECURE_AUTH_COOKIE" ) && isset( $_COOKIE[ SECURE_AUTH_COOKIE ] )) {
33 // Different users can share one account - so use session id
34 $cookie_elements = explode( '|', $_COOKIE[ SECURE_AUTH_COOKIE ] );
35 if ( isset( $cookie_elements[2] ) ) {
36 $mainwp_key_maker_session_id = substr( (string) $cookie_elements[2], 0, 30 );
37 }
38 }
39 }
40 }
41 }
42
43
44 if ( ! function_exists( "mainwp_key_maker_store_request" ) ) {
45 /**
46 * Store $_GET/$_POST inside transient for further use
47 */
48 function mainwp_key_maker_store_request() {
49 global $mainwp_key_maker_session_id, $mainwp_key_maker_is_redirect;
50
51 mainwp_key_maker_get_session_id();
52
53 // Only for logged
54 if ( ! empty( $mainwp_key_maker_session_id ) ) {
55 // Skip heartbleeed WordPress action
56 if ( isset( $_REQUEST['action'] ) && $_REQUEST['action'] == 'heartbeat' && isset( $_REQUEST['screen_id'] ) ) {
57 return;
58 }
59
60 $previous_data = get_transient( 'mainwp_eir_' . $mainwp_key_maker_session_id );
61 if ( $previous_data === false ) {
62 $previous_data = array();
63 }
64
65 $datas = array();
66
67 // Store values in transient so we have access to them in next page
68 $datas['post'] = $_POST;
69 $datas['get'] = $_GET;
70 $datas['url'] = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'];
71 $datas['time'] = time();
72
73 $previous_data[] = $datas;
74
75 set_transient( 'mainwp_eir_' . $mainwp_key_maker_session_id, $previous_data, 90 );
76 $mainwp_key_maker_is_redirect = true;
77 }
78 }
79 }
80
81 // We add additional functionality to wp_redirect and wp_verify_nonce for administrators
82 if ( ! function_exists( 'wp_redirect' ) ) :
83
84 /**
85 * Redirects to another page.
86 * Additionally, stores $_GET, $_POST and url in transient
87 *
88 * @since 1.5.1
89 *
90 * @global bool $is_IIS
91 *
92 * @param string $location The path to redirect to.
93 * @param int $status Status code to use.
94 *
95 * @return bool False if $location is not provided, true otherwise.
96 */
97 function wp_redirect( $location, $status = 302 ) {
98 global $is_IIS;
99
100 /**
101 * Filter the redirect location.
102 *
103 * @since 2.1.0
104 *
105 * @param string $location The path to redirect to.
106 * @param int $status Status code to use.
107 */
108 $location = apply_filters( 'wp_redirect', $location, $status );
109
110 /**
111 * Filter the redirect status code.
112 *
113 * @since 2.3.0
114 *
115 * @param int $status Status code to use.
116 * @param string $location The path to redirect to.
117 */
118 $status = apply_filters( 'wp_redirect_status', $status, $location );
119
120 if ( ! $location ) {
121 return false;
122 }
123
124 $location = wp_sanitize_redirect( $location );
125
126 if ( ! $is_IIS && PHP_SAPI != 'cgi-fcgi' ) {
127 status_header( $status );
128 } // This causes problems on IIS and some FastCGI setups
129
130 mainwp_key_maker_store_request();
131
132 header( "Location: $location", true, $status );
133
134 return true;
135 }
136 endif;
137
138 if ( ! function_exists( 'wp_verify_nonce' ) ) :
139 /**
140 * Verify that correct nonce was used with time limit.
141 * Additionally stores name of nonce action in transient
142 *
143 * The user is given an amount of time to use the token, so therefore, since the
144 * UID and $action remain the same, the independent variable is the time.
145 *
146 * @since 2.0.3
147 *
148 * @param string $nonce Nonce that was used in the form to verify
149 * @param string|int $action Should give context to what is taking place and be the same when nonce was created.
150 *
151 * @return false|int False if the nonce is invalid, 1 if the nonce is valid and generated between
152 * 0-12 hours ago, 2 if the nonce is valid and generated between 12-24 hours ago.
153 */
154 function wp_verify_nonce( $nonce, $action = - 1 ) {
155 global $mainwp_key_maker_session_id;
156
157 if ( ! empty( $mainwp_key_maker_session_id ) ) {
158 $key_maker = get_transient( 'mainwp_ein_' . $mainwp_key_maker_session_id );
159 if ( $key_maker === false ) {
160 $key_maker = array();
161 }
162
163 $key_maker[ trim( $nonce ) ] = $action;
164 set_transient( 'mainwp_ein_' . $mainwp_key_maker_session_id, $key_maker );
165 }
166
167 $nonce = (string) $nonce;
168 $user = wp_get_current_user();
169 $uid = (int) $user->ID;
170 if ( ! $uid ) {
171 /**
172 * Filter whether the user who generated the nonce is logged out.
173 *
174 * @since 3.5.0
175 *
176 * @param int $uid ID of the nonce-owning user.
177 * @param string $action The nonce action.
178 */
179 $uid = apply_filters( 'nonce_user_logged_out', $uid, $action );
180 }
181
182 if ( empty( $nonce ) ) {
183 return false;
184 }
185
186 $token = wp_get_session_token();
187 $i = wp_nonce_tick();
188
189 // Nonce generated 0-12 hours ago
190 $expected = substr( wp_hash( $i . '|' . $action . '|' . $uid . '|' . $token, 'nonce' ), - 12, 10 );
191 if ( hash_equals( $expected, $nonce ) ) {
192 return 1;
193 }
194
195 // Nonce generated 12-24 hours ago
196 $expected = substr( wp_hash( ( $i - 1 ) . '|' . $action . '|' . $uid . '|' . $token, 'nonce' ), - 12, 10 );
197 if ( hash_equals( $expected, $nonce ) ) {
198 return 2;
199 }
200
201 // Invalid nonce
202 return false;
203 }
204 endif;
205
206 if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
207 // We want to support ajax calls also
208 mainwp_key_maker_store_request();
209 }
210
211 class MainWP_Key_Maker {
212
213 public function __construct() {
214 add_action( 'init', array( $this, 'init' ) );
215 }
216
217 public function init() {
218 mainwp_key_maker_get_session_id();
219
220 if ( ! current_user_can( 'manage_options' ) || ! is_admin() ) {
221 return;
222 }
223
224 global $mainwp_key_maker_is_redirect;
225
226 // Display redirect data on next page
227 if ( $mainwp_key_maker_is_redirect ) {
228 return;
229 }
230
231 // Skip Ajax
232 if ( defined( 'XMLRPC_REQUEST' ) || defined( 'DOING_AJAX' ) || defined( 'IFRAME_REQUEST' ) ) {
233 return;
234 }
235
236 // Don't process if fatal error
237 $error = error_get_last();
238 if ( ! empty( $error ) && ( $error['type'] & ( E_ERROR | E_USER_ERROR | E_RECOVERABLE_ERROR ) ) ) {
239 return;
240 }
241
242 add_action( 'wp_before_admin_bar_render', array( $this, 'bar_render' ), 999 );
243 add_action( 'admin_footer', array( $this, 'toolbar' ), 999 );
244 }
245
246 /**
247 * Render Key Maker button inside admin bar
248 * Display content using thickbox popup
249 */
250 public function bar_render() {
251 global $wp_admin_bar;
252
253 wp_register_script( 'mainwp-key-maker-colorbox', plugins_url( '/js/jquery.colorbox-min.js', __FILE__ ), array( 'jquery' ) );
254 wp_enqueue_script( 'mainwp-key-maker-colorbox' );
255
256 wp_register_script( 'mainwp-key-maker-zeroclipboard', plugins_url( '/js/ZeroClipboard.min.js', __FILE__ ), array( 'jquery' ) );
257 wp_enqueue_script( 'mainwp-key-maker-zeroclipboard' );
258
259 wp_register_style( 'mainwp-key-maker-colorbox', plugins_url( '/css/colorbox.css', __FILE__ ) );
260 wp_enqueue_style( 'mainwp-key-maker-colorbox' );
261
262 $args = array(
263 'id' => 'mainwp-key-maker-adminbar-node',
264 'title' => __( 'MainWP Key Maker', 'mainwp-key-maker' ),
265 'href' => '#mainwp-key-maker-box'
266 );
267
268 $wp_admin_bar->add_node( $args );
269 ?>
270 <style>
271 #wp-admin-bar-mainwp-key-maker {
272 cursor: pointer;
273 }
274 .mainwp-km-info {
275 margin-top: 1em;
276 padding: .6em;
277 border-left: 4px Solid #7fb100;
278 box-shadow: 0 1px 1px 0 rgba(0,0,0,.1);
279 -webkit-box-shadow: 0 1px 1px 0 rgba(0,0,0,.1);
280 }
281 </style>
282 <script>
283 jQuery(function () {
284 ZeroClipboard.config( { swfPath: "<?php echo plugins_url( '/js/ZeroClipboard.swf', __FILE__ ); ?>" } );
285
286 var client = new ZeroClipboard(jQuery(".mainwp-key-maker-textarea"));
287
288 client.on('ready', function (event) {
289 client.on("copy", function (event) {
290 event.clipboardData.setData("text/plain", event.target.innerHTML);
291 });
292
293 client.on('aftercopy', function (event) {
294 jQuery("#" + event.target.id + "-button").val('<?php _e('Copied to Clipboard!', 'mainwp-key-maker'); ?>');
295 jQuery("#" + event.target.id + "-button").removeClass('button-primary');
296 setInterval(function () {
297 jQuery("#" + event.target.id + "-button").val('<?php _e('Copy to Clipboard', 'mainwp-key-maker'); ?>');
298 jQuery("#" + event.target.id + "-button").addClass('button-primary');
299 }, 3000);
300 });
301 });
302
303 var client2 = new ZeroClipboard(jQuery(".mainwp-key-maker-copy-button"));
304
305 client2.on('ready', function (event) {
306 client2.on('aftercopy', function (event) {
307 event.target.value = '<?php _e('Copied to Clipboard!', 'mainwp-key-maker'); ?>';
308 event.target.classList.remove('button-primary');
309 setInterval(function () {
310 event.target.value = '<?php _e('Copy to Clipboard', 'mainwp-key-maker'); ?>';
311 event.target.classList.add('button-primary');
312 }, 3000);
313 });
314 });
315
316 jQuery("#wp-admin-bar-mainwp-key-maker-adminbar-node a").colorbox({inline: true, width: "1230px"});
317
318 jQuery(".mainwp-key-maker-debug-a").on("click", function () {
319 jQuery("#mainwp-key-maker-debug-" + jQuery(this).attr("ids")).toggle();
320 });
321 });
322 </script>
323
324 <?php
325 }
326
327 /**
328 * Display content for admin bar button
329 */
330 public function toolbar() {
331 global $mainwp_key_maker_session_id;
332
333 // Do we have anything to display?
334 $is_any_info = false;
335 $is_there_pre_request = false;
336 ?>
337 <div style="display:none;">
338 <div id="mainwp-key-maker-box">
339 <span style="float: right;">
340 <a href="https://mainwp.com" target="_blank" title="MainWP"><img style="height: 40px; margin-right: 15px;" src="<?php echo plugins_url('images/logo.png', __FILE__); ?>" alt="MainWP" /></a>
341 </span>
342 <h1><?php _e( 'MainWP Key Maker', 'mainwp-key-maker'); ?></h1>
343 <div style="clear: both;"></div>
344 <?php
345
346 $nonce = get_transient( 'mainwp_ein_' . $mainwp_key_maker_session_id );
347
348 if ( $nonce === false ) {
349 $nonce = array();
350 }
351
352 $previous_datas = get_transient( 'mainwp_eir_' . $mainwp_key_maker_session_id );
353
354 if ( $previous_datas !== false ) {
355 delete_transient( 'mainwp_ein_' . $mainwp_key_maker_session_id );
356 delete_transient( 'mainwp_eir_' . $mainwp_key_maker_session_id );
357 foreach ( $previous_datas as $previous_counter => $previous_data ):
358 if ( ( isset( $previous_data['post'] ) && ! empty( $previous_data['post'] ) ) || ( isset( $previous_data['get'] ) && ! empty( $previous_data['get'] ) ) ):
359 $is_any_info = true;
360 $is_there_pre_request = true;
361 ?>
362 <div style="padding-bottom: 1em; margin-bottom: 1px Solid #000;">
363 <?php
364 if ( $is_there_pre_request ):
365 ?>
366 <div class="mainwp-km-info">
367 <em><?php _e('The "Verify Form Fields and Values" button allows you to tell if the Key will contain the information you want.', 'mainwp-key-maker'); ?></em><br/>
368 <em><?php _e('If it does not, you may need to submit the form in order for the Key Maker to be able to correctly gather the form fields and values.', 'mainwp-key-maker'); ?></em>
369 </div>
370 <?php
371 endif;
372 ?>
373 <p>
374 <h2 style="margin-bottom: .3em;"><?php _e( 'Post-submission Request', 'mainwp-key-maker' ); ?></h2>
375 <em>( <?php echo date_i18n( "d-m-Y H:i:s", $previous_data['time'] ); ?> )</em>
376 <?php echo( isset( $previous_data['url'] ) ? esc_html( $previous_data['url'] ) : __( 'Unknown url', 'mainwp-key-maker' ) ); ?>
377 <span style="float: right; margin-right: 1.5em;">
378 <a href="#"
379 class="mainwp-key-maker-debug-a button"
380 style="text-decoration: none;"
381 ids="<?php echo esc_attr( $previous_counter ); ?>"><?php _e( 'Verify Form Fields and Values', 'mainwp-key-maker' ); ?>
382 </a>
383 <input type="submit"
384 id="mainwp-key-maker-textarea-previous-<?php echo esc_attr( $previous_counter ); ?>-button"
385 data-clipboard-target="mainwp-key-maker-textarea-previous-<?php echo esc_attr( $previous_counter ); ?>"
386 class="mainwp-key-maker-copy-button button button-primary"
387 value="<?php _e( 'Copy to Clipboard', 'mainwp-key-maker' ); ?>">
388 </span>
389 </p>
390 <div id="mainwp-key-maker-debug-<?php echo esc_attr( $previous_counter ); ?>"
391 style="display:none; width: 1170px !important; margin-bottom: 1em;"
392 class="postbox">
393 <div class="inside">
394 <pre><?php echo $this->custom_print_r( $previous_data, $nonce ); ?></pre>
395 </div>
396 </div>
397
398 <textarea rows="12"
399 cols="90"
400 style="width: 1170px;"
401 class="mainwp-key-maker-textarea"
402 id="mainwp-key-maker-textarea-previous-<?php echo esc_attr( $previous_counter ); ?>"
403 readonly><?php echo esc_textarea( $this->parse_data( $previous_data, $nonce ) ); ?></textarea>
404 </div>
405 <?php
406 endif;
407 endforeach;
408
409
410 }
411
412 $current_data = array();
413 $current_data['post'] = $_POST;
414 $current_data['get'] = $_GET;
415 $current_data['url'] = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'];
416 $current_data['time'] = time();
417 ?>
418 <div style="padding-bottom: 1em; margin-bottom: 1px Solid #000;">
419 <?php
420 if (!empty($current_data['post']) || !empty($current_data['get'])):
421 $is_any_info = true;
422 ?>
423 <?php
424 if ( ! $is_there_pre_request ):
425 ?>
426 <div class="mainwp-km-info">
427 <em><?php _e('The "Verify Form Fields and Values" button allows you to tell if the Key will contain the information you want.', 'mainwp-key-maker'); ?></em><br/>
428 <em><?php _e('If it does not, you may need to submit the form in order for the Key Maker to be able to correctly gather the form fields and values.', 'mainwp-key-maker'); ?></em>
429 </div>
430 <?php
431 endif;
432 ?>
433 <p>
434 <h2 style="margin-bottom: .3em;"><?php _e('Pre-submission Request', 'mainwp-key-maker'); ?></h2>
435 <em>( <?php echo date_i18n("d-m-Y H:i:s", $current_data['time']); ?> )</em>
436 <?php echo esc_html($current_data['url']); ?>
437 <span style="float: right; margin-right: 1.5em;">
438 <a
439 href="#"
440 class="mainwp-key-maker-debug-a button"
441 ids="current"
442 style="text-decoration: none;"><?php _e('Verify Form Fields and Values', 'mainwp-key-maker'); ?>
443 </a>
444 <input type="submit"
445 id="mainwp-key-maker-textarea-button"
446 data-clipboard-target="mainwp-key-maker-textarea"
447 class="mainwp-key-maker-copy-button button button-primary"
448 value="<?php _e('Copy to clipboard', 'mainwp-key-maker'); ?>">
449 </span>
450 </p>
451
452 <div id="mainwp-key-maker-debug-current"
453 style="display:none; width: 1170px !important; margin-bottom: 1em;"
454 class="postbox">
455 <div class="inside">
456 <pre><?php echo $this->custom_print_r($current_data, $nonce); ?></pre>
457 </div>
458 </div>
459
460
461 <textarea rows="12"
462 cols="90"
463 style="width: 1170px;"
464 class="mainwp-key-maker-textarea"
465 id="mainwp-key-maker-textarea"
466 readonly><?php echo esc_textarea($this->parse_data($current_data, $nonce)); ?></textarea>
467 <?php
468 endif;
469
470 if ( ! $is_any_info ):
471 ?>
472 <div class="mainwp-km-info"><?php _e( 'No form detected. You may have to submit the form before Key Maker is able to find the form and make the Key.', 'mainwp-key-maker' ); ?></div>
473 <?php
474 endif;
475 ?>
476 </div>
477 </div>
478 </div>
479 <?php
480 }
481
482 /**
483 * @param $data
484 * @param $nonce
485 *
486 * Print $_GET and $_POST using print_r with XSS protection
487 *
488 * @return string
489 */
490 public function custom_print_r( $data, $nonce ) {
491 return esc_html( print_r( $this->check_nonces( $data, $nonce ), true ) );
492 }
493
494 /**
495 * @param $data
496 * @param $nonce
497 *
498 * Recursive check if in array, nonce field exist
499 *
500 * @return array
501 */
502 public function check_nonces( $data, $nonce ) {
503 $new = array();
504 foreach ( $data as $key => $val ) {
505 if ( is_array( $val ) ) {
506 $new[ $key ] = $this->check_nonces( $val, $nonce );
507 } else {
508 $val = trim( $val );
509 if ( isset( $nonce[ $val ] ) ) {
510 $new[ $key ] = __( 'NONCE FIELD', 'mainwp-key-maker' ) . ' - ' . $nonce[ $val ];
511 } else {
512 $new[ $key ] = $val;
513 }
514 }
515 }
516
517 return $new;
518 }
519
520 /**
521 * @param $data
522 * @param $nonce
523 *
524 * Parse datas in format readable for Skeleton Key
525 *
526 * @return string
527 */
528 public function parse_data( $data, $nonce ) {
529 $out = array();
530 if ( isset( $data['post'] ) ) {
531 foreach ( $this->flatten_array( $data['post'] ) as $key => $val ) {
532 $array = array();
533 $val = trim( $val );
534
535 if ( isset( $nonce[ $val ] ) ) {
536 $array['field_type'] = 'nonce_field';
537 $array['nonce_field_name'] = $nonce[ $val ];
538 $array['nonce_field_arg'] = $key;
539 } else {
540 if ( strpos( $val, "\n" ) !== false || strpos( $val, "\r" ) !== false ) {
541 $array['field_type'] = 'textarea_field';
542 $array['textarea_field_description'] = $val;
543 $array['textarea_field_name'] = $key;
544 $array['textarea_field_value'] = $val;
545 $array['textarea_field_type'] = 'post';
546 } else {
547 $array['field_type'] = 'text_field';
548 $array['text_field_description'] = $val;
549 $array['text_field_name'] = $key;
550 $array['text_field_value'] = $val;
551 $array['text_field_type'] = 'post';
552 }
553 }
554
555 $out[] = http_build_query( $array );
556 }
557 }
558
559 if ( isset( $data['get'] ) ) {
560 foreach ( $this->flatten_array( $data['get'] ) as $key => $val ) {
561 $array = array();
562 $val = trim( $val );
563
564 if ( isset( $nonce[ $val ] ) ) {
565 $array['field_type'] = 'nonce_field';
566 $array['nonce_field_name'] = $nonce[ $val ];
567 $array['nonce_field_arg'] = $key;
568 } else {
569 $array['field_type'] = 'text_field';
570 $array['text_field_description'] = $val;
571 $array['text_field_name'] = $key;
572 $array['text_field_value'] = $val;
573 $array['text_field_type'] = 'get';
574 }
575
576 $out[] = http_build_query( $array );
577 }
578 }
579
580 $url = "";
581 if ( isset( $data['url'] ) ) {
582 $url = parse_url( $data['url'] );
583 $url = ( isset( $url['path'] ) ? $url['path'] : '' ) . ( isset( $url['query'] ) ? '?' . $url['query'] : '' );
584 }
585
586 $array = array();
587 $array['field_type'] = 'settings_field';
588 $array['settings_field_name'] = __( 'Imported', 'mainwp-key-maker' ) . ' ' . current_time( "d-m-Y H:i:s" );
589 $array['settings_field_url'] = $url;
590
591 $content = http_build_query( $array ) . '&' . implode( '&', $out );
592 $hash = sha1( $content );
593
594 $return = "-----BEGIN BULK SETTINGS MANAGER KEY-----\r\n";
595 $return .= base64_encode( $hash . '|' . $content );
596 $return .= "\r\n-----END BULK SETTINGS MANAGER KEY-----\r\n";
597
598 return $return;
599 }
600
601 /**
602 * @param $array
603 * @param string $previous
604 *
605 * Convert multidimensional array into single dimensional array
606 * Something like http[like][array][structure]
607 *
608 * @return array
609 */
610 public function flatten_array( $array, $previous = "" ) {
611 $out = array();
612 foreach ( $array as $key => $val ) {
613 if ( is_array( $val ) ) {
614 $out = array_merge( $this->flatten_array( $val, ( $previous == "" ? $key : $previous . '[' . $key . ']' ) ), $out );
615 } else {
616 if ( $previous == "" ) {
617 $out[ $key ] = $val;
618 } else {
619 $out[ $previous . '[' . $key . ']' ] = $val;
620 }
621 }
622 }
623
624 return $out;
625 }
626 }
627
628 $mainWP = new MainWP_Key_Maker();
629