Sfoglia il codice sorgente

2010-07-09 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>

	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
Tatsuhiro Tsujikawa 15 anni fa
parent
commit
f285f66ac8

+ 11 - 0
ChangeLog

@@ -1,3 +1,14 @@
+2010-07-09  Tatsuhiro Tsujikawa  <t-tujikawa@users.sourceforge.net>
+
+	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  <t-tujikawa@users.sourceforge.net>
 
 	Documented that aria2 supports Chromium/Google Chrom cookies file.

+ 2 - 13
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,

+ 1 - 1
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();

+ 2 - 2
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"]);
     }
   }

+ 25 - 7
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;
+  sequence_ = SEQ_SEND_CWD_PREP;
   return true;
 }
 
-bool FtpNegotiationCommand::sendCwd() {
+bool FtpNegotiationCommand::sendCwdPrep()
+{
   // Calling setReadCheckSocket() is needed when the socket is reused, 
   setReadCheckSocket(getSocket());
-  if(ftp_->sendCwd()) {
+  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()
+{
+  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:

+ 4 - 0
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<std::string> cwdDirs_;
 protected:
   virtual bool executeInternal();
 public:

+ 1 - 28
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();