phpseclib\Net\SFTP::_list PHP Method

_list() public method

Reads a list, be it detailed or not, of files in the given directory
public _list ( string $dir, boolean $raw = true ) : mixed
$dir string
$raw boolean
return mixed
    function _list($dir, $raw = true)
    {
        if (!($this->bitmap & SSH2::MASK_LOGIN)) {
            return false;
        }
        $dir = $this->_realpath($dir . '/');
        if ($dir === false) {
            return false;
        }
        // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.1.2
        if (!$this->_send_sftp_packet(NET_SFTP_OPENDIR, pack('Na*', strlen($dir), $dir))) {
            return false;
        }
        $response = $this->_get_sftp_packet();
        switch ($this->packet_type) {
            case NET_SFTP_HANDLE:
                // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-9.2
                // since 'handle' is the last field in the SSH_FXP_HANDLE packet, we'll just remove the first four bytes that
                // represent the length of the string and leave it at that
                $handle = substr($response, 4);
                break;
            case NET_SFTP_STATUS:
                // presumably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED
                $this->_logError($response);
                return false;
            default:
                throw new \UnexpectedValueException('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS');
        }
        $this->_update_stat_cache($dir, array());
        $contents = array();
        while (true) {
            // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.2.2
            // why multiple SSH_FXP_READDIR packets would be sent when the response to a single one can span arbitrarily many
            // SSH_MSG_CHANNEL_DATA messages is not known to me.
            if (!$this->_send_sftp_packet(NET_SFTP_READDIR, pack('Na*', strlen($handle), $handle))) {
                return false;
            }
            $response = $this->_get_sftp_packet();
            switch ($this->packet_type) {
                case NET_SFTP_NAME:
                    if (strlen($response) < 4) {
                        return false;
                    }
                    extract(unpack('Ncount', Strings::shift($response, 4)));
                    for ($i = 0; $i < $count; $i++) {
                        if (strlen($response) < 4) {
                            return false;
                        }
                        extract(unpack('Nlength', Strings::shift($response, 4)));
                        $shortname = Strings::shift($response, $length);
                        if (strlen($response) < 4) {
                            return false;
                        }
                        extract(unpack('Nlength', Strings::shift($response, 4)));
                        $longname = Strings::shift($response, $length);
                        $attributes = $this->_parseAttributes($response);
                        if (!isset($attributes['type'])) {
                            $fileType = $this->_parseLongname($longname);
                            if ($fileType) {
                                $attributes['type'] = $fileType;
                            }
                        }
                        $contents[$shortname] = $attributes + array('filename' => $shortname);
                        if (isset($attributes['type']) && $attributes['type'] == NET_SFTP_TYPE_DIRECTORY && ($shortname != '.' && $shortname != '..')) {
                            $this->_update_stat_cache($dir . '/' . $shortname, array());
                        } else {
                            if ($shortname == '..') {
                                $temp = $this->_realpath($dir . '/..') . '/.';
                            } else {
                                $temp = $dir . '/' . $shortname;
                            }
                            $this->_update_stat_cache($temp, (object) array('lstat' => $attributes));
                        }
                        // SFTPv6 has an optional boolean end-of-list field, but we'll ignore that, since the
                        // final SSH_FXP_STATUS packet should tell us that, already.
                    }
                    break;
                case NET_SFTP_STATUS:
                    if (strlen($response) < 4) {
                        return false;
                    }
                    extract(unpack('Nstatus', Strings::shift($response, 4)));
                    if ($status != NET_SFTP_STATUS_EOF) {
                        $this->_logError($response, $status);
                        return false;
                    }
                    break 2;
                default:
                    throw new \UnexpectedValueException('Expected SSH_FXP_NAME or SSH_FXP_STATUS');
            }
        }
        if (!$this->_close_handle($handle)) {
            return false;
        }
        if (count($this->sortOptions)) {
            uasort($contents, array(&$this, '_comparator'));
        }
        return $raw ? $contents : array_keys($contents);
    }