Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2008 The Chromium Authors. All rights reserved. Use of this | 1 // Copyright (c) 2008 The Chromium Authors. All rights reserved. Use of this |
| 2 // source code is governed by a BSD-style license that can be found in the | 2 // source code is governed by a BSD-style license that can be found in the |
| 3 // LICENSE file. | 3 // LICENSE file. |
| 4 | 4 |
| 5 #include "net/ftp/ftp_network_transaction.h" | 5 #include "net/ftp/ftp_network_transaction.h" |
| 6 | 6 |
| 7 #include "base/compiler_specific.h" | 7 #include "base/compiler_specific.h" |
| 8 #include "base/string_util.h" | 8 #include "base/string_util.h" |
| 9 #include "net/base/connection_type_histograms.h" | 9 #include "net/base/connection_type_histograms.h" |
| 10 #include "net/base/load_log.h" | 10 #include "net/base/load_log.h" |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 29 FtpNetworkSession* session, | 29 FtpNetworkSession* session, |
| 30 ClientSocketFactory* socket_factory) | 30 ClientSocketFactory* socket_factory) |
| 31 : command_sent_(COMMAND_NONE), | 31 : command_sent_(COMMAND_NONE), |
| 32 ALLOW_THIS_IN_INITIALIZER_LIST( | 32 ALLOW_THIS_IN_INITIALIZER_LIST( |
| 33 io_callback_(this, &FtpNetworkTransaction::OnIOComplete)), | 33 io_callback_(this, &FtpNetworkTransaction::OnIOComplete)), |
| 34 user_callback_(NULL), | 34 user_callback_(NULL), |
| 35 session_(session), | 35 session_(session), |
| 36 request_(NULL), | 36 request_(NULL), |
| 37 resolver_(session->host_resolver()), | 37 resolver_(session->host_resolver()), |
| 38 read_ctrl_buf_(new IOBuffer(kCtrlBufLen)), | 38 read_ctrl_buf_(new IOBuffer(kCtrlBufLen)), |
| 39 ctrl_response_buffer_(new FtpCtrlResponseBuffer()), | |
| 39 read_data_buf_len_(0), | 40 read_data_buf_len_(0), |
| 40 file_data_len_(0), | 41 file_data_len_(0), |
| 41 write_command_buf_written_(0), | 42 write_command_buf_written_(0), |
| 42 last_error_(OK), | 43 last_error_(OK), |
| 43 is_anonymous_(false), | |
| 44 retr_failed_(false), | 44 retr_failed_(false), |
| 45 data_connection_port_(0), | 45 data_connection_port_(0), |
| 46 socket_factory_(socket_factory), | 46 socket_factory_(socket_factory), |
| 47 next_state_(STATE_NONE) { | 47 next_state_(STATE_NONE) { |
| 48 } | 48 } |
| 49 | 49 |
| 50 FtpNetworkTransaction::~FtpNetworkTransaction() { | 50 FtpNetworkTransaction::~FtpNetworkTransaction() { |
| 51 } | 51 } |
| 52 | 52 |
| 53 int FtpNetworkTransaction::Start(const FtpRequestInfo* request_info, | 53 int FtpNetworkTransaction::Start(const FtpRequestInfo* request_info, |
| 54 CompletionCallback* callback, | 54 CompletionCallback* callback, |
| 55 LoadLog* load_log) { | 55 LoadLog* load_log) { |
| 56 load_log_ = load_log; | 56 load_log_ = load_log; |
| 57 request_ = request_info; | 57 request_ = request_info; |
| 58 | 58 |
| 59 if (request_->url.has_username()) { | |
| 60 username_ = UTF8ToWide(request_->url.username()); | |
|
wtc
2009/08/25 20:52:50
Please ask Darin and Brett whether the embedded us
eroman
2009/09/01 07:12:37
They definitely do need to be unescaped.
See Http
| |
| 61 if (request_->url.has_password()) | |
|
eroman
2009/09/01 07:12:37
Don't actually need the guard, will just be empty
| |
| 62 password_ = UTF8ToWide(request_->url.password()); | |
| 63 else | |
|
wtc
2009/08/25 20:52:50
Do we need the "else" here? password_ is initiali
| |
| 64 password_ = L""; | |
| 65 } else { | |
| 66 username_ = L"anonymous"; | |
| 67 password_ = L"chrome@example.com"; | |
| 68 } | |
| 69 | |
| 59 next_state_ = STATE_CTRL_INIT; | 70 next_state_ = STATE_CTRL_INIT; |
| 60 int rv = DoLoop(OK); | 71 int rv = DoLoop(OK); |
| 61 if (rv == ERR_IO_PENDING) | 72 if (rv == ERR_IO_PENDING) |
| 62 user_callback_ = callback; | 73 user_callback_ = callback; |
| 63 return rv; | 74 return rv; |
| 64 } | 75 } |
| 65 | 76 |
| 66 int FtpNetworkTransaction::Stop(int error) { | 77 int FtpNetworkTransaction::Stop(int error) { |
| 67 if (command_sent_ == COMMAND_QUIT) | 78 if (command_sent_ == COMMAND_QUIT) |
| 68 return error; | 79 return error; |
| 69 | 80 |
| 70 next_state_ = STATE_CTRL_WRITE_QUIT; | 81 next_state_ = STATE_CTRL_WRITE_QUIT; |
| 71 last_error_ = error; | 82 last_error_ = error; |
| 72 return OK; | 83 return OK; |
| 73 } | 84 } |
| 74 | 85 |
| 75 int FtpNetworkTransaction::RestartWithAuth(const std::wstring& username, | 86 int FtpNetworkTransaction::RestartWithAuth(const std::wstring& username, |
| 76 const std::wstring& password, | 87 const std::wstring& password, |
| 77 CompletionCallback* callback) { | 88 CompletionCallback* callback) { |
| 78 return ERR_FAILED; | 89 ResetStateForRestart(); |
| 90 | |
| 91 username_ = username; | |
| 92 password_ = password; | |
| 93 | |
| 94 next_state_ = STATE_CTRL_INIT; | |
| 95 int rv = DoLoop(OK); | |
| 96 if (rv == ERR_IO_PENDING) | |
| 97 user_callback_ = callback; | |
| 98 return rv; | |
| 79 } | 99 } |
| 80 | 100 |
| 81 int FtpNetworkTransaction::RestartIgnoringLastError( | 101 int FtpNetworkTransaction::RestartIgnoringLastError( |
| 82 CompletionCallback* callback) { | 102 CompletionCallback* callback) { |
| 83 return ERR_FAILED; | 103 return ERR_FAILED; |
| 84 } | 104 } |
| 85 | 105 |
| 86 int FtpNetworkTransaction::Read(IOBuffer* buf, | 106 int FtpNetworkTransaction::Read(IOBuffer* buf, |
| 87 int buf_len, | 107 int buf_len, |
| 88 CompletionCallback* callback) { | 108 CompletionCallback* callback) { |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 127 uint64 FtpNetworkTransaction::GetUploadProgress() const { | 147 uint64 FtpNetworkTransaction::GetUploadProgress() const { |
| 128 return 0; | 148 return 0; |
| 129 } | 149 } |
| 130 | 150 |
| 131 // Used to prepare and send FTP command. | 151 // Used to prepare and send FTP command. |
| 132 int FtpNetworkTransaction::SendFtpCommand(const std::string& command, | 152 int FtpNetworkTransaction::SendFtpCommand(const std::string& command, |
| 133 Command cmd) { | 153 Command cmd) { |
| 134 // If we send a new command when we still have unprocessed responses | 154 // If we send a new command when we still have unprocessed responses |
| 135 // for previous commands, the response receiving code will have no way to know | 155 // for previous commands, the response receiving code will have no way to know |
| 136 // which responses are for which command. | 156 // which responses are for which command. |
| 137 DCHECK(!ctrl_response_buffer_.ResponseAvailable()); | 157 DCHECK(!ctrl_response_buffer_->ResponseAvailable()); |
| 138 | 158 |
| 139 DCHECK(!write_command_buf_); | 159 DCHECK(!write_command_buf_); |
| 140 DCHECK(!write_buf_); | 160 DCHECK(!write_buf_); |
| 141 DLOG(INFO) << " >> " << command; | 161 DLOG(INFO) << " >> " << command; |
| 142 | 162 |
| 143 command_sent_ = cmd; | 163 command_sent_ = cmd; |
| 144 | 164 |
| 145 write_command_buf_ = new IOBufferWithSize(command.length() + 2); | 165 write_command_buf_ = new IOBufferWithSize(command.length() + 2); |
| 146 write_buf_ = new ReusedIOBuffer(write_command_buf_, | 166 write_buf_ = new ReusedIOBuffer(write_command_buf_, |
| 147 write_command_buf_->size()); | 167 write_command_buf_->size()); |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 169 | 189 |
| 170 if (response_code >= 500 && response_code <= 599) | 190 if (response_code >= 500 && response_code <= 599) |
| 171 return ERROR_CLASS_PERMANENT_ERROR; | 191 return ERROR_CLASS_PERMANENT_ERROR; |
| 172 | 192 |
| 173 // We should not be called on invalid error codes. | 193 // We should not be called on invalid error codes. |
| 174 NOTREACHED(); | 194 NOTREACHED(); |
| 175 return ERROR_CLASS_PERMANENT_ERROR; | 195 return ERROR_CLASS_PERMANENT_ERROR; |
| 176 } | 196 } |
| 177 | 197 |
| 178 int FtpNetworkTransaction::ProcessCtrlResponse() { | 198 int FtpNetworkTransaction::ProcessCtrlResponse() { |
| 179 FtpCtrlResponse response = ctrl_response_buffer_.PopResponse(); | 199 FtpCtrlResponse response = ctrl_response_buffer_->PopResponse(); |
| 180 | 200 |
| 181 int rv = OK; | 201 int rv = OK; |
| 182 switch (command_sent_) { | 202 switch (command_sent_) { |
| 183 case COMMAND_NONE: | 203 case COMMAND_NONE: |
| 184 // TODO(phajdan.jr): Check for errors in the welcome message. | 204 // TODO(phajdan.jr): Check for errors in the welcome message. |
| 185 next_state_ = STATE_CTRL_WRITE_USER; | 205 next_state_ = STATE_CTRL_WRITE_USER; |
| 186 break; | 206 break; |
| 187 case COMMAND_USER: | 207 case COMMAND_USER: |
| 188 rv = ProcessResponseUSER(response); | 208 rv = ProcessResponseUSER(response); |
| 189 break; | 209 break; |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 223 case COMMAND_QUIT: | 243 case COMMAND_QUIT: |
| 224 rv = ProcessResponseQUIT(response); | 244 rv = ProcessResponseQUIT(response); |
| 225 break; | 245 break; |
| 226 default: | 246 default: |
| 227 LOG(DFATAL) << "Unexpected value of command_sent_: " << command_sent_; | 247 LOG(DFATAL) << "Unexpected value of command_sent_: " << command_sent_; |
| 228 return ERR_UNEXPECTED; | 248 return ERR_UNEXPECTED; |
| 229 } | 249 } |
| 230 | 250 |
| 231 // We may get multiple responses for some commands, | 251 // We may get multiple responses for some commands, |
| 232 // see http://crbug.com/18036. | 252 // see http://crbug.com/18036. |
| 233 while (ctrl_response_buffer_.ResponseAvailable() && rv == OK) { | 253 while (ctrl_response_buffer_->ResponseAvailable() && rv == OK) { |
| 234 response = ctrl_response_buffer_.PopResponse(); | 254 response = ctrl_response_buffer_->PopResponse(); |
| 235 | 255 |
| 236 switch (command_sent_) { | 256 switch (command_sent_) { |
| 237 case COMMAND_RETR: | 257 case COMMAND_RETR: |
| 238 rv = ProcessResponseRETR(response); | 258 rv = ProcessResponseRETR(response); |
| 239 break; | 259 break; |
| 240 default: | 260 default: |
| 241 // Multiple responses for other commands are invalid. | 261 // Multiple responses for other commands are invalid. |
| 242 return Stop(ERR_INVALID_RESPONSE); | 262 return Stop(ERR_INVALID_RESPONSE); |
| 243 } | 263 } |
| 244 } | 264 } |
| 245 | 265 |
| 246 return rv; | 266 return rv; |
| 247 } | 267 } |
| 248 | 268 |
| 269 void FtpNetworkTransaction::ResetStateForRestart() { | |
| 270 command_sent_ = COMMAND_NONE; | |
| 271 user_callback_ = NULL; | |
| 272 response_ = FtpResponseInfo(); | |
| 273 read_ctrl_buf_ = new IOBuffer(kCtrlBufLen); | |
| 274 ctrl_response_buffer_.reset(new FtpCtrlResponseBuffer()); | |
| 275 read_data_buf_ = NULL; | |
| 276 read_data_buf_len_ = 0; | |
| 277 file_data_len_ = 0; | |
| 278 write_command_buf_written_ = 0; | |
| 279 last_error_ = OK; | |
| 280 retr_failed_ = false; | |
| 281 data_connection_port_ = 0; | |
| 282 ctrl_socket_.reset(); | |
| 283 data_socket_.reset(); | |
| 284 next_state_ = STATE_NONE; | |
| 285 } | |
| 286 | |
| 249 void FtpNetworkTransaction::DoCallback(int rv) { | 287 void FtpNetworkTransaction::DoCallback(int rv) { |
| 250 DCHECK(rv != ERR_IO_PENDING); | 288 DCHECK(rv != ERR_IO_PENDING); |
| 251 DCHECK(user_callback_); | 289 DCHECK(user_callback_); |
| 252 | 290 |
| 253 // Since Run may result in Read being called, clear callback_ up front. | 291 // Since Run may result in Read being called, clear callback_ up front. |
| 254 CompletionCallback* c = user_callback_; | 292 CompletionCallback* c = user_callback_; |
| 255 user_callback_ = NULL; | 293 user_callback_ = NULL; |
| 256 c->Run(rv); | 294 c->Run(rv); |
| 257 } | 295 } |
| 258 | 296 |
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 436 return ctrl_socket_->Read( | 474 return ctrl_socket_->Read( |
| 437 read_ctrl_buf_, | 475 read_ctrl_buf_, |
| 438 kCtrlBufLen, | 476 kCtrlBufLen, |
| 439 &io_callback_); | 477 &io_callback_); |
| 440 } | 478 } |
| 441 | 479 |
| 442 int FtpNetworkTransaction::DoCtrlReadComplete(int result) { | 480 int FtpNetworkTransaction::DoCtrlReadComplete(int result) { |
| 443 if (result < 0) | 481 if (result < 0) |
| 444 return Stop(result); | 482 return Stop(result); |
| 445 | 483 |
| 446 ctrl_response_buffer_.ConsumeData(read_ctrl_buf_->data(), result); | 484 ctrl_response_buffer_->ConsumeData(read_ctrl_buf_->data(), result); |
| 447 | 485 |
| 448 if (!ctrl_response_buffer_.ResponseAvailable()) { | 486 if (!ctrl_response_buffer_->ResponseAvailable()) { |
| 449 // Read more data from the control socket. | 487 // Read more data from the control socket. |
| 450 next_state_ = STATE_CTRL_READ; | 488 next_state_ = STATE_CTRL_READ; |
| 451 return OK; | 489 return OK; |
| 452 } | 490 } |
| 453 | 491 |
| 454 return ProcessCtrlResponse(); | 492 return ProcessCtrlResponse(); |
| 455 } | 493 } |
| 456 | 494 |
| 457 int FtpNetworkTransaction::DoCtrlWrite() { | 495 int FtpNetworkTransaction::DoCtrlWrite() { |
| 458 next_state_ = STATE_CTRL_WRITE_COMPLETE; | 496 next_state_ = STATE_CTRL_WRITE_COMPLETE; |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 479 } else { | 517 } else { |
| 480 next_state_ = STATE_CTRL_WRITE; | 518 next_state_ = STATE_CTRL_WRITE; |
| 481 } | 519 } |
| 482 return OK; | 520 return OK; |
| 483 } | 521 } |
| 484 | 522 |
| 485 // FTP Commands and responses | 523 // FTP Commands and responses |
| 486 | 524 |
| 487 // USER Command. | 525 // USER Command. |
| 488 int FtpNetworkTransaction::DoCtrlWriteUSER() { | 526 int FtpNetworkTransaction::DoCtrlWriteUSER() { |
| 489 std::string command = "USER"; | 527 std::string command = "USER " + WideToUTF8(username_); |
|
wtc
2009/08/25 20:52:50
Can you add a comment to the header to explain why
| |
| 490 if (request_->url.has_username()) { | |
| 491 command.append(" "); | |
| 492 command.append(request_->url.username()); | |
| 493 } else { | |
| 494 is_anonymous_ = true; | |
| 495 command.append(" anonymous"); | |
| 496 } | |
| 497 next_state_ = STATE_CTRL_READ; | 528 next_state_ = STATE_CTRL_READ; |
| 498 return SendFtpCommand(command, COMMAND_USER); | 529 return SendFtpCommand(command, COMMAND_USER); |
| 499 } | 530 } |
| 500 | 531 |
| 501 int FtpNetworkTransaction::ProcessResponseUSER( | 532 int FtpNetworkTransaction::ProcessResponseUSER( |
| 502 const FtpCtrlResponse& response) { | 533 const FtpCtrlResponse& response) { |
| 503 switch (GetErrorClass(response.status_code)) { | 534 switch (GetErrorClass(response.status_code)) { |
| 504 case ERROR_CLASS_OK: | 535 case ERROR_CLASS_OK: |
| 505 next_state_ = STATE_CTRL_WRITE_SYST; | 536 next_state_ = STATE_CTRL_WRITE_SYST; |
| 506 break; | 537 break; |
| 507 case ERROR_CLASS_INFO_NEEDED: | 538 case ERROR_CLASS_INFO_NEEDED: |
| 508 next_state_ = STATE_CTRL_WRITE_PASS; | 539 next_state_ = STATE_CTRL_WRITE_PASS; |
| 509 break; | 540 break; |
| 510 case ERROR_CLASS_TRANSIENT_ERROR: | 541 case ERROR_CLASS_TRANSIENT_ERROR: |
| 511 if (response.status_code == 421) | 542 if (response.status_code == 421) |
| 512 return Stop(ERR_FAILED); | 543 return Stop(ERR_FAILED); |
| 513 break; | 544 break; |
| 514 case ERROR_CLASS_PERMANENT_ERROR: | 545 case ERROR_CLASS_PERMANENT_ERROR: |
| 515 return Stop(ERR_FAILED); | 546 return Stop(ERR_FAILED); |
| 516 default: | 547 default: |
| 517 NOTREACHED(); | 548 NOTREACHED(); |
| 518 return Stop(ERR_UNEXPECTED); | 549 return Stop(ERR_UNEXPECTED); |
| 519 } | 550 } |
| 520 return OK; | 551 return OK; |
| 521 } | 552 } |
| 522 | 553 |
| 523 // PASS command. | 554 // PASS command. |
| 524 int FtpNetworkTransaction::DoCtrlWritePASS() { | 555 int FtpNetworkTransaction::DoCtrlWritePASS() { |
| 525 std::string command = "PASS"; | 556 std::string command = "PASS " + WideToUTF8(password_); |
|
eroman
2009/09/01 07:12:37
PLEASE READ: This looks dangerous!
|username_| an
| |
| 526 if (request_->url.has_password()) { | |
| 527 command.append(" "); | |
| 528 command.append(request_->url.password()); | |
| 529 } else { | |
| 530 command.append(" "); | |
| 531 command.append("chrome@example.com"); | |
| 532 } | |
| 533 next_state_ = STATE_CTRL_READ; | 557 next_state_ = STATE_CTRL_READ; |
| 534 return SendFtpCommand(command, COMMAND_PASS); | 558 return SendFtpCommand(command, COMMAND_PASS); |
| 535 } | 559 } |
| 536 | 560 |
| 537 int FtpNetworkTransaction::ProcessResponsePASS( | 561 int FtpNetworkTransaction::ProcessResponsePASS( |
| 538 const FtpCtrlResponse& response) { | 562 const FtpCtrlResponse& response) { |
| 539 switch (GetErrorClass(response.status_code)) { | 563 switch (GetErrorClass(response.status_code)) { |
| 540 case ERROR_CLASS_OK: | 564 case ERROR_CLASS_OK: |
| 541 next_state_ = STATE_CTRL_WRITE_SYST; | 565 next_state_ = STATE_CTRL_WRITE_SYST; |
| 542 break; | 566 break; |
| 543 case ERROR_CLASS_INFO_NEEDED: | 567 case ERROR_CLASS_INFO_NEEDED: |
| 544 next_state_ = STATE_CTRL_WRITE_ACCT; | 568 next_state_ = STATE_CTRL_WRITE_ACCT; |
| 545 break; | 569 break; |
| 546 case ERROR_CLASS_TRANSIENT_ERROR: | 570 case ERROR_CLASS_TRANSIENT_ERROR: |
| 547 if (response.status_code == 421) { | 571 if (response.status_code == 421) { |
| 548 // TODO(ibrar): Retry here. | 572 // TODO(ibrar): Retry here. |
| 549 } | 573 } |
| 550 return Stop(ERR_FAILED); | 574 return Stop(ERR_FAILED); |
| 551 case ERROR_CLASS_PERMANENT_ERROR: | 575 case ERROR_CLASS_PERMANENT_ERROR: |
| 552 if (response.status_code == 503) { | 576 if (response.status_code == 503) { |
| 553 next_state_ = STATE_CTRL_WRITE_USER; | 577 next_state_ = STATE_CTRL_WRITE_USER; |
| 554 } else { | 578 } else { |
| 555 // TODO(ibrar): Retry here. | 579 response_.auth_needed = true; |
|
eroman
2009/09/01 07:12:37
Hm, I dont know about this... will have to look mo
| |
| 556 return Stop(ERR_FAILED); | 580 return Stop(ERR_FAILED); |
| 557 } | 581 } |
| 558 break; | 582 break; |
| 559 default: | 583 default: |
| 560 NOTREACHED(); | 584 NOTREACHED(); |
| 561 return Stop(ERR_UNEXPECTED); | 585 return Stop(ERR_UNEXPECTED); |
| 562 } | 586 } |
| 563 return OK; | 587 return OK; |
| 564 } | 588 } |
| 565 | 589 |
| (...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 974 read_data_buf_->data()[0] = 0; | 998 read_data_buf_->data()[0] = 0; |
| 975 return data_socket_->Read(read_data_buf_, read_data_buf_len_, | 999 return data_socket_->Read(read_data_buf_, read_data_buf_len_, |
| 976 &io_callback_); | 1000 &io_callback_); |
| 977 } | 1001 } |
| 978 | 1002 |
| 979 int FtpNetworkTransaction::DoDataReadComplete(int result) { | 1003 int FtpNetworkTransaction::DoDataReadComplete(int result) { |
| 980 return result; | 1004 return result; |
| 981 } | 1005 } |
| 982 | 1006 |
| 983 } // namespace net | 1007 } // namespace net |
| OLD | NEW |