+/**
+ * Displays a form to the user to request for their FTP/SSH details in order
+ * to connect to the filesystem.
+ *
+ * All chosen/entered details are saved, Excluding the Password.
+ *
+ * Hostnames may be in the form of hostname:portnumber (eg: wordpress.org:2467)
+ * to specify an alternate FTP/SSH port.
+ *
+ * Plugins may override this form by returning true|false via the
+ * {@see 'request_filesystem_credentials'} filter.
+ *
+ * @since 2.5.
+ *
+ * @todo Properly mark optional arguments as such
+ *
+ * @param string $form_post the URL to post the form to
+ * @param string $type the chosen Filesystem method in use
+ * @param boolean $error if the current request has failed to connect
+ * @param string $context The directory which is needed access to, The write-test will be performed on this directory by get_filesystem_method()
+ * @param string $extra_fields Extra POST fields which should be checked for to be included in the post.
+ * @param bool $allow_relaxed_file_ownership Whether to allow Group/World writable.
+ * @return boolean False on failure. True on success.
+ */
+function request_filesystem_credentials($form_post, $type = '', $error = false, $context = false, $extra_fields = null, $allow_relaxed_file_ownership = false ) {
+
+ /**
+ * Filter the filesystem credentials form output.
+ *
+ * Returning anything other than an empty string will effectively short-circuit
+ * output of the filesystem credentials form, returning that value instead.
+ *
+ * @since 2.5.0
+ *
+ * @param mixed $output Form output to return instead. Default empty.
+ * @param string $form_post URL to POST the form to.
+ * @param string $type Chosen type of filesystem.
+ * @param bool $error Whether the current request has failed to connect.
+ * Default false.
+ * @param string $context Full path to the directory that is tested for
+ * being writable.
+ * @param bool $allow_relaxed_file_ownership Whether to allow Group/World writable.
+ * @param array $extra_fields Extra POST fields.
+ */
+ $req_cred = apply_filters( 'request_filesystem_credentials', '', $form_post, $type, $error, $context, $extra_fields, $allow_relaxed_file_ownership );
+ if ( '' !== $req_cred )
+ return $req_cred;
+
+ if ( empty($type) ) {
+ $type = get_filesystem_method( array(), $context, $allow_relaxed_file_ownership );
+ }
+
+ if ( 'direct' == $type )
+ return true;
+
+ if ( is_null( $extra_fields ) )
+ $extra_fields = array( 'version', 'locale' );
+
+ $credentials = get_option('ftp_credentials', array( 'hostname' => '', 'username' => ''));
+
+ // 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)
+ $credentials['hostname'] = defined('FTP_HOST') ? FTP_HOST : (!empty($_POST['hostname']) ? wp_unslash( $_POST['hostname'] ) : $credentials['hostname']);
+ $credentials['username'] = defined('FTP_USER') ? FTP_USER : (!empty($_POST['username']) ? wp_unslash( $_POST['username'] ) : $credentials['username']);
+ $credentials['password'] = defined('FTP_PASS') ? FTP_PASS : (!empty($_POST['password']) ? wp_unslash( $_POST['password'] ) : '');
+
+ // Check to see if we are setting the public/private keys for ssh
+ $credentials['public_key'] = defined('FTP_PUBKEY') ? FTP_PUBKEY : (!empty($_POST['public_key']) ? wp_unslash( $_POST['public_key'] ) : '');
+ $credentials['private_key'] = defined('FTP_PRIKEY') ? FTP_PRIKEY : (!empty($_POST['private_key']) ? wp_unslash( $_POST['private_key'] ) : '');
+
+ // Sanitize the hostname, Some people might pass in odd-data:
+ $credentials['hostname'] = preg_replace('|\w+://|', '', $credentials['hostname']); //Strip any schemes off
+
+ if ( strpos($credentials['hostname'], ':') ) {
+ list( $credentials['hostname'], $credentials['port'] ) = explode(':', $credentials['hostname'], 2);
+ if ( ! is_numeric($credentials['port']) )
+ unset($credentials['port']);
+ } else {
+ unset($credentials['port']);
+ }
+
+ if ( ( defined('FTP_SSH') && FTP_SSH ) || ( defined('FS_METHOD') && 'ssh2' == FS_METHOD ) )
+ $credentials['connection_type'] = 'ssh';
+ else if ( (defined('FTP_SSL') && FTP_SSL) && 'ftpext' == $type ) //Only the FTP Extension understands SSL
+ $credentials['connection_type'] = 'ftps';
+ else if ( !empty($_POST['connection_type']) )
+ $credentials['connection_type'] = wp_unslash( $_POST['connection_type'] );
+ else if ( !isset($credentials['connection_type']) ) //All else fails (And it's not defaulted to something else saved), Default to FTP
+ $credentials['connection_type'] = 'ftp';
+
+ if ( ! $error &&
+ (
+ ( !empty($credentials['password']) && !empty($credentials['username']) && !empty($credentials['hostname']) ) ||
+ ( 'ssh' == $credentials['connection_type'] && !empty($credentials['public_key']) && !empty($credentials['private_key']) )
+ ) ) {
+ $stored_credentials = $credentials;
+ if ( !empty($stored_credentials['port']) ) //save port as part of hostname to simplify above code.
+ $stored_credentials['hostname'] .= ':' . $stored_credentials['port'];
+
+ unset($stored_credentials['password'], $stored_credentials['port'], $stored_credentials['private_key'], $stored_credentials['public_key']);
+ if ( ! defined( 'WP_INSTALLING' ) ) {
+ update_option( 'ftp_credentials', $stored_credentials );
+ }
+ return $credentials;
+ }
+ $hostname = isset( $credentials['hostname'] ) ? $credentials['hostname'] : '';
+ $username = isset( $credentials['username'] ) ? $credentials['username'] : '';
+ $public_key = isset( $credentials['public_key'] ) ? $credentials['public_key'] : '';
+ $private_key = isset( $credentials['private_key'] ) ? $credentials['private_key'] : '';
+ $port = isset( $credentials['port'] ) ? $credentials['port'] : '';
+ $connection_type = isset( $credentials['connection_type'] ) ? $credentials['connection_type'] : '';
+
+ if ( $error ) {
+ $error_string = __('<strong>ERROR:</strong> There was an error connecting to the server, Please verify the settings are correct.');
+ if ( is_wp_error($error) )
+ $error_string = esc_html( $error->get_error_message() );
+ echo '<div id="message" class="error"><p>' . $error_string . '</p></div>';
+ }
+
+ $types = array();
+ if ( extension_loaded('ftp') || extension_loaded('sockets') || function_exists('fsockopen') )
+ $types[ 'ftp' ] = __('FTP');
+ if ( extension_loaded('ftp') ) //Only this supports FTPS
+ $types[ 'ftps' ] = __('FTPS (SSL)');
+ if ( extension_loaded('ssh2') && function_exists('stream_get_contents') )
+ $types[ 'ssh' ] = __('SSH2');
+
+ /**
+ * Filter the connection types to output to the filesystem credentials form.
+ *
+ * @since 2.9.0
+ *
+ * @param array $types Types of connections.
+ * @param array $credentials Credentials to connect with.
+ * @param string $type Chosen filesystem method.
+ * @param object $error Error object.
+ * @param string $context Full path to the directory that is tested
+ * for being writable.
+ */
+ $types = apply_filters( 'fs_ftp_connection_types', $types, $credentials, $type, $error, $context );
+