Ticket #5411: 5411-2.diff

File 5411-2.diff, 6.3 KB (added by adiroiban, 20 months ago)
  • twisted/protocols/ftp.py

    diff --git a/twisted/protocols/ftp.py b/twisted/protocols/ftp.py
    index 19504a7..1506826 100644
    a b class DTP(object, protocol.Protocol): 
    417417            self._onConnLost.callback(None) 
    418418 
    419419    def sendLine(self, line): 
     420        """ 
     421        Send a line to data channel. 
     422 
     423        @type  line: I{str} or I{unicdoe} 
     424        @param line: The line to be sent. 
     425 
     426        If line is I{unicode}, it will be converted to I{str}. 
     427        """ 
     428        if isinstance(line, unicode): 
     429            warnings.warn( 
     430                "Unicode date received. Encoded to UTF-8. " 
     431                "Please send only alreay encoded data.", 
     432                category=UserWarning) 
     433            line = line.encode('utf-8') 
     434 
    420435        self.transport.write(line + '\r\n') 
    421436 
    422437 
    class FTP(object, basic.LineReceiver, policies.TimeoutMixin): 
    951966        def gotListing(results): 
    952967            self.reply(DATA_CNX_ALREADY_OPEN_START_XFR) 
    953968            for (name, attrs) in results: 
    954                 self.dtpInstance.sendListResponse(name, attrs) 
     969                # IFTPShell returns Unicode file names. 
     970                name_encoded = name.encode('utf-8') 
     971                self.dtpInstance.sendListResponse(name_encoded, attrs) 
    955972            self.dtpInstance.transport.loseConnection() 
    956973            return (TXFR_COMPLETE_OK,) 
    957974 
    class FTP(object, basic.LineReceiver, policies.TimeoutMixin): 
    10141031            self.reply(DATA_CNX_ALREADY_OPEN_START_XFR) 
    10151032            for (name, ignored) in results: 
    10161033                if not glob or (glob and fnmatch.fnmatch(name, glob)): 
    1017                     self.dtpInstance.sendLine(name) 
     1034                    # IFTPShell returns Unicode file names. 
     1035                    name_encoded = name.encode('utf-8') 
     1036                    self.dtpInstance.sendLine(name_encoded) 
    10181037            self.dtpInstance.transport.loseConnection() 
    10191038            return (TXFR_COMPLETE_OK,) 
    10201039 
  • twisted/test/test_ftp.py

    diff --git a/twisted/test/test_ftp.py b/twisted/test/test_ftp.py
    index 7ba434e..da6769a 100644
    a b class FTPServerPasvDataConnectionTestCase(FTPServerTestCase): 
    672672            self.assertEqual('', download) 
    673673        return d.addCallback(checkDownload) 
    674674 
     675 
     676    def test_LISTUnicode(self): 
     677        """ 
     678        LIST will receive Unicode filenames for IFTPShell.list, and will 
     679        encode them using UTF-8. 
     680        """ 
     681        # Login 
     682        d = self._anonymousLogin() 
     683 
     684        def pachedList(me, segments, attributes): 
     685            return defer.succeed([( 
     686                u'my resum\xe9', (0, 1, 0777, 0, 0, 'user', 'group'))]) 
     687        self.patch(ftp.FTPAnonymousShell, 'list', pachedList) 
     688 
     689        self._download('LIST something', chainDeferred=d) 
     690 
     691        def checkDownload(download): 
     692            self.assertEqual( 
     693                'drwxrwxrwx   0 user      group                   ' 
     694                '0 Jan 01  1970 my resum\xc3\xa9\r\n', 
     695                download) 
     696        return d.addCallback(checkDownload) 
     697 
     698 
    675699    def testManyLargeDownloads(self): 
    676700        # Login 
    677701        d = self._anonymousLogin() 
    class FTPServerPasvDataConnectionTestCase(FTPServerTestCase): 
    756780        return d.addCallback(checkDownload) 
    757781 
    758782 
     783    def test_NLSTUnicode(self): 
     784        """ 
     785        NLST will receive Unicode filenames for IFTPShell.list, and will 
     786        encode them using UTF-8. 
     787        """ 
     788        # Login 
     789        d = self._anonymousLogin() 
     790 
     791        def pachedList(me, segments): 
     792            return defer.succeed([(u'my resum\xe9', None)]) 
     793        self.patch(ftp.FTPAnonymousShell, 'list', pachedList) 
     794 
     795        self._download('NLST something', chainDeferred=d) 
     796 
     797        def checkDownload(download): 
     798            self.assertEqual('my resum\xc3\xa9\r\n', download) 
     799        return d.addCallback(checkDownload) 
     800 
     801 
    759802    def test_NLSTOnPathToFile(self): 
    760803        """ 
    761804        NLST on an existent file returns only the path to that file. 
    class FTPServerPasvDataConnectionTestCase(FTPServerTestCase): 
    767810        self.dirPath.child('test.txt').touch() 
    768811 
    769812        self._download('NLST test.txt', chainDeferred=d) 
     813 
    770814        def checkDownload(download): 
    771815            filenames = download[:-2].split('\r\n') 
    772816            self.assertEqual(['test.txt'], filenames) 
    class DTPFactoryTests(unittest.TestCase): 
    9821026        return d 
    9831027 
    9841028 
     1029class DTPTests(unittest.TestCase): 
     1030    """ 
     1031    Tests for L{ftp.DTP}. 
     1032 
     1033    The DTP instances in these tests are generated using 
     1034    DTPFactory.buildProtocol() 
     1035    """ 
     1036 
     1037    def setUp(self): 
     1038        """ 
     1039        Create a fake protocol interpreter, a L{ftp.DTPFactory} instance, 
     1040        and dummy transport to help with tests. 
     1041        """ 
     1042        self.reactor = task.Clock() 
     1043 
     1044        class ProtocolInterpreter(object): 
     1045            dtpInstance = None 
     1046 
     1047        self.protocolInterpreter = ProtocolInterpreter() 
     1048        self.factory = ftp.DTPFactory( 
     1049            self.protocolInterpreter, None, self.reactor) 
     1050        self.transport = proto_helpers.StringTransportWithDisconnection() 
     1051 
     1052 
     1053    def test_sendLine_newline(self): 
     1054        """ 
     1055        Whend sending a line, the newline delimiter will be autoamtically 
     1056        added. 
     1057        """ 
     1058        dtp_instance = self.factory.buildProtocol(None) 
     1059        dtp_instance.makeConnection(self.transport) 
     1060        line_content = 'line content' 
     1061 
     1062        dtp_instance.sendLine(line_content) 
     1063 
     1064        data_sent = self.transport.value() 
     1065        self.assertEqual(line_content + '\r\n', data_sent) 
     1066 
     1067 
     1068    def test_sendLine_unicode(self): 
     1069        """ 
     1070        When sending an unicode line, it will be converted to str and 
     1071        a warning is raised. 
     1072        """ 
     1073        dtp_instance = self.factory.buildProtocol(None) 
     1074        dtp_instance.makeConnection(self.transport) 
     1075        line_content = u'my resum\xe9' 
     1076 
     1077        self.assertWarns( 
     1078            UserWarning, 
     1079            "Unicode date received. " 
     1080                "Encoded to UTF-8. Please send only alreay encoded data.", 
     1081            ftp.__file__, 
     1082            dtp_instance.sendLine, line_content) 
     1083 
     1084        data_sent = self.transport.value() 
     1085        self.assertTrue(isinstance(data_sent, str)) 
     1086        self.assertEqual(line_content.encode('utf-8') + '\r\n', data_sent) 
     1087 
     1088 
    9851089 
    9861090# -- Client Tests ----------------------------------------------------------- 
    9871091