Skip to content

Commit

Permalink
Implement support for MLSD FTP command in FtpNetworkTransaction.
Browse files Browse the repository at this point in the history
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
  • Loading branch information
phajdan.jr@chromium.org committed Dec 22, 2009
1 parent 2c8d596 commit 250e524
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 6 deletions.
45 changes: 44 additions & 1 deletion net/ftp/ftp_network_transaction.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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);
Expand All @@ -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");
Expand All @@ -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;
Expand Down
4 changes: 4 additions & 0 deletions net/ftp/ftp_network_transaction.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ class FtpNetworkTransaction : public FtpTransaction {
COMMAND_SIZE,
COMMAND_RETR,
COMMAND_CWD,
COMMAND_MLSD,
COMMAND_LIST,
COMMAND_MDTM,
COMMAND_QUIT
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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,
Expand Down
28 changes: 23 additions & 5 deletions net/ftp/ftp_network_transaction_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class FtpSocketDataProvider : public DynamicSocketDataProvider {
PRE_PASV,
PRE_SIZE,
PRE_MDTM,
PRE_MLSD,
PRE_LIST,
PRE_RETR,
PRE_PASV2,
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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",
Expand Down

0 comments on commit 250e524

Please sign in to comment.