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
pull/1/head
Tatsuhiro Tsujikawa 2010-07-09 11:48:59 +00:00
parent be423e2c77
commit f285f66ac8
7 changed files with 47 additions and 52 deletions

View File

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

View File

@ -142,22 +142,11 @@ bool FtpConnection::sendPwd()
return socketBuffer_.sendBufferIsEmpty(); return socketBuffer_.sendBufferIsEmpty();
} }
bool FtpConnection::sendCwd() bool FtpConnection::sendCwd(const std::string& dir)
{ {
if(socketBuffer_.sendBufferIsEmpty()) { 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 "; std::string request = "CWD ";
if(util::startsWith(util::toUpper(req_->getDir()), "/%2F")) { request += util::percentDecode(dir);
request += util::percentDecode(req_->getDir().substr(1));
} else {
if(baseWorkingDir_ != "/") {
request += baseWorkingDir_;
}
request += util::percentDecode(req_->getDir());
}
request += "\r\n"; request += "\r\n";
if(logger_->info()) { if(logger_->info()) {
logger_->info(MSG_SENDING_REQUEST, logger_->info(MSG_SENDING_REQUEST,

View File

@ -92,7 +92,7 @@ public:
bool sendPass(); bool sendPass();
bool sendType(); bool sendType();
bool sendPwd(); bool sendPwd();
bool sendCwd(); bool sendCwd(const std::string& dir);
bool sendMdtm(); bool sendMdtm();
bool sendSize(); bool sendSize();
bool sendPasv(); bool sendPasv();

View File

@ -130,7 +130,7 @@ Command* FtpInitiateConnectionCommand::createNextCommand
new FtpNegotiationCommand(getCuid(), getRequest(), getFileEntry(), new FtpNegotiationCommand(getCuid(), getRequest(), getFileEntry(),
getRequestGroup(), getDownloadEngine(), getRequestGroup(), getDownloadEngine(),
pooledSocket, pooledSocket,
FtpNegotiationCommand::SEQ_SEND_CWD, FtpNegotiationCommand::SEQ_SEND_CWD_PREP,
options["baseWorkingDir"]); options["baseWorkingDir"]);
} else if(proxyMethod == V_GET) { } else if(proxyMethod == V_GET) {
// Use GET for FTP via HTTP proxy. // Use GET for FTP via HTTP proxy.
@ -175,7 +175,7 @@ Command* FtpInitiateConnectionCommand::createNextCommand
new FtpNegotiationCommand(getCuid(), getRequest(), getFileEntry(), new FtpNegotiationCommand(getCuid(), getRequest(), getFileEntry(),
getRequestGroup(), getDownloadEngine(), getRequestGroup(), getDownloadEngine(),
pooledSocket, pooledSocket,
FtpNegotiationCommand::SEQ_SEND_CWD, FtpNegotiationCommand::SEQ_SEND_CWD_PREP,
options["baseWorkingDir"]); options["baseWorkingDir"]);
} }
} }

View File

@ -259,14 +259,24 @@ bool FtpNegotiationCommand::recvPwd()
getLogger()->info("CUID#%s - base working directory is '%s'", getLogger()->info("CUID#%s - base working directory is '%s'",
util::itos(getCuid()).c_str(), pwd.c_str()); 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; sequence_ = SEQ_SEND_CWD;
return true; return true;
} }
bool FtpNegotiationCommand::sendCwd() { bool FtpNegotiationCommand::sendCwd()
// Calling setReadCheckSocket() is needed when the socket is reused, {
setReadCheckSocket(getSocket()); if(ftp_->sendCwd(cwdDirs_.front())) {
if(ftp_->sendCwd()) {
disableWriteCheckSocket(); disableWriteCheckSocket();
sequence_ = SEQ_RECV_CWD; sequence_ = SEQ_RECV_CWD;
} else { } else {
@ -275,7 +285,8 @@ bool FtpNegotiationCommand::sendCwd() {
return false; return false;
} }
bool FtpNegotiationCommand::recvCwd() { bool FtpNegotiationCommand::recvCwd()
{
unsigned int status = ftp_->receiveResponse(); unsigned int status = ftp_->receiveResponse();
if(status == 0) { if(status == 0) {
return false; return false;
@ -289,10 +300,15 @@ bool FtpNegotiationCommand::recvCwd() {
else else
throw DL_ABORT_EX(StringFormat(EX_BAD_STATUS, status).str()); throw DL_ABORT_EX(StringFormat(EX_BAD_STATUS, status).str());
} }
if(getOption()->getAsBool(PREF_REMOTE_TIME)) { cwdDirs_.pop_front();
sequence_ = SEQ_SEND_MDTM; if(cwdDirs_.empty()) {
if(getOption()->getAsBool(PREF_REMOTE_TIME)) {
sequence_ = SEQ_SEND_MDTM;
} else {
sequence_ = SEQ_SEND_SIZE;
}
} else { } else {
sequence_ = SEQ_SEND_SIZE; sequence_ = SEQ_SEND_CWD;
} }
return true; return true;
} }
@ -773,6 +789,8 @@ bool FtpNegotiationCommand::processSequence
return sendPwd(); return sendPwd();
case SEQ_RECV_PWD: case SEQ_RECV_PWD:
return recvPwd(); return recvPwd();
case SEQ_SEND_CWD_PREP:
return sendCwdPrep();
case SEQ_SEND_CWD: case SEQ_SEND_CWD:
return sendCwd(); return sendCwd();
case SEQ_RECV_CWD: case SEQ_RECV_CWD:

View File

@ -55,6 +55,7 @@ public:
SEQ_RECV_TYPE, SEQ_RECV_TYPE,
SEQ_SEND_PWD, SEQ_SEND_PWD,
SEQ_RECV_PWD, SEQ_RECV_PWD,
SEQ_SEND_CWD_PREP,
SEQ_SEND_CWD, SEQ_SEND_CWD,
SEQ_RECV_CWD, SEQ_RECV_CWD,
SEQ_SEND_MDTM, SEQ_SEND_MDTM,
@ -92,6 +93,7 @@ private:
bool recvType(); bool recvType();
bool sendPwd(); bool sendPwd();
bool recvPwd(); bool recvPwd();
bool sendCwdPrep();
bool sendCwd(); bool sendCwd();
bool recvCwd(); bool recvCwd();
bool sendMdtm(); bool sendMdtm();
@ -136,6 +138,8 @@ private:
std::string connectedHostname_; std::string connectedHostname_;
std::string connectedAddr_; std::string connectedAddr_;
uint16_t connectedPort_; uint16_t connectedPort_;
std::deque<std::string> cwdDirs_;
protected: protected:
virtual bool executeInternal(); virtual bool executeInternal();
public: public:

View File

@ -29,8 +29,6 @@ class FtpConnectionTest:public CppUnit::TestFixture {
CPPUNIT_TEST(testReceivePwdResponse_unquotedResponse); CPPUNIT_TEST(testReceivePwdResponse_unquotedResponse);
CPPUNIT_TEST(testReceivePwdResponse_badStatus); CPPUNIT_TEST(testReceivePwdResponse_badStatus);
CPPUNIT_TEST(testSendCwd); CPPUNIT_TEST(testSendCwd);
CPPUNIT_TEST(testSendCwd_baseWorkingDir);
CPPUNIT_TEST(testSendCwd_absDir);
CPPUNIT_TEST(testSendSize); CPPUNIT_TEST(testSendSize);
CPPUNIT_TEST(testReceiveSizeResponse); CPPUNIT_TEST(testReceiveSizeResponse);
CPPUNIT_TEST(testSendRetr); CPPUNIT_TEST(testSendRetr);
@ -84,8 +82,6 @@ public:
void testReceivePwdResponse_unquotedResponse(); void testReceivePwdResponse_unquotedResponse();
void testReceivePwdResponse_badStatus(); void testReceivePwdResponse_badStatus();
void testSendCwd(); void testSendCwd();
void testSendCwd_baseWorkingDir();
void testSendCwd_absDir();
void testSendSize(); void testSendSize();
void testReceiveSizeResponse(); void testReceiveSizeResponse();
void testSendRetr(); void testSendRetr();
@ -266,7 +262,7 @@ void FtpConnectionTest::testReceivePwdResponse_badStatus()
void FtpConnectionTest::testSendCwd() void FtpConnectionTest::testSendCwd()
{ {
ftp_->sendCwd(); ftp_->sendCwd("%2Fdir%20sp");
char data[32]; char data[32];
size_t len = sizeof(data); size_t len = sizeof(data);
serverSocket_->readData(data, len); serverSocket_->readData(data, len);
@ -274,29 +270,6 @@ void FtpConnectionTest::testSendCwd()
CPPUNIT_ASSERT_EQUAL(std::string("CWD /dir sp\r\n"), std::string(data)); 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() void FtpConnectionTest::testSendSize()
{ {
ftp_->sendSize(); ftp_->sendSize();