| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the 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/histogram.h" | 8 #include "base/histogram.h" |
| 9 #include "base/string_util.h" | 9 #include "base/string_util.h" |
| 10 #include "base/utf_string_conversions.h" | 10 #include "base/utf_string_conversions.h" |
| (...skipping 25 matching lines...) Expand all Loading... |
| 36 // characters in the command if the request path contains them. To be | 36 // characters in the command if the request path contains them. To be |
| 37 // compatible, we do the same and allow non-ASCII characters in a command. | 37 // compatible, we do the same and allow non-ASCII characters in a command. |
| 38 | 38 |
| 39 // Protect agains newline injection attack. | 39 // Protect agains newline injection attack. |
| 40 if (input.find_first_of("\r\n") != std::string::npos) | 40 if (input.find_first_of("\r\n") != std::string::npos) |
| 41 return false; | 41 return false; |
| 42 | 42 |
| 43 return true; | 43 return true; |
| 44 } | 44 } |
| 45 | 45 |
| 46 enum ErrorClass { |
| 47 // The requested action was initiated. The client should expect another |
| 48 // reply before issuing the next command. |
| 49 ERROR_CLASS_INITIATED, |
| 50 |
| 51 // The requested action has been successfully completed. |
| 52 ERROR_CLASS_OK, |
| 53 |
| 54 // The command has been accepted, but to complete the operation, more |
| 55 // information must be sent by the client. |
| 56 ERROR_CLASS_INFO_NEEDED, |
| 57 |
| 58 // The command was not accepted and the requested action did not take place. |
| 59 // This condition is temporary, and the client is encouraged to restart the |
| 60 // command sequence. |
| 61 ERROR_CLASS_TRANSIENT_ERROR, |
| 62 |
| 63 // The command was not accepted and the requested action did not take place. |
| 64 // This condition is rather permanent, and the client is discouraged from |
| 65 // repeating the exact request. |
| 66 ERROR_CLASS_PERMANENT_ERROR, |
| 67 }; |
| 68 |
| 69 // Returns the error class for given response code. Caller should ensure |
| 70 // that |response_code| is in range 100-599. |
| 71 ErrorClass GetErrorClass(int response_code) { |
| 72 if (response_code >= 100 && response_code <= 199) |
| 73 return ERROR_CLASS_INITIATED; |
| 74 |
| 75 if (response_code >= 200 && response_code <= 299) |
| 76 return ERROR_CLASS_OK; |
| 77 |
| 78 if (response_code >= 300 && response_code <= 399) |
| 79 return ERROR_CLASS_INFO_NEEDED; |
| 80 |
| 81 if (response_code >= 400 && response_code <= 499) |
| 82 return ERROR_CLASS_TRANSIENT_ERROR; |
| 83 |
| 84 if (response_code >= 500 && response_code <= 599) |
| 85 return ERROR_CLASS_PERMANENT_ERROR; |
| 86 |
| 87 // We should not be called on invalid error codes. |
| 88 NOTREACHED() << response_code; |
| 89 return ERROR_CLASS_PERMANENT_ERROR; |
| 90 } |
| 91 |
| 92 // Returns network error code for received FTP |response_code|. |
| 93 int GetNetErrorCodeForFtpResponseCode(int response_code) { |
| 94 switch (response_code) { |
| 95 case 421: |
| 96 return net::ERR_FTP_SERVICE_UNAVAILABLE; |
| 97 case 426: |
| 98 return net::ERR_FTP_TRANSFER_ABORTED; |
| 99 case 450: |
| 100 return net::ERR_FTP_FILE_BUSY; |
| 101 case 500: |
| 102 case 501: |
| 103 return net::ERR_FTP_SYNTAX_ERROR; |
| 104 case 502: |
| 105 case 504: |
| 106 return net::ERR_FTP_COMMAND_NOT_SUPPORTED; |
| 107 case 503: |
| 108 return net::ERR_FTP_BAD_COMMAND_SEQUENCE; |
| 109 default: |
| 110 return net::ERR_FTP_FAILED; |
| 111 } |
| 112 } |
| 113 |
| 46 // From RFC 2428 Section 3: | 114 // From RFC 2428 Section 3: |
| 47 // The text returned in response to the EPSV command MUST be: | 115 // The text returned in response to the EPSV command MUST be: |
| 48 // <some text> (<d><d><d><tcp-port><d>) | 116 // <some text> (<d><d><d><tcp-port><d>) |
| 49 // <d> is a delimiter character, ideally to be | | 117 // <d> is a delimiter character, ideally to be | |
| 50 bool ExtractPortFromEPSVResponse(const net::FtpCtrlResponse& response, | 118 bool ExtractPortFromEPSVResponse(const net::FtpCtrlResponse& response, |
| 51 int* port) { | 119 int* port) { |
| 52 if (response.lines.size() != 1) | 120 if (response.lines.size() != 1) |
| 53 return false; | 121 return false; |
| 54 const char* ptr = response.lines[0].c_str(); | 122 const char* ptr = response.lines[0].c_str(); |
| 55 while (*ptr && *ptr != '(') | 123 while (*ptr && *ptr != '(') |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 176 | 244 |
| 177 next_state_ = STATE_CTRL_RESOLVE_HOST; | 245 next_state_ = STATE_CTRL_RESOLVE_HOST; |
| 178 int rv = DoLoop(OK); | 246 int rv = DoLoop(OK); |
| 179 if (rv == ERR_IO_PENDING) | 247 if (rv == ERR_IO_PENDING) |
| 180 user_callback_ = callback; | 248 user_callback_ = callback; |
| 181 return rv; | 249 return rv; |
| 182 } | 250 } |
| 183 | 251 |
| 184 int FtpNetworkTransaction::RestartIgnoringLastError( | 252 int FtpNetworkTransaction::RestartIgnoringLastError( |
| 185 CompletionCallback* callback) { | 253 CompletionCallback* callback) { |
| 186 return ERR_FAILED; | 254 return ERR_NOT_IMPLEMENTED; |
| 187 } | 255 } |
| 188 | 256 |
| 189 int FtpNetworkTransaction::Read(IOBuffer* buf, | 257 int FtpNetworkTransaction::Read(IOBuffer* buf, |
| 190 int buf_len, | 258 int buf_len, |
| 191 CompletionCallback* callback) { | 259 CompletionCallback* callback) { |
| 192 DCHECK(buf); | 260 DCHECK(buf); |
| 193 DCHECK_GT(buf_len, 0); | 261 DCHECK_GT(buf_len, 0); |
| 194 | 262 |
| 195 read_data_buf_ = buf; | 263 read_data_buf_ = buf; |
| 196 read_data_buf_len_ = buf_len; | 264 read_data_buf_len_ = buf_len; |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 256 write_command_buf_ = new IOBufferWithSize(command.length() + 2); | 324 write_command_buf_ = new IOBufferWithSize(command.length() + 2); |
| 257 write_buf_ = new DrainableIOBuffer(write_command_buf_, | 325 write_buf_ = new DrainableIOBuffer(write_command_buf_, |
| 258 write_command_buf_->size()); | 326 write_command_buf_->size()); |
| 259 memcpy(write_command_buf_->data(), command.data(), command.length()); | 327 memcpy(write_command_buf_->data(), command.data(), command.length()); |
| 260 memcpy(write_command_buf_->data() + command.length(), kCRLF, 2); | 328 memcpy(write_command_buf_->data() + command.length(), kCRLF, 2); |
| 261 | 329 |
| 262 next_state_ = STATE_CTRL_WRITE; | 330 next_state_ = STATE_CTRL_WRITE; |
| 263 return OK; | 331 return OK; |
| 264 } | 332 } |
| 265 | 333 |
| 266 // static | |
| 267 FtpNetworkTransaction::ErrorClass FtpNetworkTransaction::GetErrorClass( | |
| 268 int response_code) { | |
| 269 if (response_code >= 100 && response_code <= 199) | |
| 270 return ERROR_CLASS_INITIATED; | |
| 271 | |
| 272 if (response_code >= 200 && response_code <= 299) | |
| 273 return ERROR_CLASS_OK; | |
| 274 | |
| 275 if (response_code >= 300 && response_code <= 399) | |
| 276 return ERROR_CLASS_INFO_NEEDED; | |
| 277 | |
| 278 if (response_code >= 400 && response_code <= 499) | |
| 279 return ERROR_CLASS_TRANSIENT_ERROR; | |
| 280 | |
| 281 if (response_code >= 500 && response_code <= 599) | |
| 282 return ERROR_CLASS_PERMANENT_ERROR; | |
| 283 | |
| 284 // We should not be called on invalid error codes. | |
| 285 NOTREACHED(); | |
| 286 return ERROR_CLASS_PERMANENT_ERROR; | |
| 287 } | |
| 288 | |
| 289 int FtpNetworkTransaction::ProcessCtrlResponse() { | 334 int FtpNetworkTransaction::ProcessCtrlResponse() { |
| 290 FtpCtrlResponse response = ctrl_response_buffer_->PopResponse(); | 335 FtpCtrlResponse response = ctrl_response_buffer_->PopResponse(); |
| 291 | 336 |
| 292 int rv = OK; | 337 int rv = OK; |
| 293 switch (command_sent_) { | 338 switch (command_sent_) { |
| 294 case COMMAND_NONE: | 339 case COMMAND_NONE: |
| 295 // TODO(phajdan.jr): Check for errors in the welcome message. | 340 // TODO(phajdan.jr): Check for errors in the welcome message. |
| 296 next_state_ = STATE_CTRL_WRITE_USER; | 341 next_state_ = STATE_CTRL_WRITE_USER; |
| 297 break; | 342 break; |
| 298 case COMMAND_USER: | 343 case COMMAND_USER: |
| (...skipping 368 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 667 int FtpNetworkTransaction::ProcessResponseUSER( | 712 int FtpNetworkTransaction::ProcessResponseUSER( |
| 668 const FtpCtrlResponse& response) { | 713 const FtpCtrlResponse& response) { |
| 669 switch (GetErrorClass(response.status_code)) { | 714 switch (GetErrorClass(response.status_code)) { |
| 670 case ERROR_CLASS_OK: | 715 case ERROR_CLASS_OK: |
| 671 next_state_ = STATE_CTRL_WRITE_SYST; | 716 next_state_ = STATE_CTRL_WRITE_SYST; |
| 672 break; | 717 break; |
| 673 case ERROR_CLASS_INFO_NEEDED: | 718 case ERROR_CLASS_INFO_NEEDED: |
| 674 next_state_ = STATE_CTRL_WRITE_PASS; | 719 next_state_ = STATE_CTRL_WRITE_PASS; |
| 675 break; | 720 break; |
| 676 case ERROR_CLASS_TRANSIENT_ERROR: | 721 case ERROR_CLASS_TRANSIENT_ERROR: |
| 677 return Stop(ERR_FAILED); | 722 return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code)); |
| 678 case ERROR_CLASS_PERMANENT_ERROR: | 723 case ERROR_CLASS_PERMANENT_ERROR: |
| 679 response_.needs_auth = true; | 724 response_.needs_auth = true; |
| 680 return Stop(ERR_FAILED); | 725 return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code)); |
| 681 default: | 726 default: |
| 682 NOTREACHED(); | 727 NOTREACHED(); |
| 683 return Stop(ERR_UNEXPECTED); | 728 return Stop(ERR_UNEXPECTED); |
| 684 } | 729 } |
| 685 return OK; | 730 return OK; |
| 686 } | 731 } |
| 687 | 732 |
| 688 // PASS command. | 733 // PASS command. |
| 689 int FtpNetworkTransaction::DoCtrlWritePASS() { | 734 int FtpNetworkTransaction::DoCtrlWritePASS() { |
| 690 std::string command = "PASS " + WideToUTF8(password_); | 735 std::string command = "PASS " + WideToUTF8(password_); |
| 691 | 736 |
| 692 if (!IsValidFTPCommandString(command)) | 737 if (!IsValidFTPCommandString(command)) |
| 693 return Stop(ERR_MALFORMED_IDENTITY); | 738 return Stop(ERR_MALFORMED_IDENTITY); |
| 694 | 739 |
| 695 next_state_ = STATE_CTRL_READ; | 740 next_state_ = STATE_CTRL_READ; |
| 696 return SendFtpCommand(command, COMMAND_PASS); | 741 return SendFtpCommand(command, COMMAND_PASS); |
| 697 } | 742 } |
| 698 | 743 |
| 699 int FtpNetworkTransaction::ProcessResponsePASS( | 744 int FtpNetworkTransaction::ProcessResponsePASS( |
| 700 const FtpCtrlResponse& response) { | 745 const FtpCtrlResponse& response) { |
| 701 switch (GetErrorClass(response.status_code)) { | 746 switch (GetErrorClass(response.status_code)) { |
| 702 case ERROR_CLASS_OK: | 747 case ERROR_CLASS_OK: |
| 703 next_state_ = STATE_CTRL_WRITE_SYST; | 748 next_state_ = STATE_CTRL_WRITE_SYST; |
| 704 break; | 749 break; |
| 705 case ERROR_CLASS_INFO_NEEDED: | 750 case ERROR_CLASS_INFO_NEEDED: |
| 706 return Stop(ERR_FAILED); | 751 return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code)); |
| 707 case ERROR_CLASS_TRANSIENT_ERROR: | 752 case ERROR_CLASS_TRANSIENT_ERROR: |
| 708 return Stop(ERR_FAILED); | 753 return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code)); |
| 709 case ERROR_CLASS_PERMANENT_ERROR: | 754 case ERROR_CLASS_PERMANENT_ERROR: |
| 710 response_.needs_auth = true; | 755 response_.needs_auth = true; |
| 711 return Stop(ERR_FAILED); | 756 return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code)); |
| 712 default: | 757 default: |
| 713 NOTREACHED(); | 758 NOTREACHED(); |
| 714 return Stop(ERR_UNEXPECTED); | 759 return Stop(ERR_UNEXPECTED); |
| 715 } | 760 } |
| 716 return OK; | 761 return OK; |
| 717 } | 762 } |
| 718 | 763 |
| 719 // SYST command. | 764 // SYST command. |
| 720 int FtpNetworkTransaction::DoCtrlWriteSYST() { | 765 int FtpNetworkTransaction::DoCtrlWriteSYST() { |
| 721 std::string command = "SYST"; | 766 std::string command = "SYST"; |
| (...skipping 28 matching lines...) Expand all Loading... |
| 750 } else if (line.find("vms") != std::string::npos) { | 795 } else if (line.find("vms") != std::string::npos) { |
| 751 system_type_ = SYSTEM_TYPE_VMS; | 796 system_type_ = SYSTEM_TYPE_VMS; |
| 752 } | 797 } |
| 753 } | 798 } |
| 754 next_state_ = STATE_CTRL_WRITE_PWD; | 799 next_state_ = STATE_CTRL_WRITE_PWD; |
| 755 break; | 800 break; |
| 756 } | 801 } |
| 757 case ERROR_CLASS_INFO_NEEDED: | 802 case ERROR_CLASS_INFO_NEEDED: |
| 758 return Stop(ERR_INVALID_RESPONSE); | 803 return Stop(ERR_INVALID_RESPONSE); |
| 759 case ERROR_CLASS_TRANSIENT_ERROR: | 804 case ERROR_CLASS_TRANSIENT_ERROR: |
| 760 return Stop(ERR_FAILED); | 805 return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code)); |
| 761 case ERROR_CLASS_PERMANENT_ERROR: | 806 case ERROR_CLASS_PERMANENT_ERROR: |
| 762 // Server does not recognize the SYST command so proceed. | 807 // Server does not recognize the SYST command so proceed. |
| 763 next_state_ = STATE_CTRL_WRITE_PWD; | 808 next_state_ = STATE_CTRL_WRITE_PWD; |
| 764 break; | 809 break; |
| 765 default: | 810 default: |
| 766 NOTREACHED(); | 811 NOTREACHED(); |
| 767 return Stop(ERR_UNEXPECTED); | 812 return Stop(ERR_UNEXPECTED); |
| 768 } | 813 } |
| 769 return OK; | 814 return OK; |
| 770 } | 815 } |
| (...skipping 26 matching lines...) Expand all Loading... |
| 797 line = FtpUtil::VMSPathToUnix(line); | 842 line = FtpUtil::VMSPathToUnix(line); |
| 798 if (line.length() && line[line.length() - 1] == '/') | 843 if (line.length() && line[line.length() - 1] == '/') |
| 799 line.erase(line.length() - 1); | 844 line.erase(line.length() - 1); |
| 800 current_remote_directory_ = line; | 845 current_remote_directory_ = line; |
| 801 next_state_ = STATE_CTRL_WRITE_TYPE; | 846 next_state_ = STATE_CTRL_WRITE_TYPE; |
| 802 break; | 847 break; |
| 803 } | 848 } |
| 804 case ERROR_CLASS_INFO_NEEDED: | 849 case ERROR_CLASS_INFO_NEEDED: |
| 805 return Stop(ERR_INVALID_RESPONSE); | 850 return Stop(ERR_INVALID_RESPONSE); |
| 806 case ERROR_CLASS_TRANSIENT_ERROR: | 851 case ERROR_CLASS_TRANSIENT_ERROR: |
| 807 return Stop(ERR_FAILED); | 852 return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code)); |
| 808 case ERROR_CLASS_PERMANENT_ERROR: | 853 case ERROR_CLASS_PERMANENT_ERROR: |
| 809 return Stop(ERR_FAILED); | 854 return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code)); |
| 810 default: | 855 default: |
| 811 NOTREACHED(); | 856 NOTREACHED(); |
| 812 return Stop(ERR_UNEXPECTED); | 857 return Stop(ERR_UNEXPECTED); |
| 813 } | 858 } |
| 814 return OK; | 859 return OK; |
| 815 } | 860 } |
| 816 | 861 |
| 817 // TYPE command. | 862 // TYPE command. |
| 818 int FtpNetworkTransaction::DoCtrlWriteTYPE() { | 863 int FtpNetworkTransaction::DoCtrlWriteTYPE() { |
| 819 std::string command = "TYPE "; | 864 std::string command = "TYPE "; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 833 const FtpCtrlResponse& response) { | 878 const FtpCtrlResponse& response) { |
| 834 switch (GetErrorClass(response.status_code)) { | 879 switch (GetErrorClass(response.status_code)) { |
| 835 case ERROR_CLASS_INITIATED: | 880 case ERROR_CLASS_INITIATED: |
| 836 return Stop(ERR_INVALID_RESPONSE); | 881 return Stop(ERR_INVALID_RESPONSE); |
| 837 case ERROR_CLASS_OK: | 882 case ERROR_CLASS_OK: |
| 838 next_state_ = use_epsv_ ? STATE_CTRL_WRITE_EPSV : STATE_CTRL_WRITE_PASV; | 883 next_state_ = use_epsv_ ? STATE_CTRL_WRITE_EPSV : STATE_CTRL_WRITE_PASV; |
| 839 break; | 884 break; |
| 840 case ERROR_CLASS_INFO_NEEDED: | 885 case ERROR_CLASS_INFO_NEEDED: |
| 841 return Stop(ERR_INVALID_RESPONSE); | 886 return Stop(ERR_INVALID_RESPONSE); |
| 842 case ERROR_CLASS_TRANSIENT_ERROR: | 887 case ERROR_CLASS_TRANSIENT_ERROR: |
| 843 return Stop(ERR_FAILED); | 888 return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code)); |
| 844 case ERROR_CLASS_PERMANENT_ERROR: | 889 case ERROR_CLASS_PERMANENT_ERROR: |
| 845 return Stop(ERR_FAILED); | 890 return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code)); |
| 846 default: | 891 default: |
| 847 NOTREACHED(); | 892 NOTREACHED(); |
| 848 return Stop(ERR_UNEXPECTED); | 893 return Stop(ERR_UNEXPECTED); |
| 849 } | 894 } |
| 850 return OK; | 895 return OK; |
| 851 } | 896 } |
| 852 | 897 |
| 853 // EPSV command | 898 // EPSV command |
| 854 int FtpNetworkTransaction::DoCtrlWriteEPSV() { | 899 int FtpNetworkTransaction::DoCtrlWriteEPSV() { |
| 855 const std::string command = "EPSV"; | 900 const std::string command = "EPSV"; |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 900 if (!ExtractPortFromPASVResponse(response, &data_connection_port_)) | 945 if (!ExtractPortFromPASVResponse(response, &data_connection_port_)) |
| 901 return Stop(ERR_INVALID_RESPONSE); | 946 return Stop(ERR_INVALID_RESPONSE); |
| 902 if (data_connection_port_ < 1024 || | 947 if (data_connection_port_ < 1024 || |
| 903 !IsPortAllowedByFtp(data_connection_port_)) | 948 !IsPortAllowedByFtp(data_connection_port_)) |
| 904 return Stop(ERR_UNSAFE_PORT); | 949 return Stop(ERR_UNSAFE_PORT); |
| 905 next_state_ = STATE_DATA_CONNECT; | 950 next_state_ = STATE_DATA_CONNECT; |
| 906 break; | 951 break; |
| 907 case ERROR_CLASS_INFO_NEEDED: | 952 case ERROR_CLASS_INFO_NEEDED: |
| 908 return Stop(ERR_INVALID_RESPONSE); | 953 return Stop(ERR_INVALID_RESPONSE); |
| 909 case ERROR_CLASS_TRANSIENT_ERROR: | 954 case ERROR_CLASS_TRANSIENT_ERROR: |
| 910 return Stop(ERR_FTP_PASV_COMMAND_FAILED); | 955 return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code)); |
| 911 case ERROR_CLASS_PERMANENT_ERROR: | 956 case ERROR_CLASS_PERMANENT_ERROR: |
| 912 return Stop(ERR_FTP_PASV_COMMAND_FAILED); | 957 return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code)); |
| 913 default: | 958 default: |
| 914 NOTREACHED(); | 959 NOTREACHED(); |
| 915 return Stop(ERR_UNEXPECTED); | 960 return Stop(ERR_UNEXPECTED); |
| 916 } | 961 } |
| 917 return OK; | 962 return OK; |
| 918 } | 963 } |
| 919 | 964 |
| 920 // SIZE command | 965 // SIZE command |
| 921 int FtpNetworkTransaction::DoCtrlWriteSIZE() { | 966 int FtpNetworkTransaction::DoCtrlWriteSIZE() { |
| 922 std::string command = "SIZE " + GetRequestPathForFtpCommand(false); | 967 std::string command = "SIZE " + GetRequestPathForFtpCommand(false); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 942 case ERROR_CLASS_INFO_NEEDED: | 987 case ERROR_CLASS_INFO_NEEDED: |
| 943 break; | 988 break; |
| 944 case ERROR_CLASS_TRANSIENT_ERROR: | 989 case ERROR_CLASS_TRANSIENT_ERROR: |
| 945 break; | 990 break; |
| 946 case ERROR_CLASS_PERMANENT_ERROR: | 991 case ERROR_CLASS_PERMANENT_ERROR: |
| 947 // It's possible that SIZE failed because the path is a directory. | 992 // It's possible that SIZE failed because the path is a directory. |
| 948 if (response.status_code == 550 && | 993 if (response.status_code == 550 && |
| 949 resource_type_ == RESOURCE_TYPE_UNKNOWN) { | 994 resource_type_ == RESOURCE_TYPE_UNKNOWN) { |
| 950 resource_type_ = RESOURCE_TYPE_DIRECTORY; | 995 resource_type_ = RESOURCE_TYPE_DIRECTORY; |
| 951 } else if (resource_type_ != RESOURCE_TYPE_DIRECTORY) { | 996 } else if (resource_type_ != RESOURCE_TYPE_DIRECTORY) { |
| 952 return Stop(ERR_FAILED); | 997 return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code)); |
| 953 } | 998 } |
| 954 break; | 999 break; |
| 955 default: | 1000 default: |
| 956 NOTREACHED(); | 1001 NOTREACHED(); |
| 957 return Stop(ERR_UNEXPECTED); | 1002 return Stop(ERR_UNEXPECTED); |
| 958 } | 1003 } |
| 959 | 1004 |
| 960 if (resource_type_ == RESOURCE_TYPE_DIRECTORY) | 1005 if (resource_type_ == RESOURCE_TYPE_DIRECTORY) |
| 961 next_state_ = STATE_CTRL_WRITE_CWD; | 1006 next_state_ = STATE_CTRL_WRITE_CWD; |
| 962 else | 1007 else |
| (...skipping 15 matching lines...) Expand all Loading... |
| 978 case ERROR_CLASS_INITIATED: | 1023 case ERROR_CLASS_INITIATED: |
| 979 // We want the client to start reading the response at this point. | 1024 // We want the client to start reading the response at this point. |
| 980 // It got here either through Start or RestartWithAuth. We want that | 1025 // It got here either through Start or RestartWithAuth. We want that |
| 981 // method to complete. Not setting next state here will make DoLoop exit | 1026 // method to complete. Not setting next state here will make DoLoop exit |
| 982 // and in turn make Start/RestartWithAuth complete. | 1027 // and in turn make Start/RestartWithAuth complete. |
| 983 break; | 1028 break; |
| 984 case ERROR_CLASS_OK: | 1029 case ERROR_CLASS_OK: |
| 985 next_state_ = STATE_CTRL_WRITE_QUIT; | 1030 next_state_ = STATE_CTRL_WRITE_QUIT; |
| 986 break; | 1031 break; |
| 987 case ERROR_CLASS_INFO_NEEDED: | 1032 case ERROR_CLASS_INFO_NEEDED: |
| 988 return Stop(ERR_FAILED); | 1033 return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code)); |
| 989 case ERROR_CLASS_TRANSIENT_ERROR: | 1034 case ERROR_CLASS_TRANSIENT_ERROR: |
| 990 return Stop(ERR_FAILED); | 1035 return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code)); |
| 991 case ERROR_CLASS_PERMANENT_ERROR: | 1036 case ERROR_CLASS_PERMANENT_ERROR: |
| 992 // Code 550 means "Failed to open file". Other codes are unrelated, | 1037 // Code 550 means "Failed to open file". Other codes are unrelated, |
| 993 // like "Not logged in" etc. | 1038 // like "Not logged in" etc. |
| 994 if (response.status_code != 550) | 1039 if (response.status_code != 550) |
| 995 return Stop(ERR_FAILED); | 1040 return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code)); |
| 996 | 1041 |
| 997 // It's possible that RETR failed because the path is a directory. | 1042 // It's possible that RETR failed because the path is a directory. |
| 998 resource_type_ = RESOURCE_TYPE_DIRECTORY; | 1043 resource_type_ = RESOURCE_TYPE_DIRECTORY; |
| 999 | 1044 |
| 1000 // We're going to try CWD next, but first send a PASV one more time, | 1045 // We're going to try CWD next, but first send a PASV one more time, |
| 1001 // because some FTP servers, including FileZilla, require that. | 1046 // because some FTP servers, including FileZilla, require that. |
| 1002 // See http://crbug.com/25316. | 1047 // See http://crbug.com/25316. |
| 1003 next_state_ = use_epsv_ ? STATE_CTRL_WRITE_EPSV : STATE_CTRL_WRITE_PASV; | 1048 next_state_ = use_epsv_ ? STATE_CTRL_WRITE_EPSV : STATE_CTRL_WRITE_PASV; |
| 1004 break; | 1049 break; |
| 1005 default: | 1050 default: |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1019 int FtpNetworkTransaction::ProcessResponseCWD(const FtpCtrlResponse& response) { | 1064 int FtpNetworkTransaction::ProcessResponseCWD(const FtpCtrlResponse& response) { |
| 1020 switch (GetErrorClass(response.status_code)) { | 1065 switch (GetErrorClass(response.status_code)) { |
| 1021 case ERROR_CLASS_INITIATED: | 1066 case ERROR_CLASS_INITIATED: |
| 1022 return Stop(ERR_INVALID_RESPONSE); | 1067 return Stop(ERR_INVALID_RESPONSE); |
| 1023 case ERROR_CLASS_OK: | 1068 case ERROR_CLASS_OK: |
| 1024 next_state_ = STATE_CTRL_WRITE_MLSD; | 1069 next_state_ = STATE_CTRL_WRITE_MLSD; |
| 1025 break; | 1070 break; |
| 1026 case ERROR_CLASS_INFO_NEEDED: | 1071 case ERROR_CLASS_INFO_NEEDED: |
| 1027 return Stop(ERR_INVALID_RESPONSE); | 1072 return Stop(ERR_INVALID_RESPONSE); |
| 1028 case ERROR_CLASS_TRANSIENT_ERROR: | 1073 case ERROR_CLASS_TRANSIENT_ERROR: |
| 1029 return Stop(ERR_FAILED); | 1074 return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code)); |
| 1030 case ERROR_CLASS_PERMANENT_ERROR: | 1075 case ERROR_CLASS_PERMANENT_ERROR: |
| 1031 if (resource_type_ == RESOURCE_TYPE_DIRECTORY && | 1076 if (resource_type_ == RESOURCE_TYPE_DIRECTORY && |
| 1032 response.status_code == 550) { | 1077 response.status_code == 550) { |
| 1033 // We're assuming that the resource is a directory, but the server says | 1078 // We're assuming that the resource is a directory, but the server says |
| 1034 // it's not true. The most probable interpretation is that it doesn't | 1079 // it's not true. The most probable interpretation is that it doesn't |
| 1035 // exist (with FTP we can't be sure). | 1080 // exist (with FTP we can't be sure). |
| 1036 return Stop(ERR_FILE_NOT_FOUND); | 1081 return Stop(ERR_FILE_NOT_FOUND); |
| 1037 } | 1082 } |
| 1038 return Stop(ERR_FAILED); | 1083 return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code)); |
| 1039 default: | 1084 default: |
| 1040 NOTREACHED(); | 1085 NOTREACHED(); |
| 1041 return Stop(ERR_UNEXPECTED); | 1086 return Stop(ERR_UNEXPECTED); |
| 1042 } | 1087 } |
| 1043 return OK; | 1088 return OK; |
| 1044 } | 1089 } |
| 1045 | 1090 |
| 1046 // MLSD command | 1091 // MLSD command |
| 1047 int FtpNetworkTransaction::DoCtrlWriteMLSD() { | 1092 int FtpNetworkTransaction::DoCtrlWriteMLSD() { |
| 1048 next_state_ = STATE_CTRL_READ; | 1093 next_state_ = STATE_CTRL_READ; |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1095 // and in turn make Start/RestartWithAuth complete. | 1140 // and in turn make Start/RestartWithAuth complete. |
| 1096 response_.is_directory_listing = true; | 1141 response_.is_directory_listing = true; |
| 1097 break; | 1142 break; |
| 1098 case ERROR_CLASS_OK: | 1143 case ERROR_CLASS_OK: |
| 1099 response_.is_directory_listing = true; | 1144 response_.is_directory_listing = true; |
| 1100 next_state_ = STATE_CTRL_WRITE_QUIT; | 1145 next_state_ = STATE_CTRL_WRITE_QUIT; |
| 1101 break; | 1146 break; |
| 1102 case ERROR_CLASS_INFO_NEEDED: | 1147 case ERROR_CLASS_INFO_NEEDED: |
| 1103 return Stop(ERR_INVALID_RESPONSE); | 1148 return Stop(ERR_INVALID_RESPONSE); |
| 1104 case ERROR_CLASS_TRANSIENT_ERROR: | 1149 case ERROR_CLASS_TRANSIENT_ERROR: |
| 1105 return Stop(ERR_FAILED); | 1150 return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code)); |
| 1106 case ERROR_CLASS_PERMANENT_ERROR: | 1151 case ERROR_CLASS_PERMANENT_ERROR: |
| 1107 return Stop(ERR_FAILED); | 1152 return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code)); |
| 1108 default: | 1153 default: |
| 1109 NOTREACHED(); | 1154 NOTREACHED(); |
| 1110 return Stop(ERR_UNEXPECTED); | 1155 return Stop(ERR_UNEXPECTED); |
| 1111 } | 1156 } |
| 1112 return OK; | 1157 return OK; |
| 1113 } | 1158 } |
| 1114 | 1159 |
| 1115 // QUIT command | 1160 // QUIT command |
| 1116 int FtpNetworkTransaction::DoCtrlWriteQUIT() { | 1161 int FtpNetworkTransaction::DoCtrlWriteQUIT() { |
| 1117 std::string command = "QUIT"; | 1162 std::string command = "QUIT"; |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1258 if (!had_error_type[type]) { | 1303 if (!had_error_type[type]) { |
| 1259 had_error_type[type] = true; | 1304 had_error_type[type] = true; |
| 1260 UMA_HISTOGRAM_ENUMERATION("Net.FtpDataConnectionErrorHappened", | 1305 UMA_HISTOGRAM_ENUMERATION("Net.FtpDataConnectionErrorHappened", |
| 1261 type, NUM_OF_NET_ERROR_TYPES); | 1306 type, NUM_OF_NET_ERROR_TYPES); |
| 1262 } | 1307 } |
| 1263 UMA_HISTOGRAM_ENUMERATION("Net.FtpDataConnectionErrorCount", | 1308 UMA_HISTOGRAM_ENUMERATION("Net.FtpDataConnectionErrorCount", |
| 1264 type, NUM_OF_NET_ERROR_TYPES); | 1309 type, NUM_OF_NET_ERROR_TYPES); |
| 1265 } | 1310 } |
| 1266 | 1311 |
| 1267 } // namespace net | 1312 } // namespace net |
| OLD | NEW |