def do_LIST(self, path): try: _path = self.ftp_path(path) with self.config.vfs.check_access(path=_path, user=self._uid, perms="r"): listing = self.config.vfs.listdir(_path) if isinstance(listing, list): # RFC 959 recommends the listing to be sorted. listing.sort() iterator = self.config.vfs.format_list(_path, listing) self.respond("150 Here comes the directory listing.") _list_data = get_data_from_iter(iterator) # Push data to the data channel self.push_data(_list_data.encode()) # start the command channel self.start_data_channel() self.respond(b"226 Directory send OK.") except FSOperationNotPermitted: self.respond(b"500 Operation not permitted.") except ( OSError, fs.errors.FSError, FilesystemError, FTPPrivilegeException, ) as err: self._log_err(err) self.respond(b"550 LIST command failed.")
def do_STAT(self, path): """If invoked without parameters, returns general status information about the FTP server process. If a parameter is given, acts like the LIST command, except that data is sent over the command channel (no PORT or PASV command is required). """ # return STATus information about ftp data connection if not path: s = list() s.append('Connected to: {}:{}'.format(self.host, self.port)) if self.authenticated: s.append('Logged in as: {}'.format(self.username)) else: if not self.username: s.append("Waiting for username.") else: s.append("Waiting for password.") if self._current_type == 'a': _type = 'ASCII' else: _type = 'Binary' s.append("TYPE: {}; STRUcture: File; MODE: Stream".format(_type)) if self._data_sock is not None and self._data_channel is False: s.append('Passive data channel waiting for connection.') elif self._data_channel is True: bytes_sent = self.metrics.data_channel_bytes_send + self.metrics.command_chanel_bytes_send bytes_recv = self.metrics.command_chanel_bytes_recv + self.metrics.data_channel_bytes_recv elapsed_time = self.metrics.get_elapsed_time() s.append('Data connection open:') s.append('Total bytes sent: {}'.format(bytes_sent)) s.append('Total bytes received: {}'.format(bytes_recv)) s.append('Transfer elapsed time: {} secs'.format(elapsed_time)) else: s.append('Data connection closed.') self.respond('211-FTP server status:\r\n') self.respond(''.join([' {}\r\n'.format(item) for item in s])) self.respond('211 End of status.') # return directory LISTing over the command channel else: try: line = self.ftp_path(path) with self.config.vfs.check_access(path=line, user=self._uid, perms='r'): if self.config.vfs.isdir(path): listing = self.config.vfs.listdir(path) # RFC 959 recommends the listing to be sorted. listing.sort() iterator = self.config.vfs.format_list(path, listing) else: basedir, filename = os.path.split(path) self.config.stat(path) iterator = self.config.vfs.format_list(basedir, [filename]) _status = '213-Status of "{}":\r\n'.format(line) _status += get_data_from_iter(iterator) _status += '213 End of status.' self.respond(_status.encode()) except FSOperationNotPermitted: self.respond(b'500 Operation not permitted.') except (OSError, FilesystemError, AssertionError, fs.errors.FSError, FTPPrivilegeException): self.respond(b'550 STAT command failed.')
def do_LIST(self, path): try: _path = self.ftp_path(path) with self.config.vfs.check_access(path=_path, user=self._uid, perms='r'): listing = self.config.vfs.listdir(_path) if isinstance(listing, list): # RFC 959 recommends the listing to be sorted. listing.sort() iterator = self.config.vfs.format_list(_path, listing) self.respond('150 Here comes the directory listing.') _list_data = get_data_from_iter(iterator) # Push data to the data channel self.push_data(_list_data.encode()) # start the command channel self.start_data_channel() self.respond(b'226 Directory send OK.') except FSOperationNotPermitted: self.respond(b'500 Operation not permitted.') except (OSError, fs.errors.FSError, FilesystemError, FTPPrivilegeException) as err: self._log_err(err) self.respond(b'550 LIST command failed.')
def do_STAT(self, path): """If invoked without parameters, returns general status information about the FTP server process. If a parameter is given, acts like the LIST command, except that data is sent over the command channel (no PORT or PASV command is required). """ # return STATus information about ftp data connection if not path: s = list() s.append("Connected to: {}:{}".format(self.host, self.port)) if self.authenticated: s.append("Logged in as: {}".format(self.username)) else: if not self.username: s.append("Waiting for username.") else: s.append("Waiting for password.") if self._current_type == "a": _type = "ASCII" else: _type = "Binary" s.append("TYPE: {}; STRUcture: File; MODE: Stream".format(_type)) if self._data_sock is not None and self._data_channel is False: s.append("Passive data channel waiting for connection.") elif self._data_channel is True: bytes_sent = (self.metrics.data_channel_bytes_send + self.metrics.command_chanel_bytes_send) bytes_recv = (self.metrics.command_chanel_bytes_recv + self.metrics.data_channel_bytes_recv) elapsed_time = self.metrics.get_elapsed_time() s.append("Data connection open:") s.append("Total bytes sent: {}".format(bytes_sent)) s.append("Total bytes received: {}".format(bytes_recv)) s.append("Transfer elapsed time: {} secs".format(elapsed_time)) else: s.append("Data connection closed.") self.respond("211-FTP server status:\r\n") self.respond("".join([" {}\r\n".format(item) for item in s])) self.respond("211 End of status.") # return directory LISTing over the command channel else: try: line = self.ftp_path(path) with self.config.vfs.check_access(path=line, user=self._uid, perms="r"): if self.config.vfs.isdir(path): listing = self.config.vfs.listdir(path) # RFC 959 recommends the listing to be sorted. listing.sort() iterator = self.config.vfs.format_list(path, listing) else: basedir, filename = os.path.split(path) self.config.stat(path) iterator = self.config.vfs.format_list( basedir, [filename]) _status = '213-Status of "{}":\r\n'.format(line) _status += get_data_from_iter(iterator) _status += "213 End of status." self.respond(_status.encode()) except FSOperationNotPermitted: self.respond(b"500 Operation not permitted.") except ( OSError, FilesystemError, AssertionError, fs.errors.FSError, FTPPrivilegeException, ): self.respond(b"550 STAT command failed.")