diff options
author | wtc@chromium.org <wtc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-06-05 02:14:16 +0000 |
---|---|---|
committer | wtc@chromium.org <wtc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-06-05 02:14:16 +0000 |
commit | 4c62d8c3a0ad1c141976135d7622516eb02e46c5 (patch) | |
tree | 70c80e26965149f7afeeeea97e94837df4744f3b /net/ftp/ftp_network_transaction.cc | |
parent | b170d9cd4f96b4c16880b2a188a1aa9b442b9aa6 (diff) | |
download | chromium_src-4c62d8c3a0ad1c141976135d7622516eb02e46c5.zip chromium_src-4c62d8c3a0ad1c141976135d7622516eb02e46c5.tar.gz chromium_src-4c62d8c3a0ad1c141976135d7622516eb02e46c5.tar.bz2 |
Check in the fourth Portable FTP CL from Ibrar Ahmed
<ibrar.ahmad@gmail.com>.
Now we can browse some ftp sites and can download files.
There are some TODO yet to be fixed.
Original review: http://codereview.chromium.org/115291
R=wtc
BUG=http://crbug.com/4965
TEST=none
Review URL: http://codereview.chromium.org/118274
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@17703 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/ftp/ftp_network_transaction.cc')
-rw-r--r-- | net/ftp/ftp_network_transaction.cc | 225 |
1 files changed, 167 insertions, 58 deletions
diff --git a/net/ftp/ftp_network_transaction.cc b/net/ftp/ftp_network_transaction.cc index d8e5a82..c314764 100644 --- a/net/ftp/ftp_network_transaction.cc +++ b/net/ftp/ftp_network_transaction.cc @@ -39,6 +39,8 @@ FtpNetworkTransaction::FtpNetworkTransaction( read_data_buf_len_(0), file_data_len_(0), last_error_(OK), + is_anonymous_(false), + retr_failed_(false), data_connection_port_(0), socket_factory_(socket_factory), next_state_(STATE_NONE) { @@ -126,8 +128,8 @@ int FtpNetworkTransaction::SendFtpCommand(const std::string& command, write_buf_ = new IOBuffer(buf_len + 2); memcpy(write_buf_->data(), buf, buf_len); memcpy(write_buf_->data() + buf_len, kCRLF, 2); + buf_len += 2; - // TODO(ibrar): Handle the completion of Write and release write_buf_. return ctrl_socket_->Write(write_buf_, buf_len, &io_callback_); } @@ -175,6 +177,9 @@ int FtpNetworkTransaction::ProcessResponse(int response_code) { case COMMAND_LIST: rv = ProcessResponseLIST(response_code); break; + case COMMAND_MDTM: + rv = ProcessResponseMDTM(response_code); + break; case COMMAND_QUIT: rv = ProcessResponseQUIT(response_code); break; @@ -278,10 +283,19 @@ int FtpNetworkTransaction::DoLoop(int result) { case STATE_CTRL_WRITE_LIST: rv = DoCtrlWriteLIST(); break; + case STATE_CTRL_WRITE_MDTM: + rv = DoCtrlWriteMDTM(); + break; case STATE_CTRL_WRITE_QUIT: rv = DoCtrlWriteQUIT(); break; + case STATE_DATA_RESOLVE_HOST: + rv = DoDataResolveHost(); + break; + case STATE_DATA_RESOLVE_HOST_COMPLETE: + rv = DoDataResolveHostComplete(rv); + break; case STATE_DATA_CONNECT: DCHECK(rv == OK); rv = DoDataConnect(); @@ -350,6 +364,9 @@ int FtpNetworkTransaction::DoCtrlConnectComplete(int result) { } int FtpNetworkTransaction::DoCtrlRead() { + if (write_buf_) // Clear the write buffer + write_buf_ = NULL; + next_state_ = STATE_CTRL_READ_COMPLETE; read_ctrl_buf_->data()[0] = 0; return ctrl_socket_->Read(read_ctrl_buf_, read_ctrl_buf_size_ - 1, @@ -390,11 +407,13 @@ int FtpNetworkTransaction::DoCtrlReadComplete(int result) { // USER Command. int FtpNetworkTransaction::DoCtrlWriteUSER() { - std::string command = "USER "; + std::string command = "USER"; if (request_->url.has_username()) { + command.append(" "); command.append(request_->url.username()); } else { - command.append("anonymous"); + is_anonymous_ = true; + command.append(" anonymous"); } next_state_ = STATE_CTRL_READ; return SendFtpCommand(command, COMMAND_USER); @@ -402,9 +421,8 @@ int FtpNetworkTransaction::DoCtrlWriteUSER() { int FtpNetworkTransaction::ProcessResponseUSER(int response_code) { switch (GetErrorClass(response_code)) { - case ERROR_CLASS_INITIATED: case ERROR_CLASS_OK: - next_state_ = STATE_CTRL_WRITE_USER; + next_state_ = STATE_CTRL_WRITE_SYST; break; case ERROR_CLASS_PENDING: next_state_ = STATE_CTRL_WRITE_PASS; @@ -423,11 +441,13 @@ int FtpNetworkTransaction::ProcessResponseUSER(int response_code) { // PASS command. int FtpNetworkTransaction::DoCtrlWritePASS() { - std::string command = "PASS "; + std::string command = "PASS"; if (request_->url.has_password()) { + command.append(" "); command.append(request_->url.password()); } else { - command.append("IEUser@"); + command.append(" "); + command.append("chrome@example.com"); } next_state_ = STATE_CTRL_READ; return SendFtpCommand(command, COMMAND_PASS); @@ -435,7 +455,6 @@ int FtpNetworkTransaction::DoCtrlWritePASS() { int FtpNetworkTransaction::ProcessResponsePASS(int response_code) { switch (GetErrorClass(response_code)) { - case ERROR_CLASS_INITIATED: case ERROR_CLASS_OK: next_state_ = STATE_CTRL_WRITE_SYST; break; @@ -443,11 +462,15 @@ int FtpNetworkTransaction::ProcessResponsePASS(int response_code) { next_state_ = STATE_CTRL_WRITE_ACCT; break; case ERROR_CLASS_ERROR_RETRY: + if (response_code == 421) { + // TODO(ibrar): Retry here. + } return Stop(ERR_FAILED); case ERROR_CLASS_ERROR: if (response_code == 503) { - next_state_ = STATE_CTRL_WRITE_PASS; + next_state_ = STATE_CTRL_WRITE_USER; } else { + // TODO(ibrar): Retry here. return Stop(ERR_FAILED); } break; @@ -457,44 +480,35 @@ int FtpNetworkTransaction::ProcessResponsePASS(int response_code) { return OK; } -// ACCT command. -int FtpNetworkTransaction::DoCtrlWriteACCT() { - std::string command = "ACCT noaccount"; +// SYST command. +int FtpNetworkTransaction::DoCtrlWriteSYST() { + std::string command = "SYST"; next_state_ = STATE_CTRL_READ; - return SendFtpCommand(command, COMMAND_ACCT); + return SendFtpCommand(command, COMMAND_SYST); } -int FtpNetworkTransaction::ProcessResponseACCT(int response_code) { +int FtpNetworkTransaction::ProcessResponseSYST(int response_code) { switch (GetErrorClass(response_code)) { case ERROR_CLASS_INITIATED: return Stop(ERR_FAILED); case ERROR_CLASS_OK: - next_state_ = STATE_CTRL_WRITE_SYST; + // TODO(ibrar): Process SYST response properly. + next_state_ = STATE_CTRL_WRITE_PWD; break; case ERROR_CLASS_PENDING: return Stop(ERR_FAILED); case ERROR_CLASS_ERROR_RETRY: return Stop(ERR_FAILED); case ERROR_CLASS_ERROR: - return Stop(ERR_FAILED); + // Server does not recognize the SYST command so proceed. + next_state_ = STATE_CTRL_WRITE_PWD; + break; default: return Stop(ERR_FAILED); } return OK; } -// SYST command. -int FtpNetworkTransaction::DoCtrlWriteSYST() { - std::string command = "SYST"; - next_state_ = STATE_CTRL_READ; - return SendFtpCommand(command, COMMAND_SYST); -} - -int FtpNetworkTransaction::ProcessResponseSYST(int response_code) { - next_state_ = STATE_CTRL_WRITE_PWD; - return OK; -} - // PWD command. int FtpNetworkTransaction::DoCtrlWritePWD() { std::string command = "PWD"; @@ -547,9 +561,35 @@ int FtpNetworkTransaction::ProcessResponseTYPE(int response_code) { return OK; } +// ACCT command. +int FtpNetworkTransaction::DoCtrlWriteACCT() { + std::string command = "ACCT noaccount"; + next_state_ = STATE_CTRL_READ; + return SendFtpCommand(command, COMMAND_ACCT); +} + +int FtpNetworkTransaction::ProcessResponseACCT(int response_code) { + switch (GetErrorClass(response_code)) { + case ERROR_CLASS_INITIATED: + return Stop(ERR_FAILED); + case ERROR_CLASS_OK: + next_state_ = STATE_CTRL_WRITE_SYST; + break; + case ERROR_CLASS_PENDING: + return Stop(ERR_FAILED); + case ERROR_CLASS_ERROR_RETRY: + return Stop(ERR_FAILED); + case ERROR_CLASS_ERROR: + return Stop(ERR_FAILED); + default: + return Stop(ERR_FAILED); + } + return OK; +} + // PASV command int FtpNetworkTransaction::DoCtrlWritePASV() { - std::string command = "PASV "; + std::string command = "PASV"; next_state_ = STATE_CTRL_READ; return SendFtpCommand(command, COMMAND_PASV); } @@ -580,7 +620,7 @@ int FtpNetworkTransaction::ProcessResponsePASV(int response_code) { &i0, &i1, &i2, &i3, &p0, &p1) == 6) { data_connection_ip_ = StringPrintf("%d.%d.%d.%d", i0, i1, i2, i3); data_connection_port_ = (p0 << 8) + p1; - next_state_ = STATE_DATA_CONNECT; + next_state_ = STATE_DATA_RESOLVE_HOST; } else { return Stop(ERR_FAILED); } @@ -599,9 +639,11 @@ int FtpNetworkTransaction::ProcessResponsePASV(int response_code) { // SIZE command int FtpNetworkTransaction::DoCtrlWriteSIZE() { - std::string command = "SIZE "; - if (request_->url.has_path()) + std::string command = "SIZE"; + if (request_->url.has_path()) { + command.append(" "); command.append(request_->url.path()); + } next_state_ = STATE_CTRL_READ; return SendFtpCommand(command, COMMAND_SIZE); } @@ -609,33 +651,41 @@ int FtpNetworkTransaction::DoCtrlWriteSIZE() { int FtpNetworkTransaction::ProcessResponseSIZE(int response_code) { switch (GetErrorClass(response_code)) { case ERROR_CLASS_INITIATED: - next_state_ = STATE_CTRL_WRITE_LIST; break; case ERROR_CLASS_OK: - next_state_ = STATE_CTRL_WRITE_RETR; + // Remove CR, CRLF from read_ctrl_buf_. + for (char* ptr = read_ctrl_buf_->data(); *ptr != '\0'; ptr++) { + if ((*ptr == '\r') || (*ptr == '\n')) { + // Stop if '\n' or '\r' detected. + *ptr = '\0'; + break; + } + } if (!StringToInt(read_ctrl_buf_->data() + 4, &file_data_len_)) return Stop(ERR_FAILED); break; case ERROR_CLASS_PENDING: - next_state_ = STATE_CTRL_WRITE_LIST; break; case ERROR_CLASS_ERROR_RETRY: - next_state_ = STATE_CTRL_WRITE_LIST; break; case ERROR_CLASS_ERROR: - next_state_ = STATE_CTRL_WRITE_LIST; break; default: return Stop(ERR_FAILED); } + next_state_ = STATE_CTRL_WRITE_MDTM; return OK; } // RETR command int FtpNetworkTransaction::DoCtrlWriteRETR() { - std::string command = "RETR "; - if (request_->url.has_path()) + std::string command = "RETR"; + if (request_->url.has_path()) { + command.append(" "); command.append(request_->url.path()); + } else { + command.append(" /"); + } next_state_ = STATE_CTRL_READ; return SendFtpCommand(command, COMMAND_RETR); } @@ -644,10 +694,10 @@ int FtpNetworkTransaction::ProcessResponseRETR(int response_code) { switch (GetErrorClass(response_code)) { case ERROR_CLASS_INITIATED: next_state_ = STATE_CTRL_WRITE_QUIT; - ctrl_socket_->Disconnect(); break; case ERROR_CLASS_OK: - break; // FTP Done + next_state_ = STATE_DATA_RESOLVE_HOST; + break; case ERROR_CLASS_PENDING: next_state_ = STATE_CTRL_WRITE_PASV; break; @@ -656,7 +706,41 @@ int FtpNetworkTransaction::ProcessResponseRETR(int response_code) { return Stop(ERR_FAILED); return ERR_FAILED; // TODO(ibrar): Retry here. case ERROR_CLASS_ERROR: - next_state_ = STATE_CTRL_WRITE_CWD; + retr_failed_ = true; + next_state_ = STATE_CTRL_WRITE_PASV; + break; + default: + return Stop(ERR_FAILED); + } + return OK; +} + +// MDMT command +int FtpNetworkTransaction::DoCtrlWriteMDTM() { + std::string command = "MDTM"; + if (request_->url.has_path()) { + command.append(" "); + command.append(request_->url.path()); + } else { + command.append(" /"); + } + next_state_ = STATE_CTRL_READ; + return SendFtpCommand(command, COMMAND_MDTM); +} + +int FtpNetworkTransaction::ProcessResponseMDTM(int response_code) { + switch (GetErrorClass(response_code)) { + case ERROR_CLASS_INITIATED: + return Stop(ERR_FAILED); + case ERROR_CLASS_OK: + next_state_ = STATE_CTRL_WRITE_RETR; + break; + case ERROR_CLASS_PENDING: + return Stop(ERR_FAILED); + case ERROR_CLASS_ERROR_RETRY: + return Stop(ERR_FAILED); + case ERROR_CLASS_ERROR: + next_state_ = STATE_CTRL_WRITE_RETR; break; default: return Stop(ERR_FAILED); @@ -664,9 +748,16 @@ int FtpNetworkTransaction::ProcessResponseRETR(int response_code) { return OK; } + // CWD command int FtpNetworkTransaction::DoCtrlWriteCWD() { std::string command = "CWD"; + if (request_->url.has_path()) { + command.append(" "); + command.append(request_->url.path()); + } else { + command.append(" /"); + } next_state_ = STATE_CTRL_READ; return SendFtpCommand(command, COMMAND_CWD); } @@ -677,6 +768,7 @@ int FtpNetworkTransaction::ProcessResponseCWD(int response_code) { return Stop(ERR_FAILED); case ERROR_CLASS_OK: next_state_ = STATE_CTRL_WRITE_LIST; + break; case ERROR_CLASS_PENDING: return Stop(ERR_FAILED); case ERROR_CLASS_ERROR_RETRY: @@ -691,9 +783,7 @@ int FtpNetworkTransaction::ProcessResponseCWD(int response_code) { // LIST command int FtpNetworkTransaction::DoCtrlWriteLIST() { - std::string command = "LIST "; - if (request_->url.has_path()) - command.append(request_->url.path()); + std::string command = "LIST"; next_state_ = STATE_CTRL_READ; return SendFtpCommand(command, COMMAND_LIST); } @@ -701,12 +791,12 @@ int FtpNetworkTransaction::DoCtrlWriteLIST() { int FtpNetworkTransaction::ProcessResponseLIST(int response_code) { switch (GetErrorClass(response_code)) { case ERROR_CLASS_INITIATED: - next_state_ = STATE_CTRL_WRITE_QUIT; - response_.is_directory_listing = true; + response_message_buf_len_ = 0; // Clear the responce buffer. + next_state_ = STATE_CTRL_READ; break; case ERROR_CLASS_OK: - next_state_ = STATE_CTRL_WRITE_QUIT; response_.is_directory_listing = true; + next_state_ = STATE_CTRL_WRITE_QUIT; break; case ERROR_CLASS_PENDING: return Stop(ERR_FAILED); @@ -733,22 +823,41 @@ int FtpNetworkTransaction::ProcessResponseQUIT(int response_code) { } // Data Connection + +int FtpNetworkTransaction::DoDataResolveHost() { + next_state_ = STATE_DATA_RESOLVE_HOST_COMPLETE; + + DidStartDnsResolution(data_connection_ip_, this); + return resolver_.Resolve(data_connection_ip_, data_connection_port_, + &addresses_, &io_callback_); +} + +int FtpNetworkTransaction::DoDataResolveHostComplete(int result) { + bool ok = (result == OK); + DidFinishDnsResolutionWithStatus(ok, GURL(), this); + if (ok) { + next_state_ = STATE_DATA_CONNECT; + return result; + } + return ERR_FAILED; +} + int FtpNetworkTransaction::DoDataConnect() { + if (data_socket_ != NULL && data_socket_->IsConnected()) + data_socket_->Disconnect(); + next_state_ = STATE_DATA_CONNECT_COMPLETE; - AddressList adr; - // TODO(ibrar): Call resolver_.Resolve in asynchronous mode, with a non-null - // callback. - int err = resolver_.Resolve(data_connection_ip_, - data_connection_port_, &adr, NULL); - if (err != OK) - return err; - data_socket_.reset(socket_factory_->CreateTCPClientSocket(adr)); + data_socket_.reset(socket_factory_->CreateTCPClientSocket(addresses_)); return data_socket_->Connect(&io_callback_); } int FtpNetworkTransaction::DoDataConnectComplete(int result) { - next_state_ = STATE_CTRL_WRITE_SIZE; - return result; + if (retr_failed_) { + next_state_ = STATE_CTRL_WRITE_CWD; + } else { + next_state_ = STATE_CTRL_WRITE_SIZE; + } + return OK; } int FtpNetworkTransaction::DoDataRead() { |