summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/ftp/ftp_network_transaction.cc40
-rw-r--r--net/ftp/ftp_network_transaction.h1
-rw-r--r--net/ftp/ftp_network_transaction_unittest.cc27
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);