diff options
-rw-r--r-- | net/base/net_error_list.h | 34 | ||||
-rw-r--r-- | net/ftp/ftp_network_transaction.cc | 133 | ||||
-rw-r--r-- | net/ftp/ftp_network_transaction.h | 27 | ||||
-rw-r--r-- | net/ftp/ftp_network_transaction_unittest.cc | 66 |
4 files changed, 154 insertions, 106 deletions
diff --git a/net/base/net_error_list.h b/net/base/net_error_list.h index 06dca41..f8b4186 100644 --- a/net/base/net_error_list.h +++ b/net/base/net_error_list.h @@ -387,5 +387,35 @@ NET_ERROR(NO_PRIVATE_KEY_FOR_CERT, -502) // An error adding to the OS certificate database (e.g. OS X Keychain). NET_ERROR(ADD_USER_CERT_FAILED, -503) -// The FTP PASV command failed. -NET_ERROR(FTP_PASV_COMMAND_FAILED, -600) +// *** Code -600 is reserved (was FTP_PASV_COMMAND_FAILED). *** + +// A generic error for failed FTP control connection command. +// If possible, please use or add a more specific error code. +NET_ERROR(FTP_FAILED, -601) + +// The server cannot fulfill the request at this point. This is a temporary +// error. +// FTP response code 421. +NET_ERROR(FTP_SERVICE_UNAVAILABLE, -602) + +// The server has aborted the transfer. +// FTP response code 426. +NET_ERROR(FTP_TRANSFER_ABORTED, -603) + +// The file is busy, or some other temporary error condition on opening +// the file. +// FTP response code 450. +NET_ERROR(FTP_FILE_BUSY, -604) + +// Server rejected our command because of syntax errors. +// FTP response codes 500, 501. +NET_ERROR(FTP_SYNTAX_ERROR, -605) + +// Server does not support the command we issued. +// FTP response codes 502, 504. +NET_ERROR(FTP_COMMAND_NOT_SUPPORTED, -606) + +// Server rejected our command because we didn't issue the commands in right +// order. +// FTP response code 503. +NET_ERROR(FTP_BAD_COMMAND_SEQUENCE, -607) diff --git a/net/ftp/ftp_network_transaction.cc b/net/ftp/ftp_network_transaction.cc index 83e2997..f6b7203 100644 --- a/net/ftp/ftp_network_transaction.cc +++ b/net/ftp/ftp_network_transaction.cc @@ -43,6 +43,74 @@ bool IsValidFTPCommandString(const std::string& input) { return true; } +enum ErrorClass { + // The requested action was initiated. The client should expect another + // reply before issuing the next command. + ERROR_CLASS_INITIATED, + + // The requested action has been successfully completed. + ERROR_CLASS_OK, + + // The command has been accepted, but to complete the operation, more + // information must be sent by the client. + ERROR_CLASS_INFO_NEEDED, + + // The command was not accepted and the requested action did not take place. + // This condition is temporary, and the client is encouraged to restart the + // command sequence. + ERROR_CLASS_TRANSIENT_ERROR, + + // The command was not accepted and the requested action did not take place. + // This condition is rather permanent, and the client is discouraged from + // repeating the exact request. + ERROR_CLASS_PERMANENT_ERROR, +}; + +// Returns the error class for given response code. Caller should ensure +// that |response_code| is in range 100-599. +ErrorClass GetErrorClass(int response_code) { + if (response_code >= 100 && response_code <= 199) + return ERROR_CLASS_INITIATED; + + if (response_code >= 200 && response_code <= 299) + return ERROR_CLASS_OK; + + if (response_code >= 300 && response_code <= 399) + return ERROR_CLASS_INFO_NEEDED; + + if (response_code >= 400 && response_code <= 499) + return ERROR_CLASS_TRANSIENT_ERROR; + + if (response_code >= 500 && response_code <= 599) + return ERROR_CLASS_PERMANENT_ERROR; + + // We should not be called on invalid error codes. + NOTREACHED() << response_code; + return ERROR_CLASS_PERMANENT_ERROR; +} + +// Returns network error code for received FTP |response_code|. +int GetNetErrorCodeForFtpResponseCode(int response_code) { + switch (response_code) { + case 421: + return net::ERR_FTP_SERVICE_UNAVAILABLE; + case 426: + return net::ERR_FTP_TRANSFER_ABORTED; + case 450: + return net::ERR_FTP_FILE_BUSY; + case 500: + case 501: + return net::ERR_FTP_SYNTAX_ERROR; + case 502: + case 504: + return net::ERR_FTP_COMMAND_NOT_SUPPORTED; + case 503: + return net::ERR_FTP_BAD_COMMAND_SEQUENCE; + default: + return net::ERR_FTP_FAILED; + } +} + // From RFC 2428 Section 3: // The text returned in response to the EPSV command MUST be: // <some text> (<d><d><d><tcp-port><d>) @@ -183,7 +251,7 @@ int FtpNetworkTransaction::RestartWithAuth(const std::wstring& username, int FtpNetworkTransaction::RestartIgnoringLastError( CompletionCallback* callback) { - return ERR_FAILED; + return ERR_NOT_IMPLEMENTED; } int FtpNetworkTransaction::Read(IOBuffer* buf, @@ -263,29 +331,6 @@ int FtpNetworkTransaction::SendFtpCommand(const std::string& command, return OK; } -// static -FtpNetworkTransaction::ErrorClass FtpNetworkTransaction::GetErrorClass( - int response_code) { - if (response_code >= 100 && response_code <= 199) - return ERROR_CLASS_INITIATED; - - if (response_code >= 200 && response_code <= 299) - return ERROR_CLASS_OK; - - if (response_code >= 300 && response_code <= 399) - return ERROR_CLASS_INFO_NEEDED; - - if (response_code >= 400 && response_code <= 499) - return ERROR_CLASS_TRANSIENT_ERROR; - - if (response_code >= 500 && response_code <= 599) - return ERROR_CLASS_PERMANENT_ERROR; - - // We should not be called on invalid error codes. - NOTREACHED(); - return ERROR_CLASS_PERMANENT_ERROR; -} - int FtpNetworkTransaction::ProcessCtrlResponse() { FtpCtrlResponse response = ctrl_response_buffer_->PopResponse(); @@ -674,10 +719,10 @@ int FtpNetworkTransaction::ProcessResponseUSER( next_state_ = STATE_CTRL_WRITE_PASS; break; case ERROR_CLASS_TRANSIENT_ERROR: - return Stop(ERR_FAILED); + return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code)); case ERROR_CLASS_PERMANENT_ERROR: response_.needs_auth = true; - return Stop(ERR_FAILED); + return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code)); default: NOTREACHED(); return Stop(ERR_UNEXPECTED); @@ -703,12 +748,12 @@ int FtpNetworkTransaction::ProcessResponsePASS( next_state_ = STATE_CTRL_WRITE_SYST; break; case ERROR_CLASS_INFO_NEEDED: - return Stop(ERR_FAILED); + return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code)); case ERROR_CLASS_TRANSIENT_ERROR: - return Stop(ERR_FAILED); + return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code)); case ERROR_CLASS_PERMANENT_ERROR: response_.needs_auth = true; - return Stop(ERR_FAILED); + return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code)); default: NOTREACHED(); return Stop(ERR_UNEXPECTED); @@ -757,7 +802,7 @@ int FtpNetworkTransaction::ProcessResponseSYST( case ERROR_CLASS_INFO_NEEDED: return Stop(ERR_INVALID_RESPONSE); case ERROR_CLASS_TRANSIENT_ERROR: - return Stop(ERR_FAILED); + return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code)); case ERROR_CLASS_PERMANENT_ERROR: // Server does not recognize the SYST command so proceed. next_state_ = STATE_CTRL_WRITE_PWD; @@ -804,9 +849,9 @@ int FtpNetworkTransaction::ProcessResponsePWD(const FtpCtrlResponse& response) { case ERROR_CLASS_INFO_NEEDED: return Stop(ERR_INVALID_RESPONSE); case ERROR_CLASS_TRANSIENT_ERROR: - return Stop(ERR_FAILED); + return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code)); case ERROR_CLASS_PERMANENT_ERROR: - return Stop(ERR_FAILED); + return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code)); default: NOTREACHED(); return Stop(ERR_UNEXPECTED); @@ -840,9 +885,9 @@ int FtpNetworkTransaction::ProcessResponseTYPE( case ERROR_CLASS_INFO_NEEDED: return Stop(ERR_INVALID_RESPONSE); case ERROR_CLASS_TRANSIENT_ERROR: - return Stop(ERR_FAILED); + return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code)); case ERROR_CLASS_PERMANENT_ERROR: - return Stop(ERR_FAILED); + return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code)); default: NOTREACHED(); return Stop(ERR_UNEXPECTED); @@ -907,9 +952,9 @@ int FtpNetworkTransaction::ProcessResponsePASV( case ERROR_CLASS_INFO_NEEDED: return Stop(ERR_INVALID_RESPONSE); case ERROR_CLASS_TRANSIENT_ERROR: - return Stop(ERR_FTP_PASV_COMMAND_FAILED); + return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code)); case ERROR_CLASS_PERMANENT_ERROR: - return Stop(ERR_FTP_PASV_COMMAND_FAILED); + return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code)); default: NOTREACHED(); return Stop(ERR_UNEXPECTED); @@ -949,7 +994,7 @@ int FtpNetworkTransaction::ProcessResponseSIZE( resource_type_ == RESOURCE_TYPE_UNKNOWN) { resource_type_ = RESOURCE_TYPE_DIRECTORY; } else if (resource_type_ != RESOURCE_TYPE_DIRECTORY) { - return Stop(ERR_FAILED); + return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code)); } break; default: @@ -985,14 +1030,14 @@ int FtpNetworkTransaction::ProcessResponseRETR( next_state_ = STATE_CTRL_WRITE_QUIT; break; case ERROR_CLASS_INFO_NEEDED: - return Stop(ERR_FAILED); + return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code)); case ERROR_CLASS_TRANSIENT_ERROR: - return Stop(ERR_FAILED); + return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code)); case ERROR_CLASS_PERMANENT_ERROR: // Code 550 means "Failed to open file". Other codes are unrelated, // like "Not logged in" etc. if (response.status_code != 550) - return Stop(ERR_FAILED); + return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code)); // It's possible that RETR failed because the path is a directory. resource_type_ = RESOURCE_TYPE_DIRECTORY; @@ -1026,7 +1071,7 @@ int FtpNetworkTransaction::ProcessResponseCWD(const FtpCtrlResponse& response) { case ERROR_CLASS_INFO_NEEDED: return Stop(ERR_INVALID_RESPONSE); case ERROR_CLASS_TRANSIENT_ERROR: - return Stop(ERR_FAILED); + return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code)); case ERROR_CLASS_PERMANENT_ERROR: if (resource_type_ == RESOURCE_TYPE_DIRECTORY && response.status_code == 550) { @@ -1035,7 +1080,7 @@ int FtpNetworkTransaction::ProcessResponseCWD(const FtpCtrlResponse& response) { // exist (with FTP we can't be sure). return Stop(ERR_FILE_NOT_FOUND); } - return Stop(ERR_FAILED); + return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code)); default: NOTREACHED(); return Stop(ERR_UNEXPECTED); @@ -1102,9 +1147,9 @@ int FtpNetworkTransaction::ProcessResponseLIST( case ERROR_CLASS_INFO_NEEDED: return Stop(ERR_INVALID_RESPONSE); case ERROR_CLASS_TRANSIENT_ERROR: - return Stop(ERR_FAILED); + return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code)); case ERROR_CLASS_PERMANENT_ERROR: - return Stop(ERR_FAILED); + return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code)); default: NOTREACHED(); return Stop(ERR_UNEXPECTED); diff --git a/net/ftp/ftp_network_transaction.h b/net/ftp/ftp_network_transaction.h index 66724c6..31c38c74 100644 --- a/net/ftp/ftp_network_transaction.h +++ b/net/ftp/ftp_network_transaction.h @@ -63,29 +63,6 @@ class FtpNetworkTransaction : public FtpTransaction { COMMAND_QUIT, }; - enum ErrorClass { - // The requested action was initiated. The client should expect another - // reply before issuing the next command. - ERROR_CLASS_INITIATED, - - // The requested action has been successfully completed. - ERROR_CLASS_OK, - - // The command has been accepted, but to complete the operation, more - // information must be sent by the client. - ERROR_CLASS_INFO_NEEDED, - - // The command was not accepted and the requested action did not take place. - // This condition is temporary, and the client is encouraged to restart the - // command sequence. - ERROR_CLASS_TRANSIENT_ERROR, - - // The command was not accepted and the requested action did not take place. - // This condition is rather permanent, and the client is discouraged from - // repeating the exact request. - ERROR_CLASS_PERMANENT_ERROR, - }; - // Major categories of remote system types, as returned by SYST command. enum SystemType { SYSTEM_TYPE_UNKNOWN, @@ -123,10 +100,6 @@ class FtpNetworkTransaction : public FtpTransaction { int SendFtpCommand(const std::string& command, Command cmd); - // Return the error class for given response code. You should validate the - // code to be in range 100-599. - static ErrorClass GetErrorClass(int response_code); - // Returns request path suitable to be included in an FTP command. If the path // will be used as a directory, |is_directory| should be true. std::string GetRequestPathForFtpCommand(bool is_directory) const; diff --git a/net/ftp/ftp_network_transaction_unittest.cc b/net/ftp/ftp_network_transaction_unittest.cc index 137b4a5..b7cc29d 100644 --- a/net/ftp/ftp_network_transaction_unittest.cc +++ b/net/ftp/ftp_network_transaction_unittest.cc @@ -82,7 +82,7 @@ class FtpSocketDataProvider : public DynamicSocketDataProvider { "227 Entering Extended Passive Mode (|||31744|)\r\n"); case PRE_NOPASV: return Verify("PASV\r\n", data, PRE_QUIT, - "500 not going to happen\r\n"); + "599 fail\r\n"); case PRE_QUIT: return Verify("QUIT\r\n", data, QUIT, "221 Goodbye.\r\n"); default: @@ -474,8 +474,8 @@ class FtpSocketDataProviderFileDownloadInvalidResponse switch (state()) { case PRE_SIZE: return Verify("SIZE /file\r\n", data, PRE_QUIT, - "500 Evil Response\r\n" - "500 More Evil\r\n"); + "599 Evil Response\r\n" + "599 More Evil\r\n"); default: return FtpSocketDataProviderFileDownload::OnWrite(data); } @@ -1031,7 +1031,7 @@ TEST_F(FtpNetworkTransactionTest, EvilRestartUser) { ASSERT_EQ(ERR_IO_PENDING, transaction_.Start(&request_info, &callback_, BoundNetLog())); - ASSERT_EQ(ERR_FAILED, callback_.WaitForResult()); + ASSERT_EQ(ERR_FTP_FAILED, callback_.WaitForResult()); MockRead ctrl_reads[] = { MockRead("220 host TestFTPd\r\n"), @@ -1061,7 +1061,7 @@ TEST_F(FtpNetworkTransactionTest, EvilRestartPassword) { ASSERT_EQ(ERR_IO_PENDING, transaction_.Start(&request_info, &callback_, BoundNetLog())); - ASSERT_EQ(ERR_FAILED, callback_.WaitForResult()); + ASSERT_EQ(ERR_FTP_FAILED, callback_.WaitForResult()); MockRead ctrl_reads[] = { MockRead("220 host TestFTPd\r\n"), @@ -1120,8 +1120,8 @@ TEST_F(FtpNetworkTransactionTest, DirectoryTransactionFailUser) { "ftp://host", FtpSocketDataProvider::PRE_USER, FtpSocketDataProvider::PRE_QUIT, - "500 no such user\r\n", - ERR_FAILED); + "599 fail\r\n", + ERR_FTP_FAILED); } TEST_F(FtpNetworkTransactionTest, DirectoryTransactionFailPass) { @@ -1131,7 +1131,7 @@ TEST_F(FtpNetworkTransactionTest, DirectoryTransactionFailPass) { FtpSocketDataProvider::PRE_PASSWD, FtpSocketDataProvider::PRE_QUIT, "530 Login authentication failed\r\n", - ERR_FAILED); + ERR_FTP_FAILED); } // Regression test for http://crbug.com/38707. @@ -1142,7 +1142,7 @@ TEST_F(FtpNetworkTransactionTest, DirectoryTransactionFailPass503) { FtpSocketDataProvider::PRE_PASSWD, FtpSocketDataProvider::PRE_QUIT, "503 Bad sequence of commands\r\n", - ERR_FAILED); + ERR_FTP_BAD_COMMAND_SEQUENCE); } TEST_F(FtpNetworkTransactionTest, DirectoryTransactionFailSyst) { @@ -1151,7 +1151,7 @@ TEST_F(FtpNetworkTransactionTest, DirectoryTransactionFailSyst) { "ftp://host", FtpSocketDataProvider::PRE_SYST, FtpSocketDataProvider::PRE_PWD, - "500 failed syst\r\n", + "599 fail\r\n", OK); } @@ -1161,8 +1161,8 @@ TEST_F(FtpNetworkTransactionTest, DirectoryTransactionFailPwd) { "ftp://host", FtpSocketDataProvider::PRE_PWD, FtpSocketDataProvider::PRE_QUIT, - "500 failed pwd\r\n", - ERR_FAILED); + "599 fail\r\n", + ERR_FTP_FAILED); } TEST_F(FtpNetworkTransactionTest, DirectoryTransactionFailType) { @@ -1171,8 +1171,8 @@ TEST_F(FtpNetworkTransactionTest, DirectoryTransactionFailType) { "ftp://host", FtpSocketDataProvider::PRE_TYPE, FtpSocketDataProvider::PRE_QUIT, - "500 failed type\r\n", - ERR_FAILED); + "599 fail\r\n", + ERR_FTP_FAILED); } TEST_F(FtpNetworkTransactionTest, DirectoryTransactionFailEpsv) { @@ -1181,8 +1181,8 @@ TEST_F(FtpNetworkTransactionTest, DirectoryTransactionFailEpsv) { "ftp://host", FtpSocketDataProvider::PRE_EPSV, FtpSocketDataProvider::PRE_NOPASV, - "500 failed epsv\r\n", - ERR_FTP_PASV_COMMAND_FAILED); + "599 fail\r\n", + ERR_FTP_FAILED); } TEST_F(FtpNetworkTransactionTest, DirectoryTransactionFailCwd) { @@ -1191,8 +1191,8 @@ TEST_F(FtpNetworkTransactionTest, DirectoryTransactionFailCwd) { "ftp://host", FtpSocketDataProvider::PRE_CWD, FtpSocketDataProvider::PRE_QUIT, - "500 failed cwd\r\n", - ERR_FAILED); + "599 fail\r\n", + ERR_FTP_FAILED); } TEST_F(FtpNetworkTransactionTest, DirectoryTransactionFileNotFound) { @@ -1221,8 +1221,8 @@ TEST_F(FtpNetworkTransactionTest, DirectoryTransactionFailList) { "ftp://host/dir", FtpSocketDataProvider::PRE_LIST, FtpSocketDataProvider::PRE_QUIT, - "500 failed list\r\n", - ERR_FAILED); + "599 fail\r\n", + ERR_FTP_FAILED); } TEST_F(FtpNetworkTransactionTest, DownloadTransactionFailUser) { @@ -1231,8 +1231,8 @@ TEST_F(FtpNetworkTransactionTest, DownloadTransactionFailUser) { "ftp://host/file", FtpSocketDataProvider::PRE_USER, FtpSocketDataProvider::PRE_QUIT, - "500 no such user\r\n", - ERR_FAILED); + "599 fail\r\n", + ERR_FTP_FAILED); } TEST_F(FtpNetworkTransactionTest, DownloadTransactionFailPass) { @@ -1242,7 +1242,7 @@ TEST_F(FtpNetworkTransactionTest, DownloadTransactionFailPass) { FtpSocketDataProvider::PRE_PASSWD, FtpSocketDataProvider::PRE_QUIT, "530 Login authentication failed\r\n", - ERR_FAILED); + ERR_FTP_FAILED); } TEST_F(FtpNetworkTransactionTest, DownloadTransactionFailSyst) { @@ -1251,7 +1251,7 @@ TEST_F(FtpNetworkTransactionTest, DownloadTransactionFailSyst) { "ftp://host/file", FtpSocketDataProvider::PRE_SYST, FtpSocketDataProvider::PRE_PWD, - "500 failed syst\r\n", + "599 fail\r\n", OK); } @@ -1261,8 +1261,8 @@ TEST_F(FtpNetworkTransactionTest, DownloadTransactionFailPwd) { "ftp://host/file", FtpSocketDataProvider::PRE_PWD, FtpSocketDataProvider::PRE_QUIT, - "500 failed pwd\r\n", - ERR_FAILED); + "599 fail\r\n", + ERR_FTP_FAILED); } TEST_F(FtpNetworkTransactionTest, DownloadTransactionFailType) { @@ -1271,8 +1271,8 @@ TEST_F(FtpNetworkTransactionTest, DownloadTransactionFailType) { "ftp://host/file", FtpSocketDataProvider::PRE_TYPE, FtpSocketDataProvider::PRE_QUIT, - "500 failed type\r\n", - ERR_FAILED); + "599 fail\r\n", + ERR_FTP_FAILED); } TEST_F(FtpNetworkTransactionTest, DownloadTransactionFailEpsv) { @@ -1281,8 +1281,8 @@ TEST_F(FtpNetworkTransactionTest, DownloadTransactionFailEpsv) { "ftp://host/file", FtpSocketDataProvider::PRE_EPSV, FtpSocketDataProvider::PRE_NOPASV, - "500 failed pasv\r\n", - ERR_FTP_PASV_COMMAND_FAILED); + "599 fail\r\n", + ERR_FTP_FAILED); } TEST_F(FtpNetworkTransactionTest, DownloadTransactionFailRetr) { @@ -1291,8 +1291,8 @@ TEST_F(FtpNetworkTransactionTest, DownloadTransactionFailRetr) { "ftp://host/file", FtpSocketDataProvider::PRE_RETR, FtpSocketDataProvider::PRE_QUIT, - "500 failed retr\r\n", - ERR_FAILED); + "599 fail\r\n", + ERR_FTP_FAILED); } TEST_F(FtpNetworkTransactionTest, DownloadTransactionFileNotFound) { @@ -1302,7 +1302,7 @@ TEST_F(FtpNetworkTransactionTest, DownloadTransactionFileNotFound) { FtpSocketDataProvider::PRE_SIZE, FtpSocketDataProvider::PRE_QUIT, "550 File Not Found\r\n", - ERR_FAILED); + ERR_FTP_FAILED); } // Test for http://crbug.com/38845. |