diff options
author | phajdan.jr@chromium.org <phajdan.jr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-12-22 11:59:21 +0000 |
---|---|---|
committer | phajdan.jr@chromium.org <phajdan.jr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-12-22 11:59:21 +0000 |
commit | 250e5243ce41f9025442773a038670fc24a4622c (patch) | |
tree | 01c5efb2babc434368a9adc288bdc797706d6722 /net | |
parent | 2c8d596cbd1f91a7d6134c7c5b33a188af51d0bc (diff) | |
download | chromium_src-250e5243ce41f9025442773a038670fc24a4622c.zip chromium_src-250e5243ce41f9025442773a038670fc24a4622c.tar.gz chromium_src-250e5243ce41f9025442773a038670fc24a4622c.tar.bz2 |
Implement support for MLSD FTP command in FtpNetworkTransaction.
This way we can request the better-parseable MLSD listing,
and in case it doesn't work fall back to LIST command.
TEST=Covered by net_unittests.
BUG=29691
Review URL: http://codereview.chromium.org/500134
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@35141 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r-- | net/ftp/ftp_network_transaction.cc | 45 | ||||
-rw-r--r-- | net/ftp/ftp_network_transaction.h | 4 | ||||
-rw-r--r-- | net/ftp/ftp_network_transaction_unittest.cc | 28 |
3 files changed, 71 insertions, 6 deletions
diff --git a/net/ftp/ftp_network_transaction.cc b/net/ftp/ftp_network_transaction.cc index 8014d07..44f1aa1 100644 --- a/net/ftp/ftp_network_transaction.cc +++ b/net/ftp/ftp_network_transaction.cc @@ -259,6 +259,9 @@ int FtpNetworkTransaction::ProcessCtrlResponse() { case COMMAND_CWD: rv = ProcessResponseCWD(response); break; + case COMMAND_MLSD: + rv = ProcessResponseMLSD(response); + break; case COMMAND_LIST: rv = ProcessResponseLIST(response); break; @@ -282,6 +285,9 @@ int FtpNetworkTransaction::ProcessCtrlResponse() { case COMMAND_RETR: rv = ProcessResponseRETR(response); break; + case COMMAND_MLSD: + rv = ProcessResponseMLSD(response); + break; case COMMAND_LIST: rv = ProcessResponseLIST(response); break; @@ -438,6 +444,10 @@ int FtpNetworkTransaction::DoLoop(int result) { DCHECK(rv == OK); rv = DoCtrlWriteCWD(); break; + case STATE_CTRL_WRITE_MLSD: + DCHECK(rv == 0); + rv = DoCtrlWriteMLSD(); + break; case STATE_CTRL_WRITE_LIST: DCHECK(rv == OK); rv = DoCtrlWriteLIST(); @@ -989,7 +999,7 @@ int FtpNetworkTransaction::ProcessResponseCWD(const FtpCtrlResponse& response) { case ERROR_CLASS_INITIATED: return Stop(ERR_INVALID_RESPONSE); case ERROR_CLASS_OK: - next_state_ = STATE_CTRL_WRITE_LIST; + next_state_ = STATE_CTRL_WRITE_MLSD; break; case ERROR_CLASS_INFO_NEEDED: return Stop(ERR_INVALID_RESPONSE); @@ -1011,6 +1021,38 @@ int FtpNetworkTransaction::ProcessResponseCWD(const FtpCtrlResponse& response) { return OK; } +// MLSD command +int FtpNetworkTransaction::DoCtrlWriteMLSD() { + next_state_ = STATE_CTRL_READ; + return SendFtpCommand("MLSD", COMMAND_MLSD); +} + +int FtpNetworkTransaction::ProcessResponseMLSD( + const FtpCtrlResponse& response) { + switch (GetErrorClass(response.status_code)) { + case ERROR_CLASS_INITIATED: + response_.is_directory_listing = true; + next_state_ = STATE_CTRL_READ; + break; + case ERROR_CLASS_OK: + response_.is_directory_listing = true; + next_state_ = STATE_CTRL_WRITE_QUIT; + break; + case ERROR_CLASS_INFO_NEEDED: + return Stop(ERR_INVALID_RESPONSE); + case ERROR_CLASS_TRANSIENT_ERROR: + case ERROR_CLASS_PERMANENT_ERROR: + // Fallback to the LIST command, more widely supported, + // but without a specified output format. + next_state_ = STATE_CTRL_WRITE_LIST; + break; + default: + NOTREACHED(); + return Stop(ERR_UNEXPECTED); + } + return OK; +} + // LIST command int FtpNetworkTransaction::DoCtrlWriteLIST() { std::string command(system_type_ == SYSTEM_TYPE_VMS ? "LIST *.*;0" : "LIST"); @@ -1023,6 +1065,7 @@ int FtpNetworkTransaction::ProcessResponseLIST( switch (GetErrorClass(response.status_code)) { case ERROR_CLASS_INITIATED: response_.is_directory_listing = true; + next_state_ = STATE_CTRL_READ; break; case ERROR_CLASS_OK: response_.is_directory_listing = true; diff --git a/net/ftp/ftp_network_transaction.h b/net/ftp/ftp_network_transaction.h index 8a11947..e8140f4 100644 --- a/net/ftp/ftp_network_transaction.h +++ b/net/ftp/ftp_network_transaction.h @@ -57,6 +57,7 @@ class FtpNetworkTransaction : public FtpTransaction { COMMAND_SIZE, COMMAND_RETR, COMMAND_CWD, + COMMAND_MLSD, COMMAND_LIST, COMMAND_MDTM, COMMAND_QUIT @@ -151,6 +152,8 @@ class FtpNetworkTransaction : public FtpTransaction { int ProcessResponseSIZE(const FtpCtrlResponse& response); int DoCtrlWriteCWD(); int ProcessResponseCWD(const FtpCtrlResponse& response); + int DoCtrlWriteMLSD(); + int ProcessResponseMLSD(const FtpCtrlResponse& response); int DoCtrlWriteLIST(); int ProcessResponseLIST(const FtpCtrlResponse& response); int DoCtrlWriteMDTM(); @@ -240,6 +243,7 @@ class FtpNetworkTransaction : public FtpTransaction { STATE_CTRL_WRITE_RETR, STATE_CTRL_WRITE_SIZE, STATE_CTRL_WRITE_CWD, + STATE_CTRL_WRITE_MLSD, STATE_CTRL_WRITE_LIST, STATE_CTRL_WRITE_MDTM, STATE_CTRL_WRITE_QUIT, diff --git a/net/ftp/ftp_network_transaction_unittest.cc b/net/ftp/ftp_network_transaction_unittest.cc index d20818a..d8479aa5 100644 --- a/net/ftp/ftp_network_transaction_unittest.cc +++ b/net/ftp/ftp_network_transaction_unittest.cc @@ -39,6 +39,7 @@ class FtpSocketDataProvider : public DynamicSocketDataProvider { PRE_PASV, PRE_SIZE, PRE_MDTM, + PRE_MLSD, PRE_LIST, PRE_RETR, PRE_PASV2, @@ -174,9 +175,12 @@ class FtpSocketDataProviderDirectoryListing : public FtpSocketDataProvider { "550 Can't download directory\r\n"); case PRE_CWD: - return Verify("CWD /\r\n", data, PRE_LIST, "200 OK\r\n"); + return Verify("CWD /\r\n", data, PRE_MLSD, "200 OK\r\n"); + case PRE_MLSD: + return Verify("MLSD\r\n", data, PRE_QUIT, + "150 Accepted data connection\r\n" + "226 MLSD complete\r\n"); case PRE_LIST: - // TODO(phajdan.jr): Also test with "150 Accepted Data Connection". return Verify("LIST\r\n", data, PRE_QUIT, "200 OK\r\n"); default: return FtpSocketDataProvider::OnWrite(data); @@ -211,8 +215,10 @@ class FtpSocketDataProviderVMSDirectoryListing : public FtpSocketDataProvider { return Verify("RETR ANONYMOUS_ROOT:[000000]dir\r\n", data, PRE_PASV2, "550 Can't download directory\r\n"); case PRE_CWD: - return Verify("CWD ANONYMOUS_ROOT:[dir]\r\n", data, PRE_LIST, + return Verify("CWD ANONYMOUS_ROOT:[dir]\r\n", data, PRE_MLSD, "200 OK\r\n"); + case PRE_MLSD: + return Verify("MLSD\r\n", data, PRE_LIST, "500 Invalid command\r\n"); case PRE_LIST: return Verify("LIST *.*;0\r\n", data, PRE_QUIT, "200 OK\r\n"); default: @@ -249,8 +255,10 @@ class FtpSocketDataProviderVMSDirectoryListingRootDirectory return Verify("RETR ANONYMOUS_ROOT\r\n", data, PRE_PASV2, "550 Can't download directory\r\n"); case PRE_CWD: - return Verify("CWD ANONYMOUS_ROOT:[000000]\r\n", data, PRE_LIST, + return Verify("CWD ANONYMOUS_ROOT:[000000]\r\n", data, PRE_MLSD, "200 OK\r\n"); + case PRE_MLSD: + return Verify("MLSD\r\n", data, PRE_LIST, "500 Invalid command\r\n"); case PRE_LIST: return Verify("LIST *.*;0\r\n", data, PRE_QUIT, "200 OK\r\n"); default: @@ -1010,10 +1018,20 @@ TEST_F(FtpNetworkTransactionTest, DirectoryTransactionFileNotFound) { ERR_FILE_NOT_FOUND); } -TEST_F(FtpNetworkTransactionTest, DirectoryTransactionFailList) { +TEST_F(FtpNetworkTransactionTest, DirectoryTransactionFailMlsd) { FtpSocketDataProviderDirectoryListing ctrl_socket; TransactionFailHelper(&ctrl_socket, "ftp://host", + FtpSocketDataProvider::PRE_MLSD, + FtpSocketDataProvider::PRE_LIST, + "500 Unrecognized command\r\n", + OK); +} + +TEST_F(FtpNetworkTransactionTest, DirectoryTransactionFailList) { + FtpSocketDataProviderVMSDirectoryListing ctrl_socket; + TransactionFailHelper(&ctrl_socket, + "ftp://host/dir", FtpSocketDataProvider::PRE_LIST, FtpSocketDataProvider::PRE_QUIT, "500 failed list\r\n", |