summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorphajdan.jr@chromium.org <phajdan.jr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-12-22 11:59:21 +0000
committerphajdan.jr@chromium.org <phajdan.jr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-12-22 11:59:21 +0000
commit250e5243ce41f9025442773a038670fc24a4622c (patch)
tree01c5efb2babc434368a9adc288bdc797706d6722 /net
parent2c8d596cbd1f91a7d6134c7c5b33a188af51d0bc (diff)
downloadchromium_src-250e5243ce41f9025442773a038670fc24a4622c.zip
chromium_src-250e5243ce41f9025442773a038670fc24a4622c.tar.gz
chromium_src-250e5243ce41f9025442773a038670fc24a4622c.tar.bz2
Implement support for MLSD FTP command in FtpNetworkTransaction.
This way we can request the better-parseable MLSD listing, and in case it doesn't work fall back to LIST command. TEST=Covered by net_unittests. BUG=29691 Review URL: http://codereview.chromium.org/500134 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@35141 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r--net/ftp/ftp_network_transaction.cc45
-rw-r--r--net/ftp/ftp_network_transaction.h4
-rw-r--r--net/ftp/ftp_network_transaction_unittest.cc28
3 files changed, 71 insertions, 6 deletions
diff --git a/net/ftp/ftp_network_transaction.cc b/net/ftp/ftp_network_transaction.cc
index 8014d07..44f1aa1 100644
--- a/net/ftp/ftp_network_transaction.cc
+++ b/net/ftp/ftp_network_transaction.cc
@@ -259,6 +259,9 @@ int FtpNetworkTransaction::ProcessCtrlResponse() {
case COMMAND_CWD:
rv = ProcessResponseCWD(response);
break;
+ case COMMAND_MLSD:
+ rv = ProcessResponseMLSD(response);
+ break;
case COMMAND_LIST:
rv = ProcessResponseLIST(response);
break;
@@ -282,6 +285,9 @@ int FtpNetworkTransaction::ProcessCtrlResponse() {
case COMMAND_RETR:
rv = ProcessResponseRETR(response);
break;
+ case COMMAND_MLSD:
+ rv = ProcessResponseMLSD(response);
+ break;
case COMMAND_LIST:
rv = ProcessResponseLIST(response);
break;
@@ -438,6 +444,10 @@ int FtpNetworkTransaction::DoLoop(int result) {
DCHECK(rv == OK);
rv = DoCtrlWriteCWD();
break;
+ case STATE_CTRL_WRITE_MLSD:
+ DCHECK(rv == 0);
+ rv = DoCtrlWriteMLSD();
+ break;
case STATE_CTRL_WRITE_LIST:
DCHECK(rv == OK);
rv = DoCtrlWriteLIST();
@@ -989,7 +999,7 @@ int FtpNetworkTransaction::ProcessResponseCWD(const FtpCtrlResponse& response) {
case ERROR_CLASS_INITIATED:
return Stop(ERR_INVALID_RESPONSE);
case ERROR_CLASS_OK:
- next_state_ = STATE_CTRL_WRITE_LIST;
+ next_state_ = STATE_CTRL_WRITE_MLSD;
break;
case ERROR_CLASS_INFO_NEEDED:
return Stop(ERR_INVALID_RESPONSE);
@@ -1011,6 +1021,38 @@ int FtpNetworkTransaction::ProcessResponseCWD(const FtpCtrlResponse& response) {
return OK;
}
+// MLSD command
+int FtpNetworkTransaction::DoCtrlWriteMLSD() {
+ next_state_ = STATE_CTRL_READ;
+ return SendFtpCommand("MLSD", COMMAND_MLSD);
+}
+
+int FtpNetworkTransaction::ProcessResponseMLSD(
+ const FtpCtrlResponse& response) {
+ switch (GetErrorClass(response.status_code)) {
+ case ERROR_CLASS_INITIATED:
+ response_.is_directory_listing = true;
+ next_state_ = STATE_CTRL_READ;
+ break;
+ case ERROR_CLASS_OK:
+ response_.is_directory_listing = true;
+ next_state_ = STATE_CTRL_WRITE_QUIT;
+ break;
+ case ERROR_CLASS_INFO_NEEDED:
+ return Stop(ERR_INVALID_RESPONSE);
+ case ERROR_CLASS_TRANSIENT_ERROR:
+ case ERROR_CLASS_PERMANENT_ERROR:
+ // Fallback to the LIST command, more widely supported,
+ // but without a specified output format.
+ next_state_ = STATE_CTRL_WRITE_LIST;
+ break;
+ default:
+ NOTREACHED();
+ return Stop(ERR_UNEXPECTED);
+ }
+ return OK;
+}
+
// LIST command
int FtpNetworkTransaction::DoCtrlWriteLIST() {
std::string command(system_type_ == SYSTEM_TYPE_VMS ? "LIST *.*;0" : "LIST");
@@ -1023,6 +1065,7 @@ int FtpNetworkTransaction::ProcessResponseLIST(
switch (GetErrorClass(response.status_code)) {
case ERROR_CLASS_INITIATED:
response_.is_directory_listing = true;
+ next_state_ = STATE_CTRL_READ;
break;
case ERROR_CLASS_OK:
response_.is_directory_listing = true;
diff --git a/net/ftp/ftp_network_transaction.h b/net/ftp/ftp_network_transaction.h
index 8a11947..e8140f4 100644
--- a/net/ftp/ftp_network_transaction.h
+++ b/net/ftp/ftp_network_transaction.h
@@ -57,6 +57,7 @@ class FtpNetworkTransaction : public FtpTransaction {
COMMAND_SIZE,
COMMAND_RETR,
COMMAND_CWD,
+ COMMAND_MLSD,
COMMAND_LIST,
COMMAND_MDTM,
COMMAND_QUIT
@@ -151,6 +152,8 @@ class FtpNetworkTransaction : public FtpTransaction {
int ProcessResponseSIZE(const FtpCtrlResponse& response);
int DoCtrlWriteCWD();
int ProcessResponseCWD(const FtpCtrlResponse& response);
+ int DoCtrlWriteMLSD();
+ int ProcessResponseMLSD(const FtpCtrlResponse& response);
int DoCtrlWriteLIST();
int ProcessResponseLIST(const FtpCtrlResponse& response);
int DoCtrlWriteMDTM();
@@ -240,6 +243,7 @@ class FtpNetworkTransaction : public FtpTransaction {
STATE_CTRL_WRITE_RETR,
STATE_CTRL_WRITE_SIZE,
STATE_CTRL_WRITE_CWD,
+ STATE_CTRL_WRITE_MLSD,
STATE_CTRL_WRITE_LIST,
STATE_CTRL_WRITE_MDTM,
STATE_CTRL_WRITE_QUIT,
diff --git a/net/ftp/ftp_network_transaction_unittest.cc b/net/ftp/ftp_network_transaction_unittest.cc
index d20818a..d8479aa5 100644
--- a/net/ftp/ftp_network_transaction_unittest.cc
+++ b/net/ftp/ftp_network_transaction_unittest.cc
@@ -39,6 +39,7 @@ class FtpSocketDataProvider : public DynamicSocketDataProvider {
PRE_PASV,
PRE_SIZE,
PRE_MDTM,
+ PRE_MLSD,
PRE_LIST,
PRE_RETR,
PRE_PASV2,
@@ -174,9 +175,12 @@ class FtpSocketDataProviderDirectoryListing : public FtpSocketDataProvider {
"550 Can't download directory\r\n");
case PRE_CWD:
- return Verify("CWD /\r\n", data, PRE_LIST, "200 OK\r\n");
+ return Verify("CWD /\r\n", data, PRE_MLSD, "200 OK\r\n");
+ case PRE_MLSD:
+ return Verify("MLSD\r\n", data, PRE_QUIT,
+ "150 Accepted data connection\r\n"
+ "226 MLSD complete\r\n");
case PRE_LIST:
- // TODO(phajdan.jr): Also test with "150 Accepted Data Connection".
return Verify("LIST\r\n", data, PRE_QUIT, "200 OK\r\n");
default:
return FtpSocketDataProvider::OnWrite(data);
@@ -211,8 +215,10 @@ class FtpSocketDataProviderVMSDirectoryListing : public FtpSocketDataProvider {
return Verify("RETR ANONYMOUS_ROOT:[000000]dir\r\n", data, PRE_PASV2,
"550 Can't download directory\r\n");
case PRE_CWD:
- return Verify("CWD ANONYMOUS_ROOT:[dir]\r\n", data, PRE_LIST,
+ return Verify("CWD ANONYMOUS_ROOT:[dir]\r\n", data, PRE_MLSD,
"200 OK\r\n");
+ case PRE_MLSD:
+ return Verify("MLSD\r\n", data, PRE_LIST, "500 Invalid command\r\n");
case PRE_LIST:
return Verify("LIST *.*;0\r\n", data, PRE_QUIT, "200 OK\r\n");
default:
@@ -249,8 +255,10 @@ class FtpSocketDataProviderVMSDirectoryListingRootDirectory
return Verify("RETR ANONYMOUS_ROOT\r\n", data, PRE_PASV2,
"550 Can't download directory\r\n");
case PRE_CWD:
- return Verify("CWD ANONYMOUS_ROOT:[000000]\r\n", data, PRE_LIST,
+ return Verify("CWD ANONYMOUS_ROOT:[000000]\r\n", data, PRE_MLSD,
"200 OK\r\n");
+ case PRE_MLSD:
+ return Verify("MLSD\r\n", data, PRE_LIST, "500 Invalid command\r\n");
case PRE_LIST:
return Verify("LIST *.*;0\r\n", data, PRE_QUIT, "200 OK\r\n");
default:
@@ -1010,10 +1018,20 @@ TEST_F(FtpNetworkTransactionTest, DirectoryTransactionFileNotFound) {
ERR_FILE_NOT_FOUND);
}
-TEST_F(FtpNetworkTransactionTest, DirectoryTransactionFailList) {
+TEST_F(FtpNetworkTransactionTest, DirectoryTransactionFailMlsd) {
FtpSocketDataProviderDirectoryListing ctrl_socket;
TransactionFailHelper(&ctrl_socket,
"ftp://host",
+ FtpSocketDataProvider::PRE_MLSD,
+ FtpSocketDataProvider::PRE_LIST,
+ "500 Unrecognized command\r\n",
+ OK);
+}
+
+TEST_F(FtpNetworkTransactionTest, DirectoryTransactionFailList) {
+ FtpSocketDataProviderVMSDirectoryListing ctrl_socket;
+ TransactionFailHelper(&ctrl_socket,
+ "ftp://host/dir",
FtpSocketDataProvider::PRE_LIST,
FtpSocketDataProvider::PRE_QUIT,
"500 failed list\r\n",