Ticket #31616: 31616.4.diff
File 31616.4.diff, 29.2 KB (added by , 10 years ago) |
---|
-
src/wp-admin/includes/file.php
910 910 911 911 $context = trailingslashit( $context ); 912 912 913 if ( ! $method ) {913 static $results = array(); 914 914 915 $temp_file_name = $context . 'temp-write-test-' . time();916 $temp_handle = @fopen($temp_file_name, 'w');917 if ( $temp_handle) {915 // saving hash for static cache; file reads/writes are to be avoided when possible 916 $hash = md5(serialize($args) . $context . $allow_relaxed_file_ownership); 917 if ( ! isset($results[$hash])) { 918 918 919 // Attempt to determine the file owner of the WordPress files, and that of newly created files 920 $wp_file_owner = $temp_file_owner = false; 921 if ( function_exists('fileowner') ) { 922 $wp_file_owner = @fileowner( __FILE__ ); 923 $temp_file_owner = @fileowner( $temp_file_name ); 919 if ( ! $method ) { 920 921 $temp_file_name = $context . 'temp-write-test-' . time(); 922 $temp_handle = @fopen( $temp_file_name, 'w' ); 923 if ( $temp_handle ) { 924 925 // Attempt to determine the file owner of the WordPress files, and that of newly created files 926 $wp_file_owner = $temp_file_owner = false; 927 if ( function_exists( 'fileowner' ) ) { 928 $wp_file_owner = @fileowner( __FILE__ ); 929 $temp_file_owner = @fileowner( $temp_file_name ); 930 } 931 932 if ( $wp_file_owner !== false && $wp_file_owner === $temp_file_owner ) { 933 // WordPress is creating files as the same owner as the WordPress files, 934 // this means it's safe to modify & create new files via PHP. 935 $method = 'direct'; 936 $GLOBALS['_wp_filesystem_direct_method'] = 'file_owner'; 937 } elseif ( $allow_relaxed_file_ownership ) { 938 // The $context directory is writable, and $allow_relaxed_file_ownership is set, this means we can modify files 939 // safely in this directory. This mode doesn't create new files, only alter existing ones. 940 $method = 'direct'; 941 $GLOBALS['_wp_filesystem_direct_method'] = 'relaxed_ownership'; 942 } 943 944 @fclose( $temp_handle ); 945 @unlink( $temp_file_name ); 924 946 } 947 } 925 948 926 if ( $wp_file_owner !== false && $wp_file_owner === $temp_file_owner ) { 927 // WordPress is creating files as the same owner as the WordPress files, 928 // this means it's safe to modify & create new files via PHP. 929 $method = 'direct'; 930 $GLOBALS['_wp_filesystem_direct_method'] = 'file_owner'; 931 } elseif ( $allow_relaxed_file_ownership ) { 932 // The $context directory is writable, and $allow_relaxed_file_ownership is set, this means we can modify files 933 // safely in this directory. This mode doesn't create new files, only alter existing ones. 934 $method = 'direct'; 935 $GLOBALS['_wp_filesystem_direct_method'] = 'relaxed_ownership'; 949 if ( ! $method && isset($args['connection_type']) && 'ssh' == $args['connection_type'] && extension_loaded('ssh2') && function_exists('stream_get_contents') ) $method = 'ssh2'; 950 if ( ! $method && extension_loaded('ftp') ) $method = 'ftpext'; 951 if ( ! $method && ( extension_loaded('sockets') || function_exists('fsockopen') ) ) $method = 'ftpsockets'; //Sockets: Socket extension; PHP Mode: FSockopen / fwrite / fread 952 953 /** 954 * Filter the filesystem method to use. 955 * 956 * @since 2.6.0 957 * 958 * @param string $method Filesystem method to return. 959 * @param array $args An array of connection details for the method. 960 * @param string $context Full path to the directory that is tested for being writable. 961 * @param bool $allow_relaxed_file_ownership Whether to allow Group/World writable. 962 */ 963 $results[$hash] = apply_filters( 'filesystem_method', $method, $args, $context, $allow_relaxed_file_ownership ); 964 } 965 966 return $results[$hash]; 967 } 968 969 /** 970 * Collects the filesystem credentials set in defines, $_POST data and database options. 971 * 972 * If no type is specified, a filesystem check will be done to see what 973 * type is available to use. 974 * 975 * If direct file access is possible, no credentials are needed. 976 * 977 * The variables of the credentials are collected using this order: 978 * 979 * 1. Defines - Preceed everything if they are set they are used 980 * 2. $_POST - Information submitted by the request form 981 * 3. Saved - Previously entered data that is saved will be used last 982 * 983 * Note: this function does not check if a specified type is available on this system 984 * it merly collects data based on available variables. 985 * 986 * @since 4.2.0 987 * 988 * @param array $args { 989 * Optional. Arguments to define the environment. Default empty array. 990 * @type string $form_post the URL to post the form to. Default ''. Accepts URL. 991 * @type string $type the chosen Filesystem method in use. Default ''. 992 * @type string $context The directory which is needed access to, 993 * the write-test will be performed on this 994 * directory by get_filesystem_method(). Default False. 995 * @type bool $allow_relaxed_file_ownership Whether to allow Group/World writable. Default False. 996 * } 997 * @return array { 998 * Optional. Credentials that are set on the system. Default empty array. 999 * @type string $connection_type Type of connection the credentials are meant for. 1000 * @type string $hostname Optional. 1001 * @type string $username Optional. 1002 * @type string $password Optional. 1003 * @type string $public_key Optional. SSH public key. 1004 * @type string $private_key Optional. SSH private key. 1005 * @type int $port Optional. 1006 * } 1007 */ 1008 function get_filesystem_credentials( $args = array() ) { 1009 $defaults = array( 1010 'form_post' => '', 1011 'type' => '', 1012 'context' => false, 1013 'allow_relaxed_file_ownership' => false 1014 ); 1015 1016 $args = wp_parse_args( $args, $defaults ); 1017 1018 // extract items 1019 $type = $args['type']; 1020 $context = $args['context']; 1021 $allow_relaxed_file_ownership = $args['allow_relaxed_file_ownership']; 1022 1023 // For the direct method no credentials are needed 1024 if ( empty($type) ) { 1025 $type = get_filesystem_method( array(), $context, $allow_relaxed_file_ownership ); 1026 } 1027 1028 if ( 'direct' == $type ) { 1029 return array( 'connection_type' => 'direct' ); 1030 } 1031 1032 // Retrieve saved information 1033 $credentials = get_option('ftp_credentials', array( 'hostname' => '', 'username' => '')); 1034 1035 // 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) 1036 $credentials['hostname'] = defined('FTP_HOST') ? FTP_HOST : (!empty($_POST['hostname']) ? wp_unslash( $_POST['hostname'] ) : $credentials['hostname']); 1037 $credentials['username'] = defined('FTP_USER') ? FTP_USER : (!empty($_POST['username']) ? wp_unslash( $_POST['username'] ) : $credentials['username']); 1038 $credentials['password'] = defined('FTP_PASS') ? FTP_PASS : (!empty($_POST['password']) ? wp_unslash( $_POST['password'] ) : ''); 1039 1040 // Check to see if we are setting the public/private keys for ssh 1041 $credentials['public_key'] = defined('FTP_PUBKEY') ? FTP_PUBKEY : (!empty($_POST['public_key']) ? wp_unslash( $_POST['public_key'] ) : ''); 1042 $credentials['private_key'] = defined('FTP_PRIKEY') ? FTP_PRIKEY : (!empty($_POST['private_key']) ? wp_unslash( $_POST['private_key'] ) : ''); 1043 1044 // Sanitize the hostname, Some people might pass in odd-data: 1045 $credentials['hostname'] = preg_replace('|\w+://|', '', $credentials['hostname']); //Strip any schemes off 1046 1047 // If hostname contains a port, check it and separate it 1048 if ( strpos($credentials['hostname'], ':') ) { 1049 list( $credentials['hostname'], $credentials['port'] ) = explode(':', $credentials['hostname'], 2); 1050 if ( ! is_numeric($credentials['port']) ) 1051 unset($credentials['port']); 1052 } else { 1053 unset($credentials['port']); 1054 } 1055 1056 // Determine connection type available 1057 if ( ( defined( 'FTP_SSH' ) && FTP_SSH ) || ( defined( 'FS_METHOD' ) && 'ssh2' == FS_METHOD ) ) { 1058 $credentials['connection_type'] = 'ssh'; 1059 } elseif ( ( defined( 'FTP_SSL' ) && FTP_SSL ) && 'ftpext' == $type ) { //Only the FTP Extension understands SSL 1060 $credentials['connection_type'] = 'ftps'; 1061 } elseif ( ! empty( $_POST['connection_type'] ) ) { 1062 $credentials['connection_type'] = wp_unslash( $_POST['connection_type'] ); 1063 } elseif ( ! isset( $credentials['connection_type'] ) ) { //All else fails (And it's not defaulted to something else saved), Default to FTP 1064 $credentials['connection_type'] = 'ftp'; 1065 } 1066 1067 return $credentials; 1068 } 1069 1070 /** 1071 * Check credentials for required parameters. 1072 * 1073 * Depending on the connection_type certain information is needed to be able to 1074 * attempt a connection. 1075 * 1076 * Type of connection: 1077 * 1078 * - direct: needs no information 1079 * - ssh: public and private keys 1080 * - other: hostname(:port), username and password 1081 * 1082 * Plugins may override this check by returning true|false via the 1083 * {@see 'request_filesystem_credentials'} filter. 1084 * 1085 * @since 4.2.0 1086 * 1087 * @param array $credentials the data to verify entered parameters on. 1088 * 1089 * @param array $args { 1090 * Optional. Arguments to feed to the filter. Default empty array. 1091 * @type string $form_post the URL to post the form to. Default ''. Accepts URL. 1092 * @type string $type the chosen Filesystem method in use. Default ''. 1093 * @type bool $error if the current request has failed to connect. Default False. 1094 * @type string $context The directory which is needed access to, the write-test will be performed on this 1095 * directory by get_filesystem_method(). Default False. 1096 * @type array $extra_fields Extra POST fields which should be checked for to be included in the post. Default null. 1097 * @type bool $allow_relaxed_file_ownership Whether to allow Group/World writable. Default False. 1098 * } 1099 * 1100 * @return bool True when all required parameters have been set for supplied type, 1101 * False when parameter is missing or empty. 1102 */ 1103 function usable_filesystem_credentials($credentials, $args = array()) { 1104 $defaults = array( 1105 'form_post' => '', 1106 'type' => '', 1107 'error' => false, 1108 'context' => false, 1109 'extra_fields' => null, 1110 'allow_relaxed_file_ownership' => false 1111 ); 1112 1113 $args = wp_parse_args( $args, $defaults ); 1114 1115 // extract items 1116 $form_post = $args['form_post']; 1117 $type = $args['type']; 1118 $error = $args['error']; 1119 $context = $args['context']; 1120 $extra_fields = $args['extra_fields']; 1121 $allow_relaxed_file_ownership = $args['allow_relaxed_file_ownership']; 1122 1123 /** This filter is documented in wp-includes/file.php */ 1124 $req_cred = apply_filters( 'request_filesystem_credentials', '', $form_post, $type, $error, $context, $extra_fields, $allow_relaxed_file_ownership ); 1125 if ( '' !== $req_cred ) 1126 return $req_cred; 1127 1128 1129 // We need something to check against 1130 if ( empty( $credentials ) ) { 1131 return false; 1132 } 1133 1134 // All the checks required an array for parameters; exit if we got something else 1135 if ( ! is_array( $credentials ) ) { 1136 return false; 1137 } 1138 1139 if ( isset( $credentials['connection_type'] ) ) { 1140 if ( 'direct' == $credentials['connection_type'] ) { 1141 return true; 1142 } 1143 1144 // SSH needs public and private key 1145 if ( 'ssh' == $credentials['connection_type'] ) { 1146 if ( ! isset( $credentials['public_key'], $credentials['private_key'] ) ) { 1147 return false; 936 1148 } 937 1149 938 @fclose($temp_handle); 939 @unlink($temp_file_name); 1150 return ( ! empty( $credentials['public_key'] ) && ! empty( $credentials['private_key'] ) ); 940 1151 } 941 1152 } 942 1153 943 if ( ! $method && isset($args['connection_type']) && 'ssh' == $args['connection_type'] && extension_loaded('ssh2') && function_exists('stream_get_contents') ) $method = 'ssh2'; 944 if ( ! $method && extension_loaded('ftp') ) $method = 'ftpext'; 945 if ( ! $method && ( extension_loaded('sockets') || function_exists('fsockopen') ) ) $method = 'ftpsockets'; //Sockets: Socket extension; PHP Mode: FSockopen / fwrite / fread 1154 // Other connection methods need hostname, password and username 1155 if ( ! isset( $credentials['password'], $credentials['username'], $credentials['hostname'] ) ) { 1156 return false; 1157 } 946 1158 947 /** 948 * Filter the filesystem method to use. 949 * 950 * @since 2.6.0 951 * 952 * @param string $method Filesystem method to return. 953 * @param array $args An array of connection details for the method. 954 * @param string $context Full path to the directory that is tested for being writable. 955 * @param bool $allow_relaxed_file_ownership Whether to allow Group/World writable. 956 */ 957 return apply_filters( 'filesystem_method', $method, $args, $context, $allow_relaxed_file_ownership ); 1159 return ( ! empty( $credentials['password'] ) && ! empty( $credentials['username'] ) && ! empty( $credentials['hostname'] ) ); 958 1160 } 959 1161 960 1162 /** … … 971 1173 * 972 1174 * @since 2.5. 973 1175 * 974 * @todo Properly mark optional arguments as such 975 * 976 * @param string $form_post the URL to post the form to 977 * @param string $type the chosen Filesystem method in use 978 * @param boolean $error if the current request has failed to connect 979 * @param string $context The directory which is needed access to, The write-test will be performed on this directory by get_filesystem_method() 980 * @param array $extra_fields Extra POST fields which should be checked for to be included in the post. 981 * @param bool $allow_relaxed_file_ownership Whether to allow Group/World writable. 1176 * @param string $form_post the URL to post the form to. 1177 * @param string $type Optional. the chosen Filesystem method in use. 1178 * @param boolean $error Optional. if the current request has failed to connect. 1179 * @param string $context Optional. The directory which is needed access to,The write-test will be performed on this directory by get_filesystem_method(). 1180 * @param array $extra_fields Optional. Extra POST fields which should be checked for to be included in the post. 1181 * @param bool $allow_relaxed_file_ownership Optional. Whether to allow Group/World writable. 982 1182 * @return boolean False on failure. True on success. 983 1183 */ 984 1184 function request_filesystem_credentials($form_post, $type = '', $error = false, $context = false, $extra_fields = null, $allow_relaxed_file_ownership = false ) { 985 986 1185 /** 987 1186 * Filter the filesystem credentials form output. 988 1187 * … … 1005 1204 if ( '' !== $req_cred ) 1006 1205 return $req_cred; 1007 1206 1008 if ( empty($type) ) { 1207 1208 // If no type is supplied, check to see if 'direct' method can be used. 1209 if ( empty( $type ) ) { 1009 1210 $type = get_filesystem_method( array(), $context, $allow_relaxed_file_ownership ); 1010 1211 } 1011 1212 1012 if ( 'direct' == $type ) 1213 if ( 'direct' == $type ) { 1013 1214 return true; 1215 } 1014 1216 1015 if ( is_null( $extra_fields ) ) 1016 $extra_fields = array( 'version', 'locale' ); 1217 $args = array( 1218 'form_post' => $form_post, 1219 'type' => $type, 1220 'error' => $error, 1221 'context' => $context, 1222 'extra_fields' => $extra_fields, 1223 'allow_relaxed_file_ownership' => $allow_relaxed_file_ownership 1224 ); 1017 1225 1018 $credentials = get_ option('ftp_credentials', array( 'hostname' => '', 'username' => ''));1226 $credentials = get_filesystem_credentials( $args ); 1019 1227 1020 // 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) 1021 $credentials['hostname'] = defined('FTP_HOST') ? FTP_HOST : (!empty($_POST['hostname']) ? wp_unslash( $_POST['hostname'] ) : $credentials['hostname']); 1022 $credentials['username'] = defined('FTP_USER') ? FTP_USER : (!empty($_POST['username']) ? wp_unslash( $_POST['username'] ) : $credentials['username']); 1023 $credentials['password'] = defined('FTP_PASS') ? FTP_PASS : (!empty($_POST['password']) ? wp_unslash( $_POST['password'] ) : ''); 1228 if ( 'direct' == $credentials['connection_type'] ) { 1229 return true; 1230 } 1024 1231 1025 // Check to see if we are setting the public/private keys for ssh 1026 $credentials['public_key'] = defined('FTP_PUBKEY') ? FTP_PUBKEY : (!empty($_POST['public_key']) ? wp_unslash( $_POST['public_key'] ) : ''); 1027 $credentials['private_key'] = defined('FTP_PRIKEY') ? FTP_PRIKEY : (!empty($_POST['private_key']) ? wp_unslash( $_POST['private_key'] ) : ''); 1232 if ( ! $error && usable_filesystem_credentials( $credentials ) ) { 1028 1233 1029 // Sanitize the hostname, Some people might pass in odd-data:1030 $credentials['hostname'] = preg_replace('|\w+://|', '', $credentials['hostname']); //Strip any schemes off1031 1032 if ( strpos($credentials['hostname'], ':') ) {1033 list( $credentials['hostname'], $credentials['port'] ) = explode(':', $credentials['hostname'], 2);1034 if ( ! is_numeric($credentials['port']) )1035 unset($credentials['port']);1036 } else {1037 unset($credentials['port']);1038 }1039 1040 if ( ( defined( 'FTP_SSH' ) && FTP_SSH ) || ( defined( 'FS_METHOD' ) && 'ssh2' == FS_METHOD ) ) {1041 $credentials['connection_type'] = 'ssh';1042 } elseif ( ( defined( 'FTP_SSL' ) && FTP_SSL ) && 'ftpext' == $type ) { //Only the FTP Extension understands SSL1043 $credentials['connection_type'] = 'ftps';1044 } elseif ( ! empty( $_POST['connection_type'] ) ) {1045 $credentials['connection_type'] = wp_unslash( $_POST['connection_type'] );1046 } elseif ( ! isset( $credentials['connection_type'] ) ) { //All else fails (And it's not defaulted to something else saved), Default to FTP1047 $credentials['connection_type'] = 'ftp';1048 }1049 if ( ! $error &&1050 (1051 ( !empty($credentials['password']) && !empty($credentials['username']) && !empty($credentials['hostname']) ) ||1052 ( 'ssh' == $credentials['connection_type'] && !empty($credentials['public_key']) && !empty($credentials['private_key']) )1053 ) ) {1054 1234 $stored_credentials = $credentials; 1055 if ( !empty($stored_credentials['port']) ) //save port as part of hostname to simplify above code. 1235 if ( ! empty( $stored_credentials['port'] ) ) //save port as part of hostname to simplify retrievement code 1236 { 1056 1237 $stored_credentials['hostname'] .= ':' . $stored_credentials['port']; 1238 } 1057 1239 1058 unset($stored_credentials['password'], $stored_credentials['port'], $stored_credentials['private_key'], $stored_credentials['public_key']); 1240 unset( $stored_credentials['password'], $stored_credentials['port'], $stored_credentials['private_key'], $stored_credentials['public_key'] ); 1241 1059 1242 if ( ! defined( 'WP_INSTALLING' ) ) { 1060 1243 update_option( 'ftp_credentials', $stored_credentials ); 1061 1244 } 1245 1062 1246 return $credentials; 1063 1247 } 1248 1249 // Output the request for credentials to the user 1250 $args = array( 1251 'form_post' => $form_post, 1252 'credentials' => $credentials, 1253 'type' => $type, 1254 'error' => $error, 1255 'context' => $context, 1256 'extra_fiels' => $extra_fields, 1257 'allow_relaxed_file_ownership' => $allow_relaxed_file_ownership 1258 ); 1259 1260 request_filesystem_credentials_form( $args ); 1261 1262 // Nothing usable has been found yet. 1263 return false; 1264 } 1265 1266 /** 1267 * Displays the form to request needed credentials in order to have sufficient 1268 * filesystem control. 1269 * 1270 * @since 4.2.0 1271 * 1272 * @param array $args { 1273 * Optional. Arguments for pre-filling the form. Default empty array. 1274 * @type string $form_post the URL to post the form to. Default ''. Accepts URL. 1275 * @type array $credentials credentials that will be pre-filled in the form. Default empty array. 1276 * @type bool $error if the current request has failed to connect. Default False. 1277 * @type string $context The directory which is needed access to, 1278 * The write-test will be performed on this directory 1279 * by get_filesystem_method(). Default false. 1280 * @type array $extra_fields Extra POST fields which should be checked for to be included in the post. Default null. 1281 * @type bool $allow_relaxed_file_ownership Whether to allow Group/World writable. Default False. 1282 * } 1283 */ 1284 function request_filesystem_credentials_form($args = array()) { 1285 $defaults = array( 1286 'form_post' => '', 1287 'credentials' => array(), 1288 'type' => '', 1289 'error' => false, 1290 'context' => false, 1291 'extra_fields' => null, 1292 'allow_relaxed_file_ownership' => false 1293 ); 1294 1295 $args = wp_parse_args( $args, $defaults ); 1296 1297 // extract variables from args 1298 $form_post = $args['form_post']; 1299 $credentials = $args['credentials']; 1300 $type = $args['type']; 1301 $error = $args['error']; 1302 $context = $args['context']; 1303 $extra_fields = $args['extra_fields']; 1304 $allow_relaxed_file_ownership = $args['allow_relaxed_file_ownership']; 1305 1306 if ( empty( $type ) ) { 1307 $type = get_filesystem_method( array(), $context, $allow_relaxed_file_ownership ); 1308 } 1309 1310 if ( ! is_array($credentials)) { 1311 $credentials = array(); 1312 } 1313 1064 1314 $hostname = isset( $credentials['hostname'] ) ? $credentials['hostname'] : ''; 1065 1315 $username = isset( $credentials['username'] ) ? $credentials['username'] : ''; 1066 1316 $public_key = isset( $credentials['public_key'] ) ? $credentials['public_key'] : ''; … … 1068 1318 $port = isset( $credentials['port'] ) ? $credentials['port'] : ''; 1069 1319 $connection_type = isset( $credentials['connection_type'] ) ? $credentials['connection_type'] : ''; 1070 1320 1321 if ( is_null( $args['extra_fields'] ) ) 1322 $extra_fields = array( 'version', 'locale' ); 1323 1071 1324 if ( $error ) { 1072 1325 $error_string = __('<strong>ERROR:</strong> There was an error connecting to the server, Please verify the settings are correct.'); 1073 1326 if ( is_wp_error($error) ) … … 1075 1328 echo '<div id="message" class="error"><p>' . $error_string . '</p></div>'; 1076 1329 } 1077 1330 1331 1332 // Detect available types by extension 1078 1333 $types = array(); 1079 1334 if ( extension_loaded('ftp') || extension_loaded('sockets') || function_exists('fsockopen') ) 1080 1335 $types[ 'ftp' ] = __('FTP'); … … 1190 1445 </div> 1191 1446 </form> 1192 1447 <?php 1193 return false; 1448 1194 1449 } -
tests/phpunit/tests/filesystem/credentials.php
1 <?php 2 3 /** 4 * @group filesystem 5 * @group wp-filesystem 6 */ 7 8 /** 9 * Verification of filesystem credentials retrievement and validation. 10 * 11 * We cannot use WP_Filesystem_UnitTestCase because filesystem method 'MockFS' will influence test results. 12 */ 13 class Tests_Filesystem_Credentials extends WP_UnitTestCase { 14 15 public function tearDown() { 16 $this->clear_credentials_option(); 17 } 18 19 /** 20 * Direct type does not need credentials 21 */ 22 function test_direct_credentials_retrievement() { 23 // test direct type 24 $credentials = get_filesystem_credentials( array('type' => 'direct' ) ); 25 $this->assertInternalType( 'array', $credentials ); 26 $this->assertArrayHasKey( 'connection_type', $credentials ); 27 $this->assertEquals( 'direct', $credentials['connection_type'] ); 28 } 29 30 function test_credentials_retrievement_filter_override() { 31 add_filter( 'filesystem_method', array($this, 'filter_filesystem_method') ); 32 33 $credentials = get_filesystem_credentials(); 34 35 $this->assertInternalType( 'array', $credentials ); 36 $this->assertArrayHasKey( 'connection_type', $credentials ); 37 $this->assertNotEquals( 'direct', $credentials['connection_type'] ); 38 39 remove_filter( 'filesystem_method', array($this, 'filter_filesystem_method') ); 40 } 41 42 /** 43 * No variables set; test for expected parameters 44 */ 45 function test_credentials_retrievement() { 46 // setting type to anything but 'direct' 47 $credentials = get_filesystem_credentials( array('type' => 'ssh') ); 48 49 $this->assertInternalType( 'array', $credentials ); 50 51 $this->assertArrayHasKey( 'connection_type', $credentials ); 52 $this->assertArrayHasKey( 'private_key', $credentials ); 53 $this->assertArrayHasKey( 'public_key', $credentials ); 54 $this->assertArrayHasKey( 'hostname', $credentials ); 55 $this->assertArrayHasKey( 'username', $credentials ); 56 $this->assertArrayHasKey( 'password', $credentials ); 57 58 $this->assertEquals( '', $credentials['private_key'] ); 59 $this->assertEquals( '', $credentials['public_key'] ); 60 $this->assertEquals( '', $credentials['hostname'] ); 61 $this->assertEquals( '', $credentials['username'] ); 62 $this->assertEquals( '', $credentials['password'] ); 63 } 64 65 /** 66 * When credentials are saved to options; these should be applied 67 */ 68 function test_saved_credentials_retrievement() { 69 // test saved variables 70 71 $this->set_credentials_option(); 72 73 $credentials = get_filesystem_credentials( array('type' => 'ftp') ); 74 75 $this->assertEquals( '', $credentials['private_key'] ); 76 $this->assertEquals( '', $credentials['public_key'] ); 77 $this->assertEquals( '', $credentials['password'] ); 78 $this->assertEquals( 'wordpress.org', $credentials['hostname'] ); 79 $this->assertEquals( 'wordpress', $credentials['username'] ); 80 $this->assertEquals( 'ftp', $credentials['connection_type'] ); 81 } 82 83 /** 84 * When credentials are submitted to the page; these take precedence over saved variables; 85 */ 86 function test_submitted_credentials_retrievement() { 87 // test retrieving of submitted data 88 $_POST['hostname'] = rand_str(); 89 $_POST['private_key'] = rand_str(); 90 $_POST['public_key'] = rand_str(); 91 $_POST['username'] = rand_str(); 92 $_POST['password'] = rand_str(); 93 94 // set option variables; to see if they aren't used 95 $this->set_credentials_option(); 96 97 $credentials = get_filesystem_credentials( array('type' => 'ftp') ); 98 99 // saved variables are set but should be ignored! 100 $this->assertEquals( $_POST['private_key'], $credentials['private_key'] ); 101 $this->assertEquals( $_POST['public_key'], $credentials['public_key'] ); 102 $this->assertEquals( $_POST['hostname'], $credentials['hostname'] ); 103 $this->assertEquals( $_POST['username'], $credentials['username'] ); 104 $this->assertEquals( $_POST['password'], $credentials['password'] ); 105 $this->assertEquals( 'ftp', $credentials['connection_type'] ); 106 107 unset($_POST['hostname'], $_POST['private_key'], $_POST['public_key'], $_POST['username'], $_POST['password']); 108 } 109 110 /** 111 * Direct connection does not need credentials, passing only the connection_type is sufficient 112 */ 113 function test_usable_direct_credentials() { 114 $credentials = array('connection_type' => 'direct'); 115 $this->assertTrue( usable_filesystem_credentials( $credentials ) ); 116 } 117 118 /** 119 * Test for SSH parameter checks 120 */ 121 function test_usable_ssh_credentials() { 122 // ssh: 123 $credentials = get_filesystem_credentials( array('type' => 'ssh' ) ); 124 $credentials['connection_type'] = 'ssh'; 125 126 // missing private_key & public_key 127 $this->assertFalse( usable_filesystem_credentials( $credentials ) ); 128 129 // set private_key & public_key 130 $credentials['private_key'] = 'private'; 131 $credentials['public_key'] = 'public'; 132 $this->assertTrue( usable_filesystem_credentials( $credentials ) ); 133 } 134 135 /** 136 * Test for SSH2 parameter checks 137 */ 138 function test_usable_ssh2_credentials() { 139 // ssh2 140 $credentials = array( 141 'connection_type' => 'ssh2' 142 ); 143 144 $this->assertFalse( usable_filesystem_credentials( $credentials ) ); 145 146 $credentials = array( 147 'public_key' => 'a', 148 'private_key' => 'b', 149 'connection_type' => 'ssh2' 150 ); 151 $this->assertFalse( usable_filesystem_credentials( $credentials ) ); 152 153 $credentials = array( 154 'hostname' => 'a', 155 'username' => 'b', 156 'password' => 'c', 157 'connection_type' => 'ssh2' 158 ); 159 $this->assertTrue( usable_filesystem_credentials( $credentials ) ); 160 } 161 162 /** 163 * Test for expected results with FTP or other credentials 164 */ 165 function test_usable_ftp_credentials() { 166 // required elements are empty 167 $credentials = array( 168 'hostname' => '', 169 'username' => '', 170 'password' => '', 171 'connection_type' => 'ftp' 172 ); 173 $this->assertFalse( usable_filesystem_credentials( $credentials ) ); 174 175 // required elements are missing 176 $credentials = array( 177 'hostname' => 'localhost', 178 'connection_type' => 'ftp' 179 ); 180 $this->assertFalse( usable_filesystem_credentials( $credentials ) ); 181 182 // required elements are set 183 $credentials = array( 184 'hostname' => 'a', 185 'username' => 'b', 186 'password' => 'c', 187 'connection_type' => 'ftp' 188 ); 189 $this->assertTrue( usable_filesystem_credentials( $credentials ) ); 190 } 191 192 /** 193 * Test if the 'request_filesystem_credentials' filter is applied properly 194 */ 195 function test_usable_credentials_filter_override() { 196 // sufficient credentials: 197 $credentials = array( 198 'hostname' => 'a', 199 'username' => 'b', 200 'password' => 'c', 201 'connection_type' => 'ftp' 202 ); 203 204 $this->assertTrue( usable_filesystem_credentials( $credentials, array('type' => 'ftp') ) ); 205 206 // force a failure 207 add_filter( 'request_filesystem_credentials', '__return_false' ); 208 209 $usable = usable_filesystem_credentials( $credentials, array('type' => 'ftp') ); 210 $this->assertFalse( $usable ); 211 212 remove_filter( 'request_filesystem_credentials', '__return_false' ); 213 214 215 216 // insufficient credentials: 217 $credentials = array( 218 'public_key' => '', 219 'private_key' => '', 220 'connection_type' => 'ssh' 221 ); 222 223 $this->assertFalse( usable_filesystem_credentials( $credentials, array('type' => 'ssh') ) ); 224 225 // force a success 226 add_filter( 'request_filesystem_credentials', '__return_true' ); 227 228 $usable = usable_filesystem_credentials( $credentials, array('type' => 'ssh') ); 229 $this->assertTrue( $usable ); 230 231 // clean up filter 232 remove_filter( 'request_filesystem_credentials', '__return_true' ); 233 } 234 235 /** Helper functions */ 236 function set_credentials_option() { 237 $credentials = array(); 238 $credentials['username'] = 'wordpress'; 239 $credentials['hostname'] = 'wordpress.org'; 240 update_option('ftp_credentials', $credentials); 241 } 242 243 function clear_credentials_option() { 244 delete_option('ftp_credentials'); 245 } 246 247 public static function filter_filesystem_method() { 248 // anything but 'direct' 249 return 'ftp'; 250 } 251 }