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/escape.h" | |
10 #include "net/base/load_log.h" | 11 #include "net/base/load_log.h" |
11 #include "net/base/net_errors.h" | 12 #include "net/base/net_errors.h" |
12 #include "net/base/net_util.h" | 13 #include "net/base/net_util.h" |
13 #include "net/ftp/ftp_network_session.h" | 14 #include "net/ftp/ftp_network_session.h" |
14 #include "net/ftp/ftp_request_info.h" | 15 #include "net/ftp/ftp_request_info.h" |
15 #include "net/socket/client_socket.h" | 16 #include "net/socket/client_socket.h" |
16 #include "net/socket/client_socket_factory.h" | 17 #include "net/socket/client_socket_factory.h" |
17 | 18 |
18 // TODO(ibrar): Try to avoid sscanf. | 19 // TODO(ibrar): Try to avoid sscanf. |
19 #if !defined(COMPILER_MSVC) | 20 #if !defined(COMPILER_MSVC) |
20 #define sscanf_s sscanf | 21 #define sscanf_s sscanf |
21 #endif | 22 #endif |
22 | 23 |
23 const char kCRLF[] = "\r\n"; | 24 const char kCRLF[] = "\r\n"; |
24 | 25 |
25 const int kCtrlBufLen = 1024; | 26 const int kCtrlBufLen = 1024; |
26 | 27 |
27 namespace { | 28 namespace { |
28 | 29 |
29 // Returns true if |input| can be safely used as a part of FTP command. | 30 // Returns true if |input| can be safely used as a part of FTP command. |
30 bool IsValidFTPCommandString(const std::string& input) { | 31 bool IsValidFTPCommandString(const std::string& input) { |
31 // RFC 959 only allows ASCII strings. | |
eroman
2009/09/18 22:51:23
Please add a comment in IsValidFTPComment() that w
| |
32 if (!IsStringASCII(input)) | |
33 return false; | |
34 | |
35 // Protect agains newline injection attack. | 32 // Protect agains newline injection attack. |
36 if (input.find_first_of("\r\n") != std::string::npos) | 33 if (input.find_first_of("\r\n") != std::string::npos) |
37 return false; | 34 return false; |
38 | 35 |
39 return true; | 36 return true; |
40 } | 37 } |
41 | 38 |
42 } // namespace | 39 } // namespace |
43 | 40 |
44 namespace net { | 41 namespace net { |
(...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
315 user_callback_ = NULL; | 312 user_callback_ = NULL; |
316 c->Run(rv); | 313 c->Run(rv); |
317 } | 314 } |
318 | 315 |
319 void FtpNetworkTransaction::OnIOComplete(int result) { | 316 void FtpNetworkTransaction::OnIOComplete(int result) { |
320 int rv = DoLoop(result); | 317 int rv = DoLoop(result); |
321 if (rv != ERR_IO_PENDING) | 318 if (rv != ERR_IO_PENDING) |
322 DoCallback(rv); | 319 DoCallback(rv); |
323 } | 320 } |
324 | 321 |
322 std::string FtpNetworkTransaction::GetRequestPathForFtpCommand() const { | |
323 std::string path = (request_->url.has_path() ? request_->url.path() : "/"); | |
324 UnescapeRule::Type unescape_rules = UnescapeRule::SPACES | | |
325 UnescapeRule::URL_SPECIAL_CHARS; | |
326 path = UnescapeURLComponent(path, unescape_rules); | |
eroman
2009/09/18 22:51:23
Please add a comment that escaping to non-ASCII is
| |
327 DCHECK(IsValidFTPCommandString(path)); | |
328 return path; | |
329 } | |
330 | |
325 int FtpNetworkTransaction::DoLoop(int result) { | 331 int FtpNetworkTransaction::DoLoop(int result) { |
326 DCHECK(next_state_ != STATE_NONE); | 332 DCHECK(next_state_ != STATE_NONE); |
327 | 333 |
328 int rv = result; | 334 int rv = result; |
329 do { | 335 do { |
330 State state = next_state_; | 336 State state = next_state_; |
331 next_state_ = STATE_NONE; | 337 next_state_ = STATE_NONE; |
332 switch (state) { | 338 switch (state) { |
333 case STATE_CTRL_INIT: | 339 case STATE_CTRL_INIT: |
334 DCHECK(rv == OK); | 340 DCHECK(rv == OK); |
(...skipping 446 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
781 return Stop(ERR_FAILED); | 787 return Stop(ERR_FAILED); |
782 default: | 788 default: |
783 NOTREACHED(); | 789 NOTREACHED(); |
784 return Stop(ERR_UNEXPECTED); | 790 return Stop(ERR_UNEXPECTED); |
785 } | 791 } |
786 return OK; | 792 return OK; |
787 } | 793 } |
788 | 794 |
789 // SIZE command | 795 // SIZE command |
790 int FtpNetworkTransaction::DoCtrlWriteSIZE() { | 796 int FtpNetworkTransaction::DoCtrlWriteSIZE() { |
791 std::string command = "SIZE"; | 797 std::string command = "SIZE " + GetRequestPathForFtpCommand(); |
792 if (request_->url.has_path()) { | |
793 command.append(" "); | |
794 command.append(request_->url.path()); | |
795 } | |
796 next_state_ = STATE_CTRL_READ; | 798 next_state_ = STATE_CTRL_READ; |
797 return SendFtpCommand(command, COMMAND_SIZE); | 799 return SendFtpCommand(command, COMMAND_SIZE); |
798 } | 800 } |
799 | 801 |
800 int FtpNetworkTransaction::ProcessResponseSIZE( | 802 int FtpNetworkTransaction::ProcessResponseSIZE( |
801 const FtpCtrlResponse& response) { | 803 const FtpCtrlResponse& response) { |
802 switch (GetErrorClass(response.status_code)) { | 804 switch (GetErrorClass(response.status_code)) { |
803 case ERROR_CLASS_INITIATED: | 805 case ERROR_CLASS_INITIATED: |
804 break; | 806 break; |
805 case ERROR_CLASS_OK: | 807 case ERROR_CLASS_OK: |
(...skipping 13 matching lines...) Expand all Loading... | |
819 default: | 821 default: |
820 NOTREACHED(); | 822 NOTREACHED(); |
821 return Stop(ERR_UNEXPECTED); | 823 return Stop(ERR_UNEXPECTED); |
822 } | 824 } |
823 next_state_ = STATE_CTRL_WRITE_MDTM; | 825 next_state_ = STATE_CTRL_WRITE_MDTM; |
824 return OK; | 826 return OK; |
825 } | 827 } |
826 | 828 |
827 // RETR command | 829 // RETR command |
828 int FtpNetworkTransaction::DoCtrlWriteRETR() { | 830 int FtpNetworkTransaction::DoCtrlWriteRETR() { |
829 std::string command = "RETR"; | 831 std::string command = "RETR " + GetRequestPathForFtpCommand(); |
830 if (request_->url.has_path()) { | |
831 command.append(" "); | |
832 command.append(request_->url.path()); | |
833 } else { | |
834 command.append(" /"); | |
835 } | |
836 next_state_ = STATE_CTRL_READ; | 832 next_state_ = STATE_CTRL_READ; |
837 return SendFtpCommand(command, COMMAND_RETR); | 833 return SendFtpCommand(command, COMMAND_RETR); |
838 } | 834 } |
839 | 835 |
840 int FtpNetworkTransaction::ProcessResponseRETR( | 836 int FtpNetworkTransaction::ProcessResponseRETR( |
841 const FtpCtrlResponse& response) { | 837 const FtpCtrlResponse& response) { |
842 switch (GetErrorClass(response.status_code)) { | 838 switch (GetErrorClass(response.status_code)) { |
843 case ERROR_CLASS_INITIATED: | 839 case ERROR_CLASS_INITIATED: |
844 // We want the client to start reading the response at this point. | 840 // We want the client to start reading the response at this point. |
845 // It got here either through Start or RestartWithAuth. We want that | 841 // It got here either through Start or RestartWithAuth. We want that |
(...skipping 26 matching lines...) Expand all Loading... | |
872 break; | 868 break; |
873 default: | 869 default: |
874 NOTREACHED(); | 870 NOTREACHED(); |
875 return Stop(ERR_UNEXPECTED); | 871 return Stop(ERR_UNEXPECTED); |
876 } | 872 } |
877 return OK; | 873 return OK; |
878 } | 874 } |
879 | 875 |
880 // MDMT command | 876 // MDMT command |
881 int FtpNetworkTransaction::DoCtrlWriteMDTM() { | 877 int FtpNetworkTransaction::DoCtrlWriteMDTM() { |
882 std::string command = "MDTM"; | 878 std::string command = "MDTM " + GetRequestPathForFtpCommand(); |
883 if (request_->url.has_path()) { | |
884 command.append(" "); | |
885 command.append(request_->url.path()); | |
886 } else { | |
887 command.append(" /"); | |
888 } | |
889 next_state_ = STATE_CTRL_READ; | 879 next_state_ = STATE_CTRL_READ; |
890 return SendFtpCommand(command, COMMAND_MDTM); | 880 return SendFtpCommand(command, COMMAND_MDTM); |
891 } | 881 } |
892 | 882 |
893 int FtpNetworkTransaction::ProcessResponseMDTM( | 883 int FtpNetworkTransaction::ProcessResponseMDTM( |
894 const FtpCtrlResponse& response) { | 884 const FtpCtrlResponse& response) { |
895 switch (GetErrorClass(response.status_code)) { | 885 switch (GetErrorClass(response.status_code)) { |
896 case ERROR_CLASS_INITIATED: | 886 case ERROR_CLASS_INITIATED: |
897 return Stop(ERR_FAILED); | 887 return Stop(ERR_FAILED); |
898 case ERROR_CLASS_OK: | 888 case ERROR_CLASS_OK: |
899 next_state_ = STATE_CTRL_WRITE_RETR; | 889 next_state_ = STATE_CTRL_WRITE_RETR; |
900 break; | 890 break; |
901 case ERROR_CLASS_INFO_NEEDED: | 891 case ERROR_CLASS_INFO_NEEDED: |
902 return Stop(ERR_FAILED); | 892 return Stop(ERR_FAILED); |
903 case ERROR_CLASS_TRANSIENT_ERROR: | 893 case ERROR_CLASS_TRANSIENT_ERROR: |
904 return Stop(ERR_FAILED); | 894 return Stop(ERR_FAILED); |
905 case ERROR_CLASS_PERMANENT_ERROR: | 895 case ERROR_CLASS_PERMANENT_ERROR: |
906 next_state_ = STATE_CTRL_WRITE_RETR; | 896 next_state_ = STATE_CTRL_WRITE_RETR; |
907 break; | 897 break; |
908 default: | 898 default: |
909 NOTREACHED(); | 899 NOTREACHED(); |
910 return Stop(ERR_UNEXPECTED); | 900 return Stop(ERR_UNEXPECTED); |
911 } | 901 } |
912 return OK; | 902 return OK; |
913 } | 903 } |
914 | 904 |
915 | 905 |
916 // CWD command | 906 // CWD command |
917 int FtpNetworkTransaction::DoCtrlWriteCWD() { | 907 int FtpNetworkTransaction::DoCtrlWriteCWD() { |
918 std::string command = "CWD"; | 908 std::string command = "CWD " + GetRequestPathForFtpCommand(); |
919 if (request_->url.has_path()) { | |
920 command.append(" "); | |
921 command.append(request_->url.path()); | |
922 } else { | |
923 command.append(" /"); | |
924 } | |
925 next_state_ = STATE_CTRL_READ; | 909 next_state_ = STATE_CTRL_READ; |
926 return SendFtpCommand(command, COMMAND_CWD); | 910 return SendFtpCommand(command, COMMAND_CWD); |
927 } | 911 } |
928 | 912 |
929 int FtpNetworkTransaction::ProcessResponseCWD(const FtpCtrlResponse& response) { | 913 int FtpNetworkTransaction::ProcessResponseCWD(const FtpCtrlResponse& response) { |
930 switch (GetErrorClass(response.status_code)) { | 914 switch (GetErrorClass(response.status_code)) { |
931 case ERROR_CLASS_INITIATED: | 915 case ERROR_CLASS_INITIATED: |
932 return Stop(ERR_INVALID_RESPONSE); | 916 return Stop(ERR_INVALID_RESPONSE); |
933 case ERROR_CLASS_OK: | 917 case ERROR_CLASS_OK: |
934 next_state_ = STATE_CTRL_WRITE_LIST; | 918 next_state_ = STATE_CTRL_WRITE_LIST; |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1038 read_data_buf_->data()[0] = 0; | 1022 read_data_buf_->data()[0] = 0; |
1039 return data_socket_->Read(read_data_buf_, read_data_buf_len_, | 1023 return data_socket_->Read(read_data_buf_, read_data_buf_len_, |
1040 &io_callback_); | 1024 &io_callback_); |
1041 } | 1025 } |
1042 | 1026 |
1043 int FtpNetworkTransaction::DoDataReadComplete(int result) { | 1027 int FtpNetworkTransaction::DoDataReadComplete(int result) { |
1044 return result; | 1028 return result; |
1045 } | 1029 } |
1046 | 1030 |
1047 } // namespace net | 1031 } // namespace net |
OLD | NEW |