128 * @since 4.9.0 Added the `$exclusions` parameter. |
128 * @since 4.9.0 Added the `$exclusions` parameter. |
129 * |
129 * |
130 * @param string $folder Optional. Full path to folder. Default empty. |
130 * @param string $folder Optional. Full path to folder. Default empty. |
131 * @param int $levels Optional. Levels of folders to follow, Default 100 (PHP Loop limit). |
131 * @param int $levels Optional. Levels of folders to follow, Default 100 (PHP Loop limit). |
132 * @param string[] $exclusions Optional. List of folders and files to skip. |
132 * @param string[] $exclusions Optional. List of folders and files to skip. |
133 * @return bool|string[] False on failure, else array of files. |
133 * @return string[]|false Array of files on success, false on failure. |
134 */ |
134 */ |
135 function list_files( $folder = '', $levels = 100, $exclusions = array() ) { |
135 function list_files( $folder = '', $levels = 100, $exclusions = array() ) { |
136 if ( empty( $folder ) ) { |
136 if ( empty( $folder ) ) { |
137 return false; |
137 return false; |
138 } |
138 } |
367 */ |
368 */ |
368 function wp_edit_theme_plugin_file( $args ) { |
369 function wp_edit_theme_plugin_file( $args ) { |
369 if ( empty( $args['file'] ) ) { |
370 if ( empty( $args['file'] ) ) { |
370 return new WP_Error( 'missing_file' ); |
371 return new WP_Error( 'missing_file' ); |
371 } |
372 } |
372 $file = $args['file']; |
373 |
373 if ( 0 !== validate_file( $file ) ) { |
374 if ( 0 !== validate_file( $args['file'] ) ) { |
374 return new WP_Error( 'bad_file' ); |
375 return new WP_Error( 'bad_file' ); |
375 } |
376 } |
376 |
377 |
377 if ( ! isset( $args['newcontent'] ) ) { |
378 if ( ! isset( $args['newcontent'] ) ) { |
378 return new WP_Error( 'missing_content' ); |
379 return new WP_Error( 'missing_content' ); |
379 } |
380 } |
380 $content = $args['newcontent']; |
|
381 |
381 |
382 if ( ! isset( $args['nonce'] ) ) { |
382 if ( ! isset( $args['nonce'] ) ) { |
383 return new WP_Error( 'missing_nonce' ); |
383 return new WP_Error( 'missing_nonce' ); |
384 } |
384 } |
|
385 |
|
386 $file = $args['file']; |
|
387 $content = $args['newcontent']; |
385 |
388 |
386 $plugin = null; |
389 $plugin = null; |
387 $theme = null; |
390 $theme = null; |
388 $real_file = null; |
391 $real_file = null; |
|
392 |
389 if ( ! empty( $args['plugin'] ) ) { |
393 if ( ! empty( $args['plugin'] ) ) { |
390 $plugin = $args['plugin']; |
394 $plugin = $args['plugin']; |
391 |
395 |
392 if ( ! current_user_can( 'edit_plugins' ) ) { |
396 if ( ! current_user_can( 'edit_plugins' ) ) { |
393 return new WP_Error( 'unauthorized', __( 'Sorry, you are not allowed to edit plugins for this site.' ) ); |
397 return new WP_Error( 'unauthorized', __( 'Sorry, you are not allowed to edit plugins for this site.' ) ); |
487 } |
492 } |
488 } |
493 } |
489 |
494 |
490 $previous_content = file_get_contents( $real_file ); |
495 $previous_content = file_get_contents( $real_file ); |
491 |
496 |
492 if ( ! is_writeable( $real_file ) ) { |
497 if ( ! is_writable( $real_file ) ) { |
493 return new WP_Error( 'file_not_writable' ); |
498 return new WP_Error( 'file_not_writable' ); |
494 } |
499 } |
495 |
500 |
496 $f = fopen( $real_file, 'w+' ); |
501 $f = fopen( $real_file, 'w+' ); |
|
502 |
497 if ( false === $f ) { |
503 if ( false === $f ) { |
498 return new WP_Error( 'file_not_writable' ); |
504 return new WP_Error( 'file_not_writable' ); |
499 } |
505 } |
500 |
506 |
501 $written = fwrite( $f, $content ); |
507 $written = fwrite( $f, $content ); |
502 fclose( $f ); |
508 fclose( $f ); |
|
509 |
503 if ( false === $written ) { |
510 if ( false === $written ) { |
504 return new WP_Error( 'unable_to_write', __( 'Unable to write to file.' ) ); |
511 return new WP_Error( 'unable_to_write', __( 'Unable to write to file.' ) ); |
505 } |
512 } |
506 |
513 |
507 wp_opcache_invalidate( $real_file, true ); |
514 wp_opcache_invalidate( $real_file, true ); |
508 |
515 |
509 if ( $is_active && 'php' === $extension ) { |
516 if ( $is_active && 'php' === $extension ) { |
510 |
517 |
511 $scrape_key = md5( rand() ); |
518 $scrape_key = md5( rand() ); |
512 $transient = 'scrape_key_' . $scrape_key; |
519 $transient = 'scrape_key_' . $scrape_key; |
513 $scrape_nonce = strval( rand() ); |
520 $scrape_nonce = (string) rand(); |
514 // It shouldn't take more than 60 seconds to make the two loopback requests. |
521 // It shouldn't take more than 60 seconds to make the two loopback requests. |
515 set_transient( $transient, $scrape_nonce, 60 ); |
522 set_transient( $transient, $scrape_nonce, 60 ); |
516 |
523 |
517 $cookies = wp_unslash( $_COOKIE ); |
524 $cookies = wp_unslash( $_COOKIE ); |
518 $scrape_params = array( |
525 $scrape_params = array( |
573 $json_parse_failure = array( |
580 $json_parse_failure = array( |
574 'code' => 'json_parse_error', |
581 'code' => 'json_parse_error', |
575 ); |
582 ); |
576 |
583 |
577 $result = null; |
584 $result = null; |
|
585 |
578 if ( false === $scrape_result_position ) { |
586 if ( false === $scrape_result_position ) { |
579 $result = $loopback_request_failure; |
587 $result = $loopback_request_failure; |
580 } else { |
588 } else { |
581 $error_output = substr( $body, $scrape_result_position + strlen( $needle_start ) ); |
589 $error_output = substr( $body, $scrape_result_position + strlen( $needle_start ) ); |
582 $error_output = substr( $error_output, 0, strpos( $error_output, $needle_end ) ); |
590 $error_output = substr( $error_output, 0, strpos( $error_output, $needle_end ) ); |
607 } |
615 } |
608 |
616 |
609 delete_transient( $transient ); |
617 delete_transient( $transient ); |
610 |
618 |
611 if ( true !== $result ) { |
619 if ( true !== $result ) { |
612 |
|
613 // Roll-back file change. |
620 // Roll-back file change. |
614 file_put_contents( $real_file, $previous_content ); |
621 file_put_contents( $real_file, $previous_content ); |
615 wp_opcache_invalidate( $real_file, true ); |
622 wp_opcache_invalidate( $real_file, true ); |
616 |
623 |
617 if ( ! isset( $result['message'] ) ) { |
624 if ( ! isset( $result['message'] ) ) { |
618 $message = __( 'Something went wrong.' ); |
625 $message = __( 'Something went wrong.' ); |
619 } else { |
626 } else { |
620 $message = $result['message']; |
627 $message = $result['message']; |
621 unset( $result['message'] ); |
628 unset( $result['message'] ); |
622 } |
629 } |
|
630 |
623 return new WP_Error( 'php_error', $message, $result ); |
631 return new WP_Error( 'php_error', $message, $result ); |
624 } |
632 } |
625 } |
633 } |
626 |
634 |
627 if ( $theme instanceof WP_Theme ) { |
635 if ( $theme instanceof WP_Theme ) { |
669 $temp_filename .= '-' . wp_generate_password( 6, false ); |
677 $temp_filename .= '-' . wp_generate_password( 6, false ); |
670 $temp_filename .= '.tmp'; |
678 $temp_filename .= '.tmp'; |
671 $temp_filename = $dir . wp_unique_filename( $dir, $temp_filename ); |
679 $temp_filename = $dir . wp_unique_filename( $dir, $temp_filename ); |
672 |
680 |
673 $fp = @fopen( $temp_filename, 'x' ); |
681 $fp = @fopen( $temp_filename, 'x' ); |
|
682 |
674 if ( ! $fp && is_writable( $dir ) && file_exists( $temp_filename ) ) { |
683 if ( ! $fp && is_writable( $dir ) && file_exists( $temp_filename ) ) { |
675 return wp_tempnam( $filename, $dir ); |
684 return wp_tempnam( $filename, $dir ); |
676 } |
685 } |
|
686 |
677 if ( $fp ) { |
687 if ( $fp ) { |
678 fclose( $fp ); |
688 fclose( $fp ); |
679 } |
689 } |
680 |
690 |
681 return $temp_filename; |
691 return $temp_filename; |
723 * |
733 * |
724 * @see wp_handle_upload_error |
734 * @see wp_handle_upload_error |
725 * |
735 * |
726 * @param string[] $file Reference to a single element of `$_FILES`. |
736 * @param string[] $file Reference to a single element of `$_FILES`. |
727 * Call the function once for each uploaded file. |
737 * Call the function once for each uploaded file. |
728 * @param string[]|false $overrides An associative array of names => values |
738 * @param array|false $overrides { |
729 * to override default variables. Default false. |
739 * An array of override parameters for this file, or boolean false if none are provided. |
|
740 * |
|
741 * @type callable $upload_error_handler Function to call when there is an error during the upload process. |
|
742 * @see wp_handle_upload_error(). |
|
743 * @type callable $unique_filename_callback Function to call when determining a unique file name for the file. |
|
744 * @see wp_unique_filename(). |
|
745 * @type string[] $upload_error_strings The strings that describe the error indicated in |
|
746 * `$_FILES[{form field}]['error']`. |
|
747 * @type bool $test_form Whether to test that the `$_POST['action']` parameter is as expected. |
|
748 * @type bool $test_size Whether to test that the file size is greater than zero bytes. |
|
749 * @type bool $test_type Whether to test that the mime type of the file is as expected. |
|
750 * @type string[] $mimes Array of allowed mime types keyed by their file extension regex. |
|
751 * } |
730 * @param string $time Time formatted in 'yyyy/mm'. |
752 * @param string $time Time formatted in 'yyyy/mm'. |
731 * @param string $action Expected value for `$_POST['action']`. |
753 * @param string $action Expected value for `$_POST['action']`. |
732 * @return string[] On success, returns an associative array of file attributes. |
754 * @return string[] On success, returns an associative array of file attributes. |
733 * On failure, returns `$overrides['upload_error_handler']( &$file, $message )` |
755 * On failure, returns `$overrides['upload_error_handler']( &$file, $message )` |
734 * or `array( 'error' => $message )`. |
756 * or `array( 'error' => $message )`. |
744 /** |
766 /** |
745 * Filters the data for a file before it is uploaded to WordPress. |
767 * Filters the data for a file before it is uploaded to WordPress. |
746 * |
768 * |
747 * The dynamic portion of the hook name, `$action`, refers to the post action. |
769 * The dynamic portion of the hook name, `$action`, refers to the post action. |
748 * |
770 * |
|
771 * Possible hook names include: |
|
772 * |
|
773 * - `wp_handle_sideload_prefilter` |
|
774 * - `wp_handle_upload_prefilter` |
|
775 * |
749 * @since 2.9.0 as 'wp_handle_upload_prefilter'. |
776 * @since 2.9.0 as 'wp_handle_upload_prefilter'. |
750 * @since 4.0.0 Converted to a dynamic hook with `$action`. |
777 * @since 4.0.0 Converted to a dynamic hook with `$action`. |
751 * |
778 * |
752 * @param string[] $file An array of data for a single file. |
779 * @param string[] $file An array of data for the file. Reference to a single element of `$_FILES`. |
753 */ |
780 */ |
754 $file = apply_filters( "{$action}_prefilter", $file ); |
781 $file = apply_filters( "{$action}_prefilter", $file ); |
|
782 |
|
783 /** |
|
784 * Filters the override parameters for a file before it is uploaded to WordPress. |
|
785 * |
|
786 * The dynamic portion of the hook name, `$action`, refers to the post action. |
|
787 * |
|
788 * Possible hook names include: |
|
789 * |
|
790 * - `wp_handle_sideload_overrides` |
|
791 * - `wp_handle_upload_overrides` |
|
792 * |
|
793 * @since 5.7.0 |
|
794 * |
|
795 * @param array|false $overrides An array of override parameters for this file. Boolean false if none are |
|
796 * provided. @see _wp_handle_upload(). |
|
797 * @param string[] $file An array of data for the file. Reference to a single element of `$_FILES`. |
|
798 */ |
|
799 $overrides = apply_filters( "{$action}_overrides", $overrides, $file ); |
755 |
800 |
756 // You may define your own function and pass the name in $overrides['upload_error_handler']. |
801 // You may define your own function and pass the name in $overrides['upload_error_handler']. |
757 $upload_error_handler = 'wp_handle_upload_error'; |
802 $upload_error_handler = 'wp_handle_upload_error'; |
758 if ( isset( $overrides['upload_error_handler'] ) ) { |
803 if ( isset( $overrides['upload_error_handler'] ) ) { |
759 $upload_error_handler = $overrides['upload_error_handler']; |
804 $upload_error_handler = $overrides['upload_error_handler']; |
809 // If you override this, you must provide $ext and $type!! |
854 // If you override this, you must provide $ext and $type!! |
810 $test_type = isset( $overrides['test_type'] ) ? $overrides['test_type'] : true; |
855 $test_type = isset( $overrides['test_type'] ) ? $overrides['test_type'] : true; |
811 $mimes = isset( $overrides['mimes'] ) ? $overrides['mimes'] : false; |
856 $mimes = isset( $overrides['mimes'] ) ? $overrides['mimes'] : false; |
812 |
857 |
813 // A correct form post will pass this test. |
858 // A correct form post will pass this test. |
814 if ( $test_form && ( ! isset( $_POST['action'] ) || ( $_POST['action'] != $action ) ) ) { |
859 if ( $test_form && ( ! isset( $_POST['action'] ) || $_POST['action'] !== $action ) ) { |
815 return call_user_func_array( $upload_error_handler, array( &$file, __( 'Invalid form submission.' ) ) ); |
860 return call_user_func_array( $upload_error_handler, array( &$file, __( 'Invalid form submission.' ) ) ); |
816 } |
861 } |
|
862 |
817 // A successful upload will pass this test. It makes no sense to override this one. |
863 // A successful upload will pass this test. It makes no sense to override this one. |
818 if ( isset( $file['error'] ) && $file['error'] > 0 ) { |
864 if ( isset( $file['error'] ) && $file['error'] > 0 ) { |
819 return call_user_func_array( $upload_error_handler, array( &$file, $upload_error_strings[ $file['error'] ] ) ); |
865 return call_user_func_array( $upload_error_handler, array( &$file, $upload_error_strings[ $file['error'] ] ) ); |
820 } |
866 } |
821 |
867 |
851 |
898 |
852 // Check to see if wp_check_filetype_and_ext() determined the filename was incorrect. |
899 // Check to see if wp_check_filetype_and_ext() determined the filename was incorrect. |
853 if ( $proper_filename ) { |
900 if ( $proper_filename ) { |
854 $file['name'] = $proper_filename; |
901 $file['name'] = $proper_filename; |
855 } |
902 } |
|
903 |
856 if ( ( ! $type || ! $ext ) && ! current_user_can( 'unfiltered_upload' ) ) { |
904 if ( ( ! $type || ! $ext ) && ! current_user_can( 'unfiltered_upload' ) ) { |
857 return call_user_func_array( $upload_error_handler, array( &$file, __( 'Sorry, this file type is not permitted for security reasons.' ) ) ); |
905 return call_user_func_array( $upload_error_handler, array( &$file, __( 'Sorry, this file type is not permitted for security reasons.' ) ) ); |
858 } |
906 } |
|
907 |
859 if ( ! $type ) { |
908 if ( ! $type ) { |
860 $type = $file['type']; |
909 $type = $file['type']; |
861 } |
910 } |
862 } else { |
911 } else { |
863 $type = ''; |
912 $type = ''; |
906 if ( 0 === strpos( $uploads['basedir'], ABSPATH ) ) { |
955 if ( 0 === strpos( $uploads['basedir'], ABSPATH ) ) { |
907 $error_path = str_replace( ABSPATH, '', $uploads['basedir'] ) . $uploads['subdir']; |
956 $error_path = str_replace( ABSPATH, '', $uploads['basedir'] ) . $uploads['subdir']; |
908 } else { |
957 } else { |
909 $error_path = basename( $uploads['basedir'] ) . $uploads['subdir']; |
958 $error_path = basename( $uploads['basedir'] ) . $uploads['subdir']; |
910 } |
959 } |
|
960 |
911 return $upload_error_handler( |
961 return $upload_error_handler( |
912 $file, |
962 $file, |
913 sprintf( |
963 sprintf( |
914 /* translators: %s: Destination file path. */ |
964 /* translators: %s: Destination file path. */ |
915 __( 'The uploaded file could not be moved to %s.' ), |
965 __( 'The uploaded file could not be moved to %s.' ), |
963 * |
1013 * |
964 * @since 2.0.0 |
1014 * @since 2.0.0 |
965 * |
1015 * |
966 * @see _wp_handle_upload() |
1016 * @see _wp_handle_upload() |
967 * |
1017 * |
968 * @param array $file Reference to a single element of `$_FILES`. |
1018 * @param array $file Reference to a single element of `$_FILES`. |
969 * Call the function once for each uploaded file. |
1019 * Call the function once for each uploaded file. |
970 * @param array|bool $overrides Optional. An associative array of names => values |
1020 * @param array|false $overrides Optional. An associative array of names => values |
971 * to override default variables. Default false. |
1021 * to override default variables. Default false. |
972 * @param string $time Optional. Time formatted in 'yyyy/mm'. Default null. |
1022 * @param string $time Optional. Time formatted in 'yyyy/mm'. Default null. |
973 * @return array On success, returns an associative array of file attributes. |
1023 * @return array On success, returns an associative array of file attributes. |
974 * On failure, returns `$overrides['upload_error_handler']( &$file, $message )` |
1024 * On failure, returns `$overrides['upload_error_handler']( &$file, $message )` |
975 * or `array( 'error' => $message )`. |
1025 * or `array( 'error' => $message )`. |
976 */ |
1026 */ |
977 function wp_handle_upload( &$file, $overrides = false, $time = null ) { |
1027 function wp_handle_upload( &$file, $overrides = false, $time = null ) { |
994 * |
1044 * |
995 * @since 2.6.0 |
1045 * @since 2.6.0 |
996 * |
1046 * |
997 * @see _wp_handle_upload() |
1047 * @see _wp_handle_upload() |
998 * |
1048 * |
999 * @param array $file Reference to a single element of `$_FILES`. |
1049 * @param array $file Reference to a single element of `$_FILES`. |
1000 * Call the function once for each uploaded file. |
1050 * Call the function once for each uploaded file. |
1001 * @param array|bool $overrides Optional. An associative array of names => values |
1051 * @param array|false $overrides Optional. An associative array of names => values |
1002 * to override default variables. Default false. |
1052 * to override default variables. Default false. |
1003 * @param string $time Optional. Time formatted in 'yyyy/mm'. Default null. |
1053 * @param string $time Optional. Time formatted in 'yyyy/mm'. Default null. |
1004 * @return array On success, returns an associative array of file attributes. |
1054 * @return array On success, returns an associative array of file attributes. |
1005 * On failure, returns `$overrides['upload_error_handler']( &$file, $message )` |
1055 * On failure, returns `$overrides['upload_error_handler']( &$file, $message )` |
1006 * or `array( 'error' => $message )`. |
1056 * or `array( 'error' => $message )`. |
1007 */ |
1057 */ |
1008 function wp_handle_sideload( &$file, $overrides = false, $time = null ) { |
1058 function wp_handle_sideload( &$file, $overrides = false, $time = null ) { |
1041 |
1091 |
1042 $url_filename = basename( parse_url( $url, PHP_URL_PATH ) ); |
1092 $url_filename = basename( parse_url( $url, PHP_URL_PATH ) ); |
1043 |
1093 |
1044 $tmpfname = wp_tempnam( $url_filename ); |
1094 $tmpfname = wp_tempnam( $url_filename ); |
1045 if ( ! $tmpfname ) { |
1095 if ( ! $tmpfname ) { |
1046 return new WP_Error( 'http_no_file', __( 'Could not create Temporary file.' ) ); |
1096 return new WP_Error( 'http_no_file', __( 'Could not create temporary file.' ) ); |
1047 } |
1097 } |
1048 |
1098 |
1049 $response = wp_safe_remote_get( |
1099 $response = wp_safe_remote_get( |
1050 $url, |
1100 $url, |
1051 array( |
1101 array( |
1060 return $response; |
1110 return $response; |
1061 } |
1111 } |
1062 |
1112 |
1063 $response_code = wp_remote_retrieve_response_code( $response ); |
1113 $response_code = wp_remote_retrieve_response_code( $response ); |
1064 |
1114 |
1065 if ( 200 != $response_code ) { |
1115 if ( 200 !== $response_code ) { |
1066 $data = array( |
1116 $data = array( |
1067 'code' => $response_code, |
1117 'code' => $response_code, |
1068 ); |
1118 ); |
1069 |
1119 |
1070 // Retrieve a sample of the response body for debugging purposes. |
1120 // Retrieve a sample of the response body for debugging purposes. |
1071 $tmpf = fopen( $tmpfname, 'rb' ); |
1121 $tmpf = fopen( $tmpfname, 'rb' ); |
|
1122 |
1072 if ( $tmpf ) { |
1123 if ( $tmpf ) { |
1073 /** |
1124 /** |
1074 * Filters the maximum error response body size in `download_url()`. |
1125 * Filters the maximum error response body size in `download_url()`. |
1075 * |
1126 * |
1076 * @since 5.1.0 |
1127 * @since 5.1.0 |
1078 * @see download_url() |
1129 * @see download_url() |
1079 * |
1130 * |
1080 * @param int $size The maximum error response body size. Default 1 KB. |
1131 * @param int $size The maximum error response body size. Default 1 KB. |
1081 */ |
1132 */ |
1082 $response_size = apply_filters( 'download_url_error_max_body_size', KB_IN_BYTES ); |
1133 $response_size = apply_filters( 'download_url_error_max_body_size', KB_IN_BYTES ); |
1083 $data['body'] = fread( $tmpf, $response_size ); |
1134 |
|
1135 $data['body'] = fread( $tmpf, $response_size ); |
1084 fclose( $tmpf ); |
1136 fclose( $tmpf ); |
1085 } |
1137 } |
1086 |
1138 |
1087 unlink( $tmpfname ); |
1139 unlink( $tmpfname ); |
|
1140 |
1088 return new WP_Error( 'http_404', trim( wp_remote_retrieve_response_message( $response ) ), $data ); |
1141 return new WP_Error( 'http_404', trim( wp_remote_retrieve_response_message( $response ) ), $data ); |
1089 } |
1142 } |
1090 |
1143 |
1091 $content_md5 = wp_remote_retrieve_header( $response, 'content-md5' ); |
1144 $content_md5 = wp_remote_retrieve_header( $response, 'content-md5' ); |
|
1145 |
1092 if ( $content_md5 ) { |
1146 if ( $content_md5 ) { |
1093 $md5_check = verify_file_md5( $tmpfname, $content_md5 ); |
1147 $md5_check = verify_file_md5( $tmpfname, $content_md5 ); |
|
1148 |
1094 if ( is_wp_error( $md5_check ) ) { |
1149 if ( is_wp_error( $md5_check ) ) { |
1095 unlink( $tmpfname ); |
1150 unlink( $tmpfname ); |
1096 return $md5_check; |
1151 return $md5_check; |
1097 } |
1152 } |
1098 } |
1153 } |
1104 * |
1159 * |
1105 * @since 5.2.0 |
1160 * @since 5.2.0 |
1106 * |
1161 * |
1107 * @param string[] $hostnames List of hostnames. |
1162 * @param string[] $hostnames List of hostnames. |
1108 */ |
1163 */ |
1109 $signed_hostnames = apply_filters( 'wp_signature_hosts', array( 'wordpress.org', 'downloads.wordpress.org', 's.w.org' ) ); |
1164 $signed_hostnames = apply_filters( 'wp_signature_hosts', array( 'wordpress.org', 'downloads.wordpress.org', 's.w.org' ) ); |
|
1165 |
1110 $signature_verification = in_array( parse_url( $url, PHP_URL_HOST ), $signed_hostnames, true ); |
1166 $signature_verification = in_array( parse_url( $url, PHP_URL_HOST ), $signed_hostnames, true ); |
1111 } |
1167 } |
1112 |
1168 |
1113 // Perform signature valiation if supported. |
1169 // Perform signature valiation if supported. |
1114 if ( $signature_verification ) { |
1170 if ( $signature_verification ) { |
1115 $signature = wp_remote_retrieve_header( $response, 'x-content-signature' ); |
1171 $signature = wp_remote_retrieve_header( $response, 'x-content-signature' ); |
|
1172 |
1116 if ( ! $signature ) { |
1173 if ( ! $signature ) { |
1117 // Retrieve signatures from a file if the header wasn't included. |
1174 // Retrieve signatures from a file if the header wasn't included. |
1118 // WordPress.org stores signatures at $package_url.sig. |
1175 // WordPress.org stores signatures at $package_url.sig. |
1119 |
1176 |
1120 $signature_url = false; |
1177 $signature_url = false; |
1123 if ( '.zip' === substr( $url_path, -4 ) || '.tar.gz' === substr( $url_path, -7 ) ) { |
1180 if ( '.zip' === substr( $url_path, -4 ) || '.tar.gz' === substr( $url_path, -7 ) ) { |
1124 $signature_url = str_replace( $url_path, $url_path . '.sig', $url ); |
1181 $signature_url = str_replace( $url_path, $url_path . '.sig', $url ); |
1125 } |
1182 } |
1126 |
1183 |
1127 /** |
1184 /** |
1128 * Filter the URL where the signature for a file is located. |
1185 * Filters the URL where the signature for a file is located. |
1129 * |
1186 * |
1130 * @since 5.2.0 |
1187 * @since 5.2.0 |
1131 * |
1188 * |
1132 * @param false|string $signature_url The URL where signatures can be found for a file, or false if none are known. |
1189 * @param false|string $signature_url The URL where signatures can be found for a file, or false if none are known. |
1133 * @param string $url The URL being verified. |
1190 * @param string $url The URL being verified. |
1188 * or a hex-encoded md5. |
1245 * or a hex-encoded md5. |
1189 * @return bool|WP_Error True on success, false when the MD5 format is unknown/unexpected, |
1246 * @return bool|WP_Error True on success, false when the MD5 format is unknown/unexpected, |
1190 * WP_Error on failure. |
1247 * WP_Error on failure. |
1191 */ |
1248 */ |
1192 function verify_file_md5( $filename, $expected_md5 ) { |
1249 function verify_file_md5( $filename, $expected_md5 ) { |
1193 if ( 32 == strlen( $expected_md5 ) ) { |
1250 if ( 32 === strlen( $expected_md5 ) ) { |
1194 $expected_raw_md5 = pack( 'H*', $expected_md5 ); |
1251 $expected_raw_md5 = pack( 'H*', $expected_md5 ); |
1195 } elseif ( 24 == strlen( $expected_md5 ) ) { |
1252 } elseif ( 24 === strlen( $expected_md5 ) ) { |
1196 $expected_raw_md5 = base64_decode( $expected_md5 ); |
1253 $expected_raw_md5 = base64_decode( $expected_md5 ); |
1197 } else { |
1254 } else { |
1198 return false; // Unknown format. |
1255 return false; // Unknown format. |
1199 } |
1256 } |
1200 |
1257 |
1220 * |
1277 * |
1221 * @since 5.2.0 |
1278 * @since 5.2.0 |
1222 * |
1279 * |
1223 * @param string $filename The file to validate. |
1280 * @param string $filename The file to validate. |
1224 * @param string|array $signatures A Signature provided for the file. |
1281 * @param string|array $signatures A Signature provided for the file. |
1225 * @param string $filename_for_errors A friendly filename for errors. Optional. |
1282 * @param string|false $filename_for_errors Optional. A friendly filename for errors. |
1226 * @return bool|WP_Error True on success, false if verification not attempted, |
1283 * @return bool|WP_Error True on success, false if verification not attempted, |
1227 * or WP_Error describing an error condition. |
1284 * or WP_Error describing an error condition. |
1228 */ |
1285 */ |
1229 function verify_file_signature( $filename, $signatures, $filename_for_errors = false ) { |
1286 function verify_file_signature( $filename, $signatures, $filename_for_errors = false ) { |
1230 if ( ! $filename_for_errors ) { |
1287 if ( ! $filename_for_errors ) { |
1250 in_array( PHP_VERSION_ID, array( 70200, 70201, 70202 ), true ) && |
1307 in_array( PHP_VERSION_ID, array( 70200, 70201, 70202 ), true ) && |
1251 extension_loaded( 'opcache' ) |
1308 extension_loaded( 'opcache' ) |
1252 ) { |
1309 ) { |
1253 // Sodium_Compat isn't compatible with PHP 7.2.0~7.2.2 due to a bug in the PHP Opcache extension, bail early as it'll fail. |
1310 // Sodium_Compat isn't compatible with PHP 7.2.0~7.2.2 due to a bug in the PHP Opcache extension, bail early as it'll fail. |
1254 // https://bugs.php.net/bug.php?id=75938 |
1311 // https://bugs.php.net/bug.php?id=75938 |
1255 |
|
1256 return new WP_Error( |
1312 return new WP_Error( |
1257 'signature_verification_unsupported', |
1313 'signature_verification_unsupported', |
1258 sprintf( |
1314 sprintf( |
1259 /* translators: %s: The filename of the package. */ |
1315 /* translators: %s: The filename of the package. */ |
1260 __( 'The authenticity of %s could not be verified as signature verification is unavailable on this system.' ), |
1316 __( 'The authenticity of %s could not be verified as signature verification is unavailable on this system.' ), |
1264 'php' => phpversion(), |
1320 'php' => phpversion(), |
1265 // phpcs:ignore PHPCompatibility.Constants.NewConstants.sodium_library_versionFound |
1321 // phpcs:ignore PHPCompatibility.Constants.NewConstants.sodium_library_versionFound |
1266 'sodium' => defined( 'SODIUM_LIBRARY_VERSION' ) ? SODIUM_LIBRARY_VERSION : ( defined( 'ParagonIE_Sodium_Compat::VERSION_STRING' ) ? ParagonIE_Sodium_Compat::VERSION_STRING : false ), |
1322 'sodium' => defined( 'SODIUM_LIBRARY_VERSION' ) ? SODIUM_LIBRARY_VERSION : ( defined( 'ParagonIE_Sodium_Compat::VERSION_STRING' ) ? ParagonIE_Sodium_Compat::VERSION_STRING : false ), |
1267 ) |
1323 ) |
1268 ); |
1324 ); |
1269 |
|
1270 } |
1325 } |
1271 |
1326 |
1272 // Verify runtime speed of Sodium_Compat is acceptable. |
1327 // Verify runtime speed of Sodium_Compat is acceptable. |
1273 if ( ! extension_loaded( 'sodium' ) && ! ParagonIE_Sodium_Compat::polyfill_is_fast() ) { |
1328 if ( ! extension_loaded( 'sodium' ) && ! ParagonIE_Sodium_Compat::polyfill_is_fast() ) { |
1274 $sodium_compat_is_fast = false; |
1329 $sodium_compat_is_fast = false; |
1499 global $wp_filesystem; |
1554 global $wp_filesystem; |
1500 |
1555 |
1501 $z = new ZipArchive(); |
1556 $z = new ZipArchive(); |
1502 |
1557 |
1503 $zopen = $z->open( $file, ZIPARCHIVE::CHECKCONS ); |
1558 $zopen = $z->open( $file, ZIPARCHIVE::CHECKCONS ); |
|
1559 |
1504 if ( true !== $zopen ) { |
1560 if ( true !== $zopen ) { |
1505 return new WP_Error( 'incompatible_archive', __( 'Incompatible Archive.' ), array( 'ziparchive_error' => $zopen ) ); |
1561 return new WP_Error( 'incompatible_archive', __( 'Incompatible Archive.' ), array( 'ziparchive_error' => $zopen ) ); |
1506 } |
1562 } |
1507 |
1563 |
1508 $uncompressed_size = 0; |
1564 $uncompressed_size = 0; |
1509 |
1565 |
1510 for ( $i = 0; $i < $z->numFiles; $i++ ) { |
1566 for ( $i = 0; $i < $z->numFiles; $i++ ) { |
1511 $info = $z->statIndex( $i ); |
1567 $info = $z->statIndex( $i ); |
|
1568 |
1512 if ( ! $info ) { |
1569 if ( ! $info ) { |
1513 return new WP_Error( 'stat_failed_ziparchive', __( 'Could not retrieve file from archive.' ) ); |
1570 return new WP_Error( 'stat_failed_ziparchive', __( 'Could not retrieve file from archive.' ) ); |
1514 } |
1571 } |
1515 |
1572 |
1516 if ( '__MACOSX/' === substr( $info['name'], 0, 9 ) ) { // Skip the OS X-created __MACOSX directory. |
1573 if ( '__MACOSX/' === substr( $info['name'], 0, 9 ) ) { // Skip the OS X-created __MACOSX directory. |
1540 * A disk that has zero free bytes has bigger problems. |
1597 * A disk that has zero free bytes has bigger problems. |
1541 * Require we have enough space to unzip the file and copy its contents, with a 10% buffer. |
1598 * Require we have enough space to unzip the file and copy its contents, with a 10% buffer. |
1542 */ |
1599 */ |
1543 if ( wp_doing_cron() ) { |
1600 if ( wp_doing_cron() ) { |
1544 $available_space = @disk_free_space( WP_CONTENT_DIR ); |
1601 $available_space = @disk_free_space( WP_CONTENT_DIR ); |
|
1602 |
1545 if ( $available_space && ( $uncompressed_size * 2.1 ) > $available_space ) { |
1603 if ( $available_space && ( $uncompressed_size * 2.1 ) > $available_space ) { |
1546 return new WP_Error( 'disk_full_unzip_file', __( 'Could not copy files. You may have run out of disk space.' ), compact( 'uncompressed_size', 'available_space' ) ); |
1604 return new WP_Error( |
|
1605 'disk_full_unzip_file', |
|
1606 __( 'Could not copy files. You may have run out of disk space.' ), |
|
1607 compact( 'uncompressed_size', 'available_space' ) |
|
1608 ); |
1547 } |
1609 } |
1548 } |
1610 } |
1549 |
1611 |
1550 $needed_dirs = array_unique( $needed_dirs ); |
1612 $needed_dirs = array_unique( $needed_dirs ); |
|
1613 |
1551 foreach ( $needed_dirs as $dir ) { |
1614 foreach ( $needed_dirs as $dir ) { |
1552 // Check the parent folders of the folders all exist within the creation array. |
1615 // Check the parent folders of the folders all exist within the creation array. |
1553 if ( untrailingslashit( $to ) == $dir ) { // Skip over the working directory, we know this exists (or will exist). |
1616 if ( untrailingslashit( $to ) === $dir ) { // Skip over the working directory, we know this exists (or will exist). |
1554 continue; |
1617 continue; |
1555 } |
1618 } |
|
1619 |
1556 if ( strpos( $dir, $to ) === false ) { // If the directory is not within the working directory, skip it. |
1620 if ( strpos( $dir, $to ) === false ) { // If the directory is not within the working directory, skip it. |
1557 continue; |
1621 continue; |
1558 } |
1622 } |
1559 |
1623 |
1560 $parent_folder = dirname( $dir ); |
1624 $parent_folder = dirname( $dir ); |
1561 while ( ! empty( $parent_folder ) && untrailingslashit( $to ) != $parent_folder && ! in_array( $parent_folder, $needed_dirs, true ) ) { |
1625 |
|
1626 while ( ! empty( $parent_folder ) |
|
1627 && untrailingslashit( $to ) !== $parent_folder |
|
1628 && ! in_array( $parent_folder, $needed_dirs, true ) |
|
1629 ) { |
1562 $needed_dirs[] = $parent_folder; |
1630 $needed_dirs[] = $parent_folder; |
1563 $parent_folder = dirname( $parent_folder ); |
1631 $parent_folder = dirname( $parent_folder ); |
1564 } |
1632 } |
1565 } |
1633 } |
|
1634 |
1566 asort( $needed_dirs ); |
1635 asort( $needed_dirs ); |
1567 |
1636 |
1568 // Create those directories if need be: |
1637 // Create those directories if need be: |
1569 foreach ( $needed_dirs as $_dir ) { |
1638 foreach ( $needed_dirs as $_dir ) { |
1570 // Only check to see if the Dir exists upon creation failure. Less I/O this way. |
1639 // Only check to see if the Dir exists upon creation failure. Less I/O this way. |
1574 } |
1643 } |
1575 unset( $needed_dirs ); |
1644 unset( $needed_dirs ); |
1576 |
1645 |
1577 for ( $i = 0; $i < $z->numFiles; $i++ ) { |
1646 for ( $i = 0; $i < $z->numFiles; $i++ ) { |
1578 $info = $z->statIndex( $i ); |
1647 $info = $z->statIndex( $i ); |
|
1648 |
1579 if ( ! $info ) { |
1649 if ( ! $info ) { |
1580 return new WP_Error( 'stat_failed_ziparchive', __( 'Could not retrieve file from archive.' ) ); |
1650 return new WP_Error( 'stat_failed_ziparchive', __( 'Could not retrieve file from archive.' ) ); |
1581 } |
1651 } |
1582 |
1652 |
1583 if ( '/' === substr( $info['name'], -1 ) ) { // Directory. |
1653 if ( '/' === substr( $info['name'], -1 ) ) { // Directory. |
1592 if ( 0 !== validate_file( $info['name'] ) ) { |
1662 if ( 0 !== validate_file( $info['name'] ) ) { |
1593 continue; |
1663 continue; |
1594 } |
1664 } |
1595 |
1665 |
1596 $contents = $z->getFromIndex( $i ); |
1666 $contents = $z->getFromIndex( $i ); |
|
1667 |
1597 if ( false === $contents ) { |
1668 if ( false === $contents ) { |
1598 return new WP_Error( 'extract_failed_ziparchive', __( 'Could not extract file from archive.' ), $info['name'] ); |
1669 return new WP_Error( 'extract_failed_ziparchive', __( 'Could not extract file from archive.' ), $info['name'] ); |
1599 } |
1670 } |
1600 |
1671 |
1601 if ( ! $wp_filesystem->put_contents( $to . $info['name'], $contents, FS_CHMOD_FILE ) ) { |
1672 if ( ! $wp_filesystem->put_contents( $to . $info['name'], $contents, FS_CHMOD_FILE ) ) { |
1667 * A disk that has zero free bytes has bigger problems. |
1738 * A disk that has zero free bytes has bigger problems. |
1668 * Require we have enough space to unzip the file and copy its contents, with a 10% buffer. |
1739 * Require we have enough space to unzip the file and copy its contents, with a 10% buffer. |
1669 */ |
1740 */ |
1670 if ( wp_doing_cron() ) { |
1741 if ( wp_doing_cron() ) { |
1671 $available_space = @disk_free_space( WP_CONTENT_DIR ); |
1742 $available_space = @disk_free_space( WP_CONTENT_DIR ); |
|
1743 |
1672 if ( $available_space && ( $uncompressed_size * 2.1 ) > $available_space ) { |
1744 if ( $available_space && ( $uncompressed_size * 2.1 ) > $available_space ) { |
1673 return new WP_Error( 'disk_full_unzip_file', __( 'Could not copy files. You may have run out of disk space.' ), compact( 'uncompressed_size', 'available_space' ) ); |
1745 return new WP_Error( |
|
1746 'disk_full_unzip_file', |
|
1747 __( 'Could not copy files. You may have run out of disk space.' ), |
|
1748 compact( 'uncompressed_size', 'available_space' ) |
|
1749 ); |
1674 } |
1750 } |
1675 } |
1751 } |
1676 |
1752 |
1677 $needed_dirs = array_unique( $needed_dirs ); |
1753 $needed_dirs = array_unique( $needed_dirs ); |
|
1754 |
1678 foreach ( $needed_dirs as $dir ) { |
1755 foreach ( $needed_dirs as $dir ) { |
1679 // Check the parent folders of the folders all exist within the creation array. |
1756 // Check the parent folders of the folders all exist within the creation array. |
1680 if ( untrailingslashit( $to ) == $dir ) { // Skip over the working directory, we know this exists (or will exist). |
1757 if ( untrailingslashit( $to ) === $dir ) { // Skip over the working directory, we know this exists (or will exist). |
1681 continue; |
1758 continue; |
1682 } |
1759 } |
|
1760 |
1683 if ( strpos( $dir, $to ) === false ) { // If the directory is not within the working directory, skip it. |
1761 if ( strpos( $dir, $to ) === false ) { // If the directory is not within the working directory, skip it. |
1684 continue; |
1762 continue; |
1685 } |
1763 } |
1686 |
1764 |
1687 $parent_folder = dirname( $dir ); |
1765 $parent_folder = dirname( $dir ); |
1688 while ( ! empty( $parent_folder ) && untrailingslashit( $to ) != $parent_folder && ! in_array( $parent_folder, $needed_dirs, true ) ) { |
1766 |
|
1767 while ( ! empty( $parent_folder ) |
|
1768 && untrailingslashit( $to ) !== $parent_folder |
|
1769 && ! in_array( $parent_folder, $needed_dirs, true ) |
|
1770 ) { |
1689 $needed_dirs[] = $parent_folder; |
1771 $needed_dirs[] = $parent_folder; |
1690 $parent_folder = dirname( $parent_folder ); |
1772 $parent_folder = dirname( $parent_folder ); |
1691 } |
1773 } |
1692 } |
1774 } |
|
1775 |
1693 asort( $needed_dirs ); |
1776 asort( $needed_dirs ); |
1694 |
1777 |
1695 // Create those directories if need be: |
1778 // Create those directories if need be: |
1696 foreach ( $needed_dirs as $_dir ) { |
1779 foreach ( $needed_dirs as $_dir ) { |
1697 // Only check to see if the dir exists upon creation failure. Less I/O this way. |
1780 // Only check to see if the dir exists upon creation failure. Less I/O this way. |
1741 function copy_dir( $from, $to, $skip_list = array() ) { |
1825 function copy_dir( $from, $to, $skip_list = array() ) { |
1742 global $wp_filesystem; |
1826 global $wp_filesystem; |
1743 |
1827 |
1744 $dirlist = $wp_filesystem->dirlist( $from ); |
1828 $dirlist = $wp_filesystem->dirlist( $from ); |
1745 |
1829 |
|
1830 if ( false === $dirlist ) { |
|
1831 return new WP_Error( 'dirlist_failed_copy_dir', __( 'Directory listing failed.' ), basename( $to ) ); |
|
1832 } |
|
1833 |
1746 $from = trailingslashit( $from ); |
1834 $from = trailingslashit( $from ); |
1747 $to = trailingslashit( $to ); |
1835 $to = trailingslashit( $to ); |
1748 |
1836 |
1749 foreach ( (array) $dirlist as $filename => $fileinfo ) { |
1837 foreach ( (array) $dirlist as $filename => $fileinfo ) { |
1750 if ( in_array( $filename, $skip_list, true ) ) { |
1838 if ( in_array( $filename, $skip_list, true ) ) { |
1753 |
1841 |
1754 if ( 'f' === $fileinfo['type'] ) { |
1842 if ( 'f' === $fileinfo['type'] ) { |
1755 if ( ! $wp_filesystem->copy( $from . $filename, $to . $filename, true, FS_CHMOD_FILE ) ) { |
1843 if ( ! $wp_filesystem->copy( $from . $filename, $to . $filename, true, FS_CHMOD_FILE ) ) { |
1756 // If copy failed, chmod file to 0644 and try again. |
1844 // If copy failed, chmod file to 0644 and try again. |
1757 $wp_filesystem->chmod( $to . $filename, FS_CHMOD_FILE ); |
1845 $wp_filesystem->chmod( $to . $filename, FS_CHMOD_FILE ); |
|
1846 |
1758 if ( ! $wp_filesystem->copy( $from . $filename, $to . $filename, true, FS_CHMOD_FILE ) ) { |
1847 if ( ! $wp_filesystem->copy( $from . $filename, $to . $filename, true, FS_CHMOD_FILE ) ) { |
1759 return new WP_Error( 'copy_failed_copy_dir', __( 'Could not copy file.' ), $to . $filename ); |
1848 return new WP_Error( 'copy_failed_copy_dir', __( 'Could not copy file.' ), $to . $filename ); |
1760 } |
1849 } |
1761 } |
1850 } |
1762 |
1851 |
1768 } |
1857 } |
1769 } |
1858 } |
1770 |
1859 |
1771 // Generate the $sub_skip_list for the subdirectory as a sub-set of the existing $skip_list. |
1860 // Generate the $sub_skip_list for the subdirectory as a sub-set of the existing $skip_list. |
1772 $sub_skip_list = array(); |
1861 $sub_skip_list = array(); |
|
1862 |
1773 foreach ( $skip_list as $skip_item ) { |
1863 foreach ( $skip_list as $skip_item ) { |
1774 if ( 0 === strpos( $skip_item, $filename . '/' ) ) { |
1864 if ( 0 === strpos( $skip_item, $filename . '/' ) ) { |
1775 $sub_skip_list[] = preg_replace( '!^' . preg_quote( $filename, '!' ) . '/!i', '', $skip_item ); |
1865 $sub_skip_list[] = preg_replace( '!^' . preg_quote( $filename, '!' ) . '/!i', '', $skip_item ); |
1776 } |
1866 } |
1777 } |
1867 } |
1778 |
1868 |
1779 $result = copy_dir( $from . $filename, $to . $filename, $sub_skip_list ); |
1869 $result = copy_dir( $from . $filename, $to . $filename, $sub_skip_list ); |
|
1870 |
1780 if ( is_wp_error( $result ) ) { |
1871 if ( is_wp_error( $result ) ) { |
1781 return $result; |
1872 return $result; |
1782 } |
1873 } |
1783 } |
1874 } |
1784 } |
1875 } |
2027 * being writable. |
2118 * being writable. |
2028 * @param array $extra_fields Extra POST fields. |
2119 * @param array $extra_fields Extra POST fields. |
2029 * @param bool $allow_relaxed_file_ownership Whether to allow Group/World writable. |
2120 * @param bool $allow_relaxed_file_ownership Whether to allow Group/World writable. |
2030 */ |
2121 */ |
2031 $req_cred = apply_filters( 'request_filesystem_credentials', '', $form_post, $type, $error, $context, $extra_fields, $allow_relaxed_file_ownership ); |
2122 $req_cred = apply_filters( 'request_filesystem_credentials', '', $form_post, $type, $error, $context, $extra_fields, $allow_relaxed_file_ownership ); |
|
2123 |
2032 if ( '' !== $req_cred ) { |
2124 if ( '' !== $req_cred ) { |
2033 return $req_cred; |
2125 return $req_cred; |
2034 } |
2126 } |
2035 |
2127 |
2036 if ( empty( $type ) ) { |
2128 if ( empty( $type ) ) { |
2065 $submitted_form['private_key'], |
2157 $submitted_form['private_key'], |
2066 $submitted_form['connection_type'] |
2158 $submitted_form['connection_type'] |
2067 ); |
2159 ); |
2068 } |
2160 } |
2069 |
2161 |
2070 // If defined, set it to that. Else, if POST'd, set it to that. If not, set it to whatever it previously was (saved details in option). |
2162 $ftp_constants = array( |
2071 $credentials['hostname'] = defined( 'FTP_HOST' ) ? FTP_HOST : ( ! empty( $submitted_form['hostname'] ) ? $submitted_form['hostname'] : $credentials['hostname'] ); |
2163 'hostname' => 'FTP_HOST', |
2072 $credentials['username'] = defined( 'FTP_USER' ) ? FTP_USER : ( ! empty( $submitted_form['username'] ) ? $submitted_form['username'] : $credentials['username'] ); |
2164 'username' => 'FTP_USER', |
2073 $credentials['password'] = defined( 'FTP_PASS' ) ? FTP_PASS : ( ! empty( $submitted_form['password'] ) ? $submitted_form['password'] : '' ); |
2165 'password' => 'FTP_PASS', |
2074 |
2166 'public_key' => 'FTP_PUBKEY', |
2075 // Check to see if we are setting the public/private keys for ssh. |
2167 'private_key' => 'FTP_PRIKEY', |
2076 $credentials['public_key'] = defined( 'FTP_PUBKEY' ) ? FTP_PUBKEY : ( ! empty( $submitted_form['public_key'] ) ? $submitted_form['public_key'] : '' ); |
2168 ); |
2077 $credentials['private_key'] = defined( 'FTP_PRIKEY' ) ? FTP_PRIKEY : ( ! empty( $submitted_form['private_key'] ) ? $submitted_form['private_key'] : '' ); |
2169 |
|
2170 // If defined, set it to that. Else, if POST'd, set it to that. If not, set it to an empty string. |
|
2171 // Otherwise, keep it as it previously was (saved details in option). |
|
2172 foreach ( $ftp_constants as $key => $constant ) { |
|
2173 if ( defined( $constant ) ) { |
|
2174 $credentials[ $key ] = constant( $constant ); |
|
2175 } elseif ( ! empty( $submitted_form[ $key ] ) ) { |
|
2176 $credentials[ $key ] = $submitted_form[ $key ]; |
|
2177 } elseif ( ! isset( $credentials[ $key ] ) ) { |
|
2178 $credentials[ $key ] = ''; |
|
2179 } |
|
2180 } |
2078 |
2181 |
2079 // Sanitize the hostname, some people might pass in odd data. |
2182 // Sanitize the hostname, some people might pass in odd data. |
2080 $credentials['hostname'] = preg_replace( '|\w+://|', '', $credentials['hostname'] ); // Strip any schemes off. |
2183 $credentials['hostname'] = preg_replace( '|\w+://|', '', $credentials['hostname'] ); // Strip any schemes off. |
2081 |
2184 |
2082 if ( strpos( $credentials['hostname'], ':' ) ) { |
2185 if ( strpos( $credentials['hostname'], ':' ) ) { |
2095 } elseif ( ! empty( $submitted_form['connection_type'] ) ) { |
2198 } elseif ( ! empty( $submitted_form['connection_type'] ) ) { |
2096 $credentials['connection_type'] = $submitted_form['connection_type']; |
2199 $credentials['connection_type'] = $submitted_form['connection_type']; |
2097 } elseif ( ! isset( $credentials['connection_type'] ) ) { // All else fails (and it's not defaulted to something else saved), default to FTP. |
2200 } elseif ( ! isset( $credentials['connection_type'] ) ) { // All else fails (and it's not defaulted to something else saved), default to FTP. |
2098 $credentials['connection_type'] = 'ftp'; |
2201 $credentials['connection_type'] = 'ftp'; |
2099 } |
2202 } |
|
2203 |
2100 if ( ! $error |
2204 if ( ! $error |
2101 && ( ( ! empty( $credentials['password'] ) && ! empty( $credentials['username'] ) && ! empty( $credentials['hostname'] ) ) |
2205 && ( ! empty( $credentials['hostname'] ) && ! empty( $credentials['username'] ) && ! empty( $credentials['password'] ) |
2102 || ( 'ssh' === $credentials['connection_type'] && ! empty( $credentials['public_key'] ) && ! empty( $credentials['private_key'] ) ) |
2206 || 'ssh' === $credentials['connection_type'] && ! empty( $credentials['public_key'] ) && ! empty( $credentials['private_key'] ) |
2103 ) |
2207 ) |
2104 ) { |
2208 ) { |
2105 $stored_credentials = $credentials; |
2209 $stored_credentials = $credentials; |
2106 |
2210 |
2107 if ( ! empty( $stored_credentials['port'] ) ) { // Save port as part of hostname to simplify above code. |
2211 if ( ! empty( $stored_credentials['port'] ) ) { // Save port as part of hostname to simplify above code. |
2108 $stored_credentials['hostname'] .= ':' . $stored_credentials['port']; |
2212 $stored_credentials['hostname'] .= ':' . $stored_credentials['port']; |
2109 } |
2213 } |
2110 |
2214 |
2111 unset( $stored_credentials['password'], $stored_credentials['port'], $stored_credentials['private_key'], $stored_credentials['public_key'] ); |
2215 unset( |
|
2216 $stored_credentials['password'], |
|
2217 $stored_credentials['port'], |
|
2218 $stored_credentials['private_key'], |
|
2219 $stored_credentials['public_key'] |
|
2220 ); |
2112 |
2221 |
2113 if ( ! wp_installing() ) { |
2222 if ( ! wp_installing() ) { |
2114 update_option( 'ftp_credentials', $stored_credentials ); |
2223 update_option( 'ftp_credentials', $stored_credentials ); |
2115 } |
2224 } |
2116 |
2225 |
2117 return $credentials; |
2226 return $credentials; |
2118 } |
2227 } |
|
2228 |
2119 $hostname = isset( $credentials['hostname'] ) ? $credentials['hostname'] : ''; |
2229 $hostname = isset( $credentials['hostname'] ) ? $credentials['hostname'] : ''; |
2120 $username = isset( $credentials['username'] ) ? $credentials['username'] : ''; |
2230 $username = isset( $credentials['username'] ) ? $credentials['username'] : ''; |
2121 $public_key = isset( $credentials['public_key'] ) ? $credentials['public_key'] : ''; |
2231 $public_key = isset( $credentials['public_key'] ) ? $credentials['public_key'] : ''; |
2122 $private_key = isset( $credentials['private_key'] ) ? $credentials['private_key'] : ''; |
2232 $private_key = isset( $credentials['private_key'] ) ? $credentials['private_key'] : ''; |
2123 $port = isset( $credentials['port'] ) ? $credentials['port'] : ''; |
2233 $port = isset( $credentials['port'] ) ? $credentials['port'] : ''; |
2154 * @param bool|WP_Error $error Whether the current request has failed to connect, |
2264 * @param bool|WP_Error $error Whether the current request has failed to connect, |
2155 * or an error object. |
2265 * or an error object. |
2156 * @param string $context Full path to the directory that is tested for being writable. |
2266 * @param string $context Full path to the directory that is tested for being writable. |
2157 */ |
2267 */ |
2158 $types = apply_filters( 'fs_ftp_connection_types', $types, $credentials, $type, $error, $context ); |
2268 $types = apply_filters( 'fs_ftp_connection_types', $types, $credentials, $type, $error, $context ); |
2159 |
|
2160 ?> |
2269 ?> |
2161 <form action="<?php echo esc_url( $form_post ); ?>" method="post"> |
2270 <form action="<?php echo esc_url( $form_post ); ?>" method="post"> |
2162 <div id="request-filesystem-credentials-form" class="request-filesystem-credentials-form"> |
2271 <div id="request-filesystem-credentials-form" class="request-filesystem-credentials-form"> |
2163 <?php |
2272 <?php |
2164 // Print a H1 heading in the FTP credentials modal dialog, default is a H2. |
2273 // Print a H1 heading in the FTP credentials modal dialog, default is a H2. |
2211 </div> |
2320 </div> |
2212 <div class="ftp-password"> |
2321 <div class="ftp-password"> |
2213 <label for="password"> |
2322 <label for="password"> |
2214 <span class="field-title"><?php echo $label_pass; ?></span> |
2323 <span class="field-title"><?php echo $label_pass; ?></span> |
2215 <input name="password" type="password" id="password" value="<?php echo $password_value; ?>"<?php disabled( defined( 'FTP_PASS' ) ); ?> /> |
2324 <input name="password" type="password" id="password" value="<?php echo $password_value; ?>"<?php disabled( defined( 'FTP_PASS' ) ); ?> /> |
2216 <em> |
|
2217 <?php |
2325 <?php |
2218 if ( ! defined( 'FTP_PASS' ) ) { |
2326 if ( ! defined( 'FTP_PASS' ) ) { |
2219 _e( 'This password will not be stored on the server.' );} |
2327 _e( 'This password will not be stored on the server.' );} |
2220 ?> |
2328 ?> |
2221 </em> |
|
2222 </label> |
2329 </label> |
2223 </div> |
2330 </div> |
2224 <fieldset> |
2331 <fieldset> |
2225 <legend><?php _e( 'Connection Type' ); ?></legend> |
2332 <legend><?php _e( 'Connection Type' ); ?></legend> |
2226 <?php |
2333 <?php |
2260 foreach ( (array) $extra_fields as $field ) { |
2367 foreach ( (array) $extra_fields as $field ) { |
2261 if ( isset( $submitted_form[ $field ] ) ) { |
2368 if ( isset( $submitted_form[ $field ] ) ) { |
2262 echo '<input type="hidden" name="' . esc_attr( $field ) . '" value="' . esc_attr( $submitted_form[ $field ] ) . '" />'; |
2369 echo '<input type="hidden" name="' . esc_attr( $field ) . '" value="' . esc_attr( $submitted_form[ $field ] ) . '" />'; |
2263 } |
2370 } |
2264 } |
2371 } |
|
2372 |
|
2373 // Make sure the `submit_button()` function is available during the REST API call |
|
2374 // from WP_Site_Health_Auto_Updates::test_check_wp_filesystem_method(). |
|
2375 if ( ! function_exists( 'submit_button' ) ) { |
|
2376 require_once ABSPATH . '/wp-admin/includes/template.php'; |
|
2377 } |
2265 ?> |
2378 ?> |
2266 <p class="request-filesystem-credentials-action-buttons"> |
2379 <p class="request-filesystem-credentials-action-buttons"> |
2267 <?php wp_nonce_field( 'filesystem-credentials', '_fs_nonce', false, true ); ?> |
2380 <?php wp_nonce_field( 'filesystem-credentials', '_fs_nonce', false, true ); ?> |
2268 <button class="button cancel-button" data-js-action="close" type="button"><?php _e( 'Cancel' ); ?></button> |
2381 <button class="button cancel-button" data-js-action="close" type="button"><?php _e( 'Cancel' ); ?></button> |
2269 <?php submit_button( __( 'Proceed' ), '', 'upgrade', false ); ?> |
2382 <?php submit_button( __( 'Proceed' ), '', 'upgrade', false ); ?> |