diff options
-rw-r--r-- | net/ftp/ftp_network_transaction.cc | 40 | ||||
-rw-r--r-- | net/ftp/ftp_network_transaction.h | 1 | ||||
-rw-r--r-- | net/ftp/ftp_network_transaction_unittest.cc | 27 |
3 files changed, 53 insertions, 15 deletions
diff --git a/net/ftp/ftp_network_transaction.cc b/net/ftp/ftp_network_transaction.cc index 3c49d09..6fd377ed 100644 --- a/net/ftp/ftp_network_transaction.cc +++ b/net/ftp/ftp_network_transaction.cc @@ -1098,29 +1098,39 @@ int FtpNetworkTransaction::ProcessResponseCWD(const FtpCtrlResponse& response) { case ERROR_CLASS_INFO_NEEDED: return Stop(ERR_INVALID_RESPONSE); case ERROR_CLASS_TRANSIENT_ERROR: + // Some FTP servers send response 451 (not a valid CWD response according + // to RFC 959) instead of 550. + if (response.status_code == 451) + return ProcessResponseCWDNotADirectory(); + return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code)); case ERROR_CLASS_PERMANENT_ERROR: - if (response.status_code == 550) { - if (resource_type_ == RESOURCE_TYPE_DIRECTORY) { - // We're assuming that the resource is a directory, but the server - // says it's not true. The most probable interpretation is that it - // doesn't exist (with FTP we can't be sure). - return Stop(ERR_FILE_NOT_FOUND); - } - - // We are here because SIZE failed and we are not sure what the resource - // type is. It could still be file, and SIZE could fail because of - // an access error (http://crbug.com/56734). Try RETR just to be sure. - resource_type_ = RESOURCE_TYPE_FILE; - next_state_ = STATE_CTRL_WRITE_RETR; - return OK; - } + if (response.status_code == 550) + return ProcessResponseCWDNotADirectory(); return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code)); default: NOTREACHED(); return Stop(ERR_UNEXPECTED); } + + return OK; +} + +int FtpNetworkTransaction::ProcessResponseCWDNotADirectory() { + if (resource_type_ == RESOURCE_TYPE_DIRECTORY) { + // We're assuming that the resource is a directory, but the server + // says it's not true. The most probable interpretation is that it + // doesn't exist (with FTP we can't be sure). + return Stop(ERR_FILE_NOT_FOUND); + } + + // We are here because SIZE failed and we are not sure what the resource + // type is. It could still be file, and SIZE could fail because of + // an access error (http://crbug.com/56734). Try RETR just to be sure. + resource_type_ = RESOURCE_TYPE_FILE; + next_state_ = STATE_CTRL_WRITE_RETR; + return OK; } diff --git a/net/ftp/ftp_network_transaction.h b/net/ftp/ftp_network_transaction.h index c47c65f..a1637c2 100644 --- a/net/ftp/ftp_network_transaction.h +++ b/net/ftp/ftp_network_transaction.h @@ -175,6 +175,7 @@ class NET_EXPORT_PRIVATE FtpNetworkTransaction : public FtpTransaction { int ProcessResponseSIZE(const FtpCtrlResponse& response); int DoCtrlWriteCWD(); int ProcessResponseCWD(const FtpCtrlResponse& response); + int ProcessResponseCWDNotADirectory(); int DoCtrlWriteLIST(); int ProcessResponseLIST(const FtpCtrlResponse& response); int DoCtrlWriteQUIT(); diff --git a/net/ftp/ftp_network_transaction_unittest.cc b/net/ftp/ftp_network_transaction_unittest.cc index 9427001d..f92561d 100644 --- a/net/ftp/ftp_network_transaction_unittest.cc +++ b/net/ftp/ftp_network_transaction_unittest.cc @@ -451,6 +451,28 @@ class FtpSocketDataProviderFileDownloadZeroSize DISALLOW_COPY_AND_ASSIGN(FtpSocketDataProviderFileDownloadZeroSize); }; +class FtpSocketDataProviderFileDownloadCWD451 + : public FtpSocketDataProviderFileDownload { + public: + FtpSocketDataProviderFileDownloadCWD451() { + } + + virtual MockWriteResult OnWrite(const std::string& data) OVERRIDE { + if (InjectFault()) + return MockWriteResult(true, data.length()); + switch (state()) { + case PRE_CWD: + return Verify("CWD /file\r\n", data, PRE_RETR, + "451 not a directory\r\n"); + default: + return FtpSocketDataProviderFileDownload::OnWrite(data); + } + } + + private: + DISALLOW_COPY_AND_ASSIGN(FtpSocketDataProviderFileDownloadCWD451); +}; + class FtpSocketDataProviderVMSFileDownload : public FtpSocketDataProvider { public: FtpSocketDataProviderVMSFileDownload() { @@ -961,6 +983,11 @@ TEST_F(FtpNetworkTransactionTest, DownloadTransactionZeroSize) { ExecuteTransaction(&ctrl_socket, "ftp://host/file", OK); } +TEST_F(FtpNetworkTransactionTest, DownloadTransactionCWD451) { + FtpSocketDataProviderFileDownloadCWD451 ctrl_socket; + ExecuteTransaction(&ctrl_socket, "ftp://host/file", OK); +} + TEST_F(FtpNetworkTransactionTest, DownloadTransactionVMS) { FtpSocketDataProviderVMSFileDownload ctrl_socket; ExecuteTransaction(&ctrl_socket, "ftp://host/file", OK); |