示例#1
0
    def fetch(self, request):
        '''Fulfill a request.

        Args:
            request (:class:`.ftp.request.Request`): Request.

        Returns:
            .ftp.request.Response: A Response populated with the initial
            data connection reply.

        Once the response is received, call :meth:`read_content`.

        Coroutine.
        '''
        response = Response()

        yield From(self._prepare_fetch(request, response))

        response.file_transfer_size = yield From(self._fetch_size(request))

        if request.restart_value:
            try:
                yield From(self._commander.restart(request.restart_value))
                response.restart_value = request.restart_value
            except FTPServerError:
                _logger.debug('Could not restart file.', exc_info=1)

        yield From(self._open_data_stream())

        command = Command('RETR', request.file_path)

        yield From(self._begin_stream(command))

        raise Return(response)
示例#2
0
    def test_control_stream(self):
        def log_cb(data_type, data):
            _logger.debug(__('{0}={1}', data_type, data))

        connection = Connection(('127.0.0.1', self.server_port()))
        yield From(connection.connect())

        control_stream = ControlStream(connection)
        control_stream.data_observer.add(log_cb)

        reply = yield From(control_stream.read_reply())
        self.assertEqual(220, reply.code)

        yield From(control_stream.write_command(Command('USER', 'smaug')))
        reply = yield From(control_stream.read_reply())
        self.assertEqual(331, reply.code)

        yield From(control_stream.write_command(Command('PASS', 'gold1')))
        reply = yield From(control_stream.read_reply())
        self.assertEqual(230, reply.code)

        yield From(control_stream.write_command(Command('PASV')))
        reply = yield From(control_stream.read_reply())
        self.assertEqual(227, reply.code)
        address = parse_address(reply.text)

        data_connection = Connection(address)
        yield From(data_connection.connect())

        data_stream = DataStream(data_connection)

        yield From(
            control_stream.write_command(Command('RETR',
                                                 'example (copy).txt')))
        reply = yield From(control_stream.read_reply())
        self.assertEqual(150, reply.code)

        my_file = io.BytesIO()

        yield From(data_stream.read_file(my_file))

        reply = yield From(control_stream.read_reply())
        self.assertEqual(226, reply.code)

        self.assertEqual('The real treasure is in Smaug’s heart 💗.\n',
                         my_file.getvalue().decode('utf-8'))
示例#3
0
    def login(self, username='******', password='******'):
        '''Log in.

        Coroutine.
        '''
        yield From(
            self._control_stream.write_command(Command('USER', username)))

        reply = yield From(self._control_stream.read_reply())

        self.raise_if_not_match('Login username',
                                ReplyCodes.user_name_okay_need_password, reply)

        yield From(
            self._control_stream.write_command(Command('PASS', password)))

        reply = yield From(self._control_stream.read_reply())

        self.raise_if_not_match('Login password',
                                ReplyCodes.user_logged_in_proceed, reply)
示例#4
0
    def test_command(self):
        command = Command('User', '*****@*****.**')
        self.assertEqual('USER', command.name)
        self.assertEqual('*****@*****.**', command.argument)

        self.assertEqual('USER', command.to_dict()['name'])
        self.assertEqual('*****@*****.**',
                         command.to_dict()['argument'])

        command = Command('Poke')
        self.assertEqual('POKE', command.name)
        self.assertEqual('', command.argument)

        self.assertEqual('POKE', command.to_dict()['name'])
        self.assertEqual('', command.to_dict()['argument'])
示例#5
0
    def fetch_file_listing(self, request):
        '''Fetch a file listing.

        Returns:
            .ftp.request.ListingResponse

        Once the response is received, call :meth:`read_listing_content`.

        Coroutine.
        '''
        response = ListingResponse()

        yield From(self._prepare_fetch(request, response))
        yield From(self._open_data_stream())

        mlsd_command = Command('MLSD', self._request.file_path)
        list_command = Command('LIST', self._request.file_path)

        try:
            yield From(self._begin_stream(mlsd_command))
            self._listing_type = 'mlsd'
        except FTPServerError as error:
            if error.reply_code in (
                    ReplyCodes.syntax_error_command_unrecognized,
                    ReplyCodes.command_not_implemented):
                self._listing_type = None
            else:
                raise

        if not self._listing_type:
            # This code not in exception handler to avoid incorrect
            # exception chaining
            yield From(self._begin_stream(list_command))
            self._listing_type = 'list'

        _logger.debug('Listing type is %s', self._listing_type)

        raise Return(response)
示例#6
0
    def restart(self, offset):
        '''Send restart command.

        Coroutine.
        '''
        yield From(
            self._control_stream.write_command(Command('REST', str(offset))))

        reply = yield From(self._control_stream.read_reply())

        self.raise_if_not_match(
            'Restart',
            ReplyCodes.requested_file_action_pending_further_information,
            reply)
示例#7
0
    def test_parse_command(self):
        command = Command()
        command.parse(b'User [email protected]\r\n')

        self.assertEqual('USER', command.name)
        self.assertEqual('*****@*****.**', command.argument)

        self.assertRaises(AssertionError, command.parse, b'OOPS\r\n')

        command = Command()
        command.parse(b'POKE\r\n')

        self.assertEqual('POKE', command.name)
        self.assertEqual('', command.argument)

        self.assertRaises(AssertionError, command.parse, b'OOPS\r\n')
示例#8
0
    def size(self, filename):
        '''Get size of file.

        Coroutine.
        '''
        yield From(
            self._control_stream.write_command(Command('SIZE', filename)))

        reply = yield From(self._control_stream.read_reply())

        self.raise_if_not_match('File size', ReplyCodes.file_status, reply)

        try:
            raise Return(int(reply.text.strip()))
        except ValueError:
            return
示例#9
0
    def passive_mode(self):
        '''Enable passive mode.

        Returns:
            tuple: The address (IP address, port) of the passive port.

        Coroutine.
        '''
        yield From(self._control_stream.write_command(Command('PASV')))

        reply = yield From(self._control_stream.read_reply())

        self.raise_if_not_match('Passive mode',
                                ReplyCodes.entering_passive_mode, reply)

        try:
            raise Return(wpull.ftp.util.parse_address(reply.text))
        except ValueError as error:
            raise ProtocolError(str(error)) from error
示例#10
0
    def test_command(self):
        command = Command('User', '*****@*****.**')
        self.assertEqual('USER', command.name)
        self.assertEqual('*****@*****.**', command.argument)

        self.assertEqual('USER', command.to_dict()['name'])
        self.assertEqual(
            '*****@*****.**', command.to_dict()['argument'])

        command = Command('Poke')
        self.assertEqual('POKE', command.name)
        self.assertEqual('', command.argument)

        self.assertEqual('POKE', command.to_dict()['name'])
        self.assertEqual('', command.to_dict()['argument'])
示例#11
0
    def test_parse_command(self):
        command = Command()
        command.parse(b'User [email protected]\r\n')

        self.assertEqual('USER', command.name)
        self.assertEqual('*****@*****.**', command.argument)

        self.assertRaises(AssertionError, command.parse, b'OOPS\r\n')

        command = Command()
        command.parse(b'POKE\r\n')

        self.assertEqual('POKE', command.name)
        self.assertEqual('', command.argument)

        self.assertRaises(AssertionError, command.parse, b'OOPS\r\n')
示例#12
0
    def setup_data_stream(self,
                          connection_factory,
                          data_stream_factory=DataStream):
        '''Create and setup a data stream.

        This function will set up passive and binary mode and handle
        connecting to the data connection.

        Args:
            connection_factory: A coroutine callback that returns
                :class:`.connection.Connection`.
            stream_callback: A callback that will be provided an instance of
                :class:`.ftp.stream.DataStream`.

        Coroutine.

        Returns:
            DataStream
        '''
        yield From(self._control_stream.write_command(Command('TYPE', 'I')))
        reply = yield From(self._control_stream.read_reply())

        self.raise_if_not_match('Binary mode', ReplyCodes.command_okay, reply)

        address = yield From(self.passive_mode())

        connection = yield From(connection_factory(address))

        # TODO: unit test for following line for connections that have
        # the same port over time but within pool cleaning intervals
        connection.reset()

        yield From(connection.connect())

        data_stream = data_stream_factory(connection)

        raise Return(data_stream)
示例#13
0
 def override_func():
     yield From(original_func())
     yield From(
         session._control_stream.write_command(
             Command('EVIL_BAD_PASV_ADDR')))
     print('Evil awaits')