diff --git a/ChangeLog b/ChangeLog index e34b0499..f1c310d7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2010-07-09 Tatsuhiro Tsujikawa + + Send each CWD component of FTP URI in separate CWD command as + described in RFC1738. + * src/FtpConnection.cc + * src/FtpConnection.h + * src/FtpInitiateConnectionCommand.cc + * src/FtpNegotiationCommand.cc + * src/FtpNegotiationCommand.h + * test/FtpConnectionTest.cc + 2010-07-09 Tatsuhiro Tsujikawa Documented that aria2 supports Chromium/Google Chrom cookies file. diff --git a/src/FtpConnection.cc b/src/FtpConnection.cc index 0aaa9a4a..8a54f935 100644 --- a/src/FtpConnection.cc +++ b/src/FtpConnection.cc @@ -142,22 +142,11 @@ bool FtpConnection::sendPwd() return socketBuffer_.sendBufferIsEmpty(); } -bool FtpConnection::sendCwd() +bool FtpConnection::sendCwd(const std::string& dir) { if(socketBuffer_.sendBufferIsEmpty()) { - if(logger_->info()) { - logger_->info("CUID#%s - Using base working directory '%s'", - util::itos(cuid_).c_str(), baseWorkingDir_.c_str()); - } std::string request = "CWD "; - if(util::startsWith(util::toUpper(req_->getDir()), "/%2F")) { - request += util::percentDecode(req_->getDir().substr(1)); - } else { - if(baseWorkingDir_ != "/") { - request += baseWorkingDir_; - } - request += util::percentDecode(req_->getDir()); - } + request += util::percentDecode(dir); request += "\r\n"; if(logger_->info()) { logger_->info(MSG_SENDING_REQUEST, diff --git a/src/FtpConnection.h b/src/FtpConnection.h index b973c597..891b6feb 100644 --- a/src/FtpConnection.h +++ b/src/FtpConnection.h @@ -92,7 +92,7 @@ public: bool sendPass(); bool sendType(); bool sendPwd(); - bool sendCwd(); + bool sendCwd(const std::string& dir); bool sendMdtm(); bool sendSize(); bool sendPasv(); diff --git a/src/FtpInitiateConnectionCommand.cc b/src/FtpInitiateConnectionCommand.cc index 8a1d5b44..9833a5f8 100644 --- a/src/FtpInitiateConnectionCommand.cc +++ b/src/FtpInitiateConnectionCommand.cc @@ -130,7 +130,7 @@ Command* FtpInitiateConnectionCommand::createNextCommand new FtpNegotiationCommand(getCuid(), getRequest(), getFileEntry(), getRequestGroup(), getDownloadEngine(), pooledSocket, - FtpNegotiationCommand::SEQ_SEND_CWD, + FtpNegotiationCommand::SEQ_SEND_CWD_PREP, options["baseWorkingDir"]); } else if(proxyMethod == V_GET) { // Use GET for FTP via HTTP proxy. @@ -175,7 +175,7 @@ Command* FtpInitiateConnectionCommand::createNextCommand new FtpNegotiationCommand(getCuid(), getRequest(), getFileEntry(), getRequestGroup(), getDownloadEngine(), pooledSocket, - FtpNegotiationCommand::SEQ_SEND_CWD, + FtpNegotiationCommand::SEQ_SEND_CWD_PREP, options["baseWorkingDir"]); } } diff --git a/src/FtpNegotiationCommand.cc b/src/FtpNegotiationCommand.cc index 1617ef36..558d4944 100644 --- a/src/FtpNegotiationCommand.cc +++ b/src/FtpNegotiationCommand.cc @@ -259,14 +259,24 @@ bool FtpNegotiationCommand::recvPwd() getLogger()->info("CUID#%s - base working directory is '%s'", util::itos(getCuid()).c_str(), pwd.c_str()); } + sequence_ = SEQ_SEND_CWD_PREP; + return true; +} + +bool FtpNegotiationCommand::sendCwdPrep() +{ + // Calling setReadCheckSocket() is needed when the socket is reused, + setReadCheckSocket(getSocket()); + util::split(getRequest()->getDir(), std::back_inserter(cwdDirs_), + A2STR::SLASH_C); + cwdDirs_.push_front(ftp_->getBaseWorkingDir()); sequence_ = SEQ_SEND_CWD; return true; } -bool FtpNegotiationCommand::sendCwd() { - // Calling setReadCheckSocket() is needed when the socket is reused, - setReadCheckSocket(getSocket()); - if(ftp_->sendCwd()) { +bool FtpNegotiationCommand::sendCwd() +{ + if(ftp_->sendCwd(cwdDirs_.front())) { disableWriteCheckSocket(); sequence_ = SEQ_RECV_CWD; } else { @@ -275,7 +285,8 @@ bool FtpNegotiationCommand::sendCwd() { return false; } -bool FtpNegotiationCommand::recvCwd() { +bool FtpNegotiationCommand::recvCwd() +{ unsigned int status = ftp_->receiveResponse(); if(status == 0) { return false; @@ -289,10 +300,15 @@ bool FtpNegotiationCommand::recvCwd() { else throw DL_ABORT_EX(StringFormat(EX_BAD_STATUS, status).str()); } - if(getOption()->getAsBool(PREF_REMOTE_TIME)) { - sequence_ = SEQ_SEND_MDTM; + cwdDirs_.pop_front(); + if(cwdDirs_.empty()) { + if(getOption()->getAsBool(PREF_REMOTE_TIME)) { + sequence_ = SEQ_SEND_MDTM; + } else { + sequence_ = SEQ_SEND_SIZE; + } } else { - sequence_ = SEQ_SEND_SIZE; + sequence_ = SEQ_SEND_CWD; } return true; } @@ -773,6 +789,8 @@ bool FtpNegotiationCommand::processSequence return sendPwd(); case SEQ_RECV_PWD: return recvPwd(); + case SEQ_SEND_CWD_PREP: + return sendCwdPrep(); case SEQ_SEND_CWD: return sendCwd(); case SEQ_RECV_CWD: diff --git a/src/FtpNegotiationCommand.h b/src/FtpNegotiationCommand.h index afbbd061..badd14a3 100644 --- a/src/FtpNegotiationCommand.h +++ b/src/FtpNegotiationCommand.h @@ -55,6 +55,7 @@ public: SEQ_RECV_TYPE, SEQ_SEND_PWD, SEQ_RECV_PWD, + SEQ_SEND_CWD_PREP, SEQ_SEND_CWD, SEQ_RECV_CWD, SEQ_SEND_MDTM, @@ -92,6 +93,7 @@ private: bool recvType(); bool sendPwd(); bool recvPwd(); + bool sendCwdPrep(); bool sendCwd(); bool recvCwd(); bool sendMdtm(); @@ -136,6 +138,8 @@ private: std::string connectedHostname_; std::string connectedAddr_; uint16_t connectedPort_; + + std::deque cwdDirs_; protected: virtual bool executeInternal(); public: diff --git a/test/FtpConnectionTest.cc b/test/FtpConnectionTest.cc index f175f091..8390c461 100644 --- a/test/FtpConnectionTest.cc +++ b/test/FtpConnectionTest.cc @@ -29,8 +29,6 @@ class FtpConnectionTest:public CppUnit::TestFixture { CPPUNIT_TEST(testReceivePwdResponse_unquotedResponse); CPPUNIT_TEST(testReceivePwdResponse_badStatus); CPPUNIT_TEST(testSendCwd); - CPPUNIT_TEST(testSendCwd_baseWorkingDir); - CPPUNIT_TEST(testSendCwd_absDir); CPPUNIT_TEST(testSendSize); CPPUNIT_TEST(testReceiveSizeResponse); CPPUNIT_TEST(testSendRetr); @@ -84,8 +82,6 @@ public: void testReceivePwdResponse_unquotedResponse(); void testReceivePwdResponse_badStatus(); void testSendCwd(); - void testSendCwd_baseWorkingDir(); - void testSendCwd_absDir(); void testSendSize(); void testReceiveSizeResponse(); void testSendRetr(); @@ -266,7 +262,7 @@ void FtpConnectionTest::testReceivePwdResponse_badStatus() void FtpConnectionTest::testSendCwd() { - ftp_->sendCwd(); + ftp_->sendCwd("%2Fdir%20sp"); char data[32]; size_t len = sizeof(data); serverSocket_->readData(data, len); @@ -274,29 +270,6 @@ void FtpConnectionTest::testSendCwd() CPPUNIT_ASSERT_EQUAL(std::string("CWD /dir sp\r\n"), std::string(data)); } -void FtpConnectionTest::testSendCwd_baseWorkingDir() -{ - ftp_->setBaseWorkingDir("/base"); - ftp_->sendCwd(); - char data[32]; - size_t len = sizeof(data); - serverSocket_->readData(data, len); - data[len] = '\0'; - CPPUNIT_ASSERT_EQUAL(std::string("CWD /base/dir sp\r\n"), std::string(data)); -} - -void FtpConnectionTest::testSendCwd_absDir() -{ - req_->setUri("http://localhost/%2fdir/file"); - ftp_->setBaseWorkingDir("/base"); - ftp_->sendCwd(); - char data[32]; - size_t len = sizeof(data); - serverSocket_->readData(data, len); - data[len] = '\0'; - CPPUNIT_ASSERT_EQUAL(std::string("CWD /dir\r\n"), std::string(data)); -} - void FtpConnectionTest::testSendSize() { ftp_->sendSize();