mirror of
https://github.com/aria2/aria2.git
synced 2024-12-14 01:18:40 +00:00
2008-09-08 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
Implemented the ability to get timestamp from remote FTP server using MDTM command described in RFC3659. * src/FtpConnection.cc * src/FtpConnection.h * src/FtpNegotiationCommand.cc * src/FtpNegotiationCommand.h * test/FtpConnectionTest.cc * test/Makefile.am
This commit is contained in:
parent
dbc8f5b737
commit
eb652b570e
11
ChangeLog
11
ChangeLog
@ -1,3 +1,14 @@
|
||||
2008-09-08 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
|
||||
|
||||
Implemented the ability to get timestamp from remote FTP server using
|
||||
MDTM command described in RFC3659.
|
||||
* src/FtpConnection.cc
|
||||
* src/FtpConnection.h
|
||||
* src/FtpNegotiationCommand.cc
|
||||
* src/FtpNegotiationCommand.h
|
||||
* test/FtpConnectionTest.cc
|
||||
* test/Makefile.am
|
||||
|
||||
2008-09-07 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
|
||||
|
||||
Implemented the ability to get timestamp from remote HTTP server and
|
||||
|
@ -47,6 +47,7 @@
|
||||
#include "DlAbortEx.h"
|
||||
#include "Socket.h"
|
||||
#include "A2STR.h"
|
||||
#include <cstring>
|
||||
|
||||
namespace aria2 {
|
||||
|
||||
@ -95,6 +96,13 @@ void FtpConnection::sendCwd() const
|
||||
socket->writeData(request);
|
||||
}
|
||||
|
||||
void FtpConnection::sendMdtm() const
|
||||
{
|
||||
std::string request = "MDTM "+Util::urlencode(req->getFile())+"\r\n";
|
||||
logger->info(MSG_SENDING_REQUEST, cuid, request.c_str());
|
||||
socket->writeData(request);
|
||||
}
|
||||
|
||||
void FtpConnection::sendSize() const
|
||||
{
|
||||
std::string request = "SIZE "+Util::urldecode(req->getFile())+"\r\n";
|
||||
@ -257,6 +265,26 @@ unsigned int FtpConnection::receiveSizeResponse(uint64_t& size)
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int FtpConnection::receiveMdtmResponse(Time& time)
|
||||
{
|
||||
// MDTM command, specified in RFC3659.
|
||||
std::pair<unsigned int, std::string> response;
|
||||
if(bulkReceiveResponse(response)) {
|
||||
if(response.first == 213) {
|
||||
char buf[15]; // YYYYMMDDhhmmss+\0, milli second part is dropped.
|
||||
sscanf(response.second.c_str(), "%*u %14s", buf);
|
||||
if(strlen(buf) == 14) {
|
||||
time = Time::parse(buf, "%Y%m%d%H%M%S");
|
||||
} else {
|
||||
time.setTimeInSec(-1);
|
||||
}
|
||||
}
|
||||
return response.first;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int FtpConnection::receivePasvResponse(std::pair<std::string, uint16_t>& dest)
|
||||
{
|
||||
std::pair<unsigned int, std::string> response;
|
||||
|
@ -37,6 +37,7 @@
|
||||
|
||||
#include "common.h"
|
||||
#include "SharedHandle.h"
|
||||
#include "TimeA2.h"
|
||||
#include <utility>
|
||||
#include <string>
|
||||
|
||||
@ -74,6 +75,7 @@ public:
|
||||
void sendPass() const;
|
||||
void sendType() const;
|
||||
void sendCwd() const;
|
||||
void sendMdtm() const;
|
||||
void sendSize() const;
|
||||
void sendPasv() const;
|
||||
SharedHandle<SocketCore> sendPort() const;
|
||||
@ -82,6 +84,13 @@ public:
|
||||
|
||||
unsigned int receiveResponse();
|
||||
unsigned int receiveSizeResponse(uint64_t& size);
|
||||
// Returns status code of MDTM reply. If the status code is 213, parses
|
||||
// time-val and store it in time.
|
||||
// If a code other than 213 is returned, time is not touched.
|
||||
// Expect MDTM reply is YYYYMMDDhhmmss in GMT. If status is 213 but returned
|
||||
// date cannot be parsed, then executes time.setTimeInSec(-1).
|
||||
// If reply is not received yet, returns 0.
|
||||
unsigned int receiveMdtmResponse(Time& time);
|
||||
unsigned int receivePasvResponse(std::pair<std::string, uint16_t>& dest);
|
||||
};
|
||||
|
||||
|
@ -202,10 +202,49 @@ bool FtpNegotiationCommand::recvCwd() {
|
||||
poolConnection();
|
||||
throw DlAbortEx(StringFormat(EX_BAD_STATUS, status).str());
|
||||
}
|
||||
sequence = SEQ_SEND_SIZE;
|
||||
if(e->option->getAsBool(PREF_REMOTE_TIME)) {
|
||||
sequence = SEQ_SEND_MDTM;
|
||||
} else {
|
||||
sequence = SEQ_SEND_SIZE;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FtpNegotiationCommand::sendMdtm()
|
||||
{
|
||||
ftp->sendMdtm();
|
||||
sequence = SEQ_RECV_MDTM;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FtpNegotiationCommand::recvMdtm()
|
||||
{
|
||||
Time lastModifiedTime(-1);
|
||||
unsigned int status = ftp->receiveMdtmResponse(lastModifiedTime);
|
||||
if(status == 0) {
|
||||
return false;
|
||||
}
|
||||
if(status == 213) {
|
||||
if(lastModifiedTime.good()) {
|
||||
_requestGroup->updateLastModifiedTime(lastModifiedTime);
|
||||
time_t t = lastModifiedTime.getTime();
|
||||
struct tm* tms = gmtime(&t); // returned struct is statically allocated.
|
||||
if(tms) {
|
||||
logger->debug("MDTM result was parsed as: %s GMT", asctime(tms));
|
||||
} else {
|
||||
logger->debug("gmtime() failed for MDTM result.");
|
||||
}
|
||||
} else {
|
||||
logger->debug("MDTM response was returned, but it seems not to be a time"
|
||||
" value as in specified in RFC3659.");
|
||||
}
|
||||
} else {
|
||||
logger->info("CUID#%d - MDTM command failed.", cuid);
|
||||
}
|
||||
sequence = SEQ_SEND_SIZE;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FtpNegotiationCommand::sendSize() {
|
||||
ftp->sendSize();
|
||||
sequence = SEQ_RECV_SIZE;
|
||||
@ -445,6 +484,10 @@ bool FtpNegotiationCommand::processSequence(const SegmentHandle& segment) {
|
||||
return sendCwd();
|
||||
case SEQ_RECV_CWD:
|
||||
return recvCwd();
|
||||
case SEQ_SEND_MDTM:
|
||||
return sendMdtm();
|
||||
case SEQ_RECV_MDTM:
|
||||
return recvMdtm();
|
||||
case SEQ_SEND_SIZE:
|
||||
return sendSize();
|
||||
case SEQ_RECV_SIZE:
|
||||
|
@ -54,6 +54,8 @@ public:
|
||||
SEQ_RECV_TYPE,
|
||||
SEQ_SEND_CWD,
|
||||
SEQ_RECV_CWD,
|
||||
SEQ_SEND_MDTM,
|
||||
SEQ_RECV_MDTM,
|
||||
SEQ_SEND_SIZE,
|
||||
SEQ_RECV_SIZE,
|
||||
SEQ_SEND_PORT,
|
||||
@ -82,6 +84,8 @@ private:
|
||||
bool recvType();
|
||||
bool sendCwd();
|
||||
bool recvCwd();
|
||||
bool sendMdtm();
|
||||
bool recvMdtm();
|
||||
bool sendSize();
|
||||
bool recvSize();
|
||||
bool sendPort();
|
||||
|
105
test/FtpConnectionTest.cc
Normal file
105
test/FtpConnectionTest.cc
Normal file
@ -0,0 +1,105 @@
|
||||
#include "FtpConnection.h"
|
||||
#include "Exception.h"
|
||||
#include "Util.h"
|
||||
#include "SocketCore.h"
|
||||
#include "Request.h"
|
||||
#include "Option.h"
|
||||
#include <iostream>
|
||||
#include <cppunit/extensions/HelperMacros.h>
|
||||
|
||||
namespace aria2 {
|
||||
|
||||
class FtpConnectionTest:public CppUnit::TestFixture {
|
||||
|
||||
CPPUNIT_TEST_SUITE(FtpConnectionTest);
|
||||
CPPUNIT_TEST(testSendMdtm);
|
||||
CPPUNIT_TEST(testReceiveMdtmResponse);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
private:
|
||||
SharedHandle<SocketCore> _serverSocket;
|
||||
uint16_t _listenPort;
|
||||
SharedHandle<FtpConnection> _ftp;
|
||||
Option _option;
|
||||
public:
|
||||
void setUp()
|
||||
{
|
||||
//_ftpServerSocket.reset(new SocketCore());
|
||||
SharedHandle<SocketCore> listenSocket(new SocketCore());
|
||||
listenSocket->bind(0);
|
||||
listenSocket->beginListen();
|
||||
std::pair<std::string, uint16_t> addrinfo;
|
||||
listenSocket->getAddrInfo(addrinfo);
|
||||
_listenPort = addrinfo.second;
|
||||
|
||||
SharedHandle<Request> req(new Request());
|
||||
req->setUrl("ftp://localhost/dir/file.img");
|
||||
|
||||
SharedHandle<SocketCore> clientSocket(new SocketCore());
|
||||
clientSocket->establishConnection("127.0.0.1", _listenPort);
|
||||
|
||||
while(!clientSocket->isWritable(0));
|
||||
clientSocket->setBlockingMode();
|
||||
|
||||
_serverSocket.reset(listenSocket->acceptConnection());
|
||||
_ftp.reset(new FtpConnection(1, clientSocket, req, &_option));
|
||||
}
|
||||
|
||||
void tearDown() {}
|
||||
|
||||
void testSendMdtm();
|
||||
void testReceiveMdtmResponse();
|
||||
};
|
||||
|
||||
|
||||
CPPUNIT_TEST_SUITE_REGISTRATION(FtpConnectionTest);
|
||||
|
||||
void FtpConnectionTest::testSendMdtm()
|
||||
{
|
||||
_ftp->sendMdtm();
|
||||
char data[32];
|
||||
size_t len = sizeof(data);
|
||||
_serverSocket->readData(data, len);
|
||||
CPPUNIT_ASSERT_EQUAL((size_t)15, len);
|
||||
data[len] = '\0';
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("MDTM file.img\r\n"), std::string(data));
|
||||
}
|
||||
|
||||
void FtpConnectionTest::testReceiveMdtmResponse()
|
||||
{
|
||||
{
|
||||
Time t;
|
||||
_serverSocket->writeData("213 20080908124312");
|
||||
CPPUNIT_ASSERT_EQUAL((unsigned int)0, _ftp->receiveMdtmResponse(t));
|
||||
_serverSocket->writeData("\r\n");
|
||||
CPPUNIT_ASSERT_EQUAL((unsigned int)213, _ftp->receiveMdtmResponse(t));
|
||||
CPPUNIT_ASSERT_EQUAL((time_t)1220877792, t.getTime());
|
||||
}
|
||||
{
|
||||
// see milli second part is ignored
|
||||
Time t;
|
||||
_serverSocket->writeData("213 20080908124312.014\r\n");
|
||||
CPPUNIT_ASSERT_EQUAL((unsigned int)213, _ftp->receiveMdtmResponse(t));
|
||||
CPPUNIT_ASSERT_EQUAL((time_t)1220877792, t.getTime());
|
||||
}
|
||||
{
|
||||
// hhmmss part is missing
|
||||
Time t;
|
||||
_serverSocket->writeData("213 20080908\r\n");
|
||||
CPPUNIT_ASSERT_EQUAL((unsigned int)213, _ftp->receiveMdtmResponse(t));
|
||||
CPPUNIT_ASSERT_EQUAL((time_t)-1, t.getTime());
|
||||
}
|
||||
{
|
||||
// invalid month: 19
|
||||
Time t;
|
||||
_serverSocket->writeData("213 20081908124312\r\n");
|
||||
CPPUNIT_ASSERT_EQUAL((unsigned int)213, _ftp->receiveMdtmResponse(t));
|
||||
CPPUNIT_ASSERT_EQUAL((time_t)-1, t.getTime());
|
||||
}
|
||||
{
|
||||
Time t;
|
||||
_serverSocket->writeData("550 File Not Found\r\n");
|
||||
CPPUNIT_ASSERT_EQUAL((unsigned int)550, _ftp->receiveMdtmResponse(t));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace aria2
|
@ -62,7 +62,8 @@ aria2c_SOURCES = AllTest.cc\
|
||||
CookieTest.cc\
|
||||
CookieStorageTest.cc\
|
||||
TimeTest.cc\
|
||||
CopyDiskAdaptorTest.cc
|
||||
CopyDiskAdaptorTest.cc\
|
||||
FtpConnectionTest.cc
|
||||
|
||||
if HAVE_LIBZ
|
||||
aria2c_SOURCES += GZipDecoderTest.cc
|
||||
|
@ -194,8 +194,9 @@ am__aria2c_SOURCES_DIST = AllTest.cc TestUtil.cc TestUtil.h \
|
||||
ServerStatURISelectorTest.cc InOrderURISelectorTest.cc \
|
||||
ServerStatTest.cc NsCookieParserTest.cc \
|
||||
DirectDiskAdaptorTest.cc CookieTest.cc CookieStorageTest.cc \
|
||||
TimeTest.cc CopyDiskAdaptorTest.cc GZipDecoderTest.cc \
|
||||
Sqlite3MozCookieParserTest.cc MessageDigestHelperTest.cc \
|
||||
TimeTest.cc CopyDiskAdaptorTest.cc FtpConnectionTest.cc \
|
||||
GZipDecoderTest.cc Sqlite3MozCookieParserTest.cc \
|
||||
MessageDigestHelperTest.cc \
|
||||
IteratableChunkChecksumValidatorTest.cc \
|
||||
IteratableChecksumValidatorTest.cc BtAllowedFastMessageTest.cc \
|
||||
BtBitfieldMessageTest.cc BtCancelMessageTest.cc \
|
||||
@ -367,8 +368,8 @@ am_aria2c_OBJECTS = AllTest.$(OBJEXT) TestUtil.$(OBJEXT) \
|
||||
NsCookieParserTest.$(OBJEXT) DirectDiskAdaptorTest.$(OBJEXT) \
|
||||
CookieTest.$(OBJEXT) CookieStorageTest.$(OBJEXT) \
|
||||
TimeTest.$(OBJEXT) CopyDiskAdaptorTest.$(OBJEXT) \
|
||||
$(am__objects_1) $(am__objects_2) $(am__objects_3) \
|
||||
$(am__objects_4) $(am__objects_5)
|
||||
FtpConnectionTest.$(OBJEXT) $(am__objects_1) $(am__objects_2) \
|
||||
$(am__objects_3) $(am__objects_4) $(am__objects_5)
|
||||
aria2c_OBJECTS = $(am_aria2c_OBJECTS)
|
||||
am__DEPENDENCIES_1 =
|
||||
aria2c_DEPENDENCIES = ../src/libaria2c.a $(am__DEPENDENCIES_1)
|
||||
@ -590,9 +591,9 @@ aria2c_SOURCES = AllTest.cc TestUtil.cc TestUtil.h SocketCoreTest.cc \
|
||||
ServerStatURISelectorTest.cc InOrderURISelectorTest.cc \
|
||||
ServerStatTest.cc NsCookieParserTest.cc \
|
||||
DirectDiskAdaptorTest.cc CookieTest.cc CookieStorageTest.cc \
|
||||
TimeTest.cc CopyDiskAdaptorTest.cc $(am__append_1) \
|
||||
$(am__append_2) $(am__append_3) $(am__append_4) \
|
||||
$(am__append_5)
|
||||
TimeTest.cc CopyDiskAdaptorTest.cc FtpConnectionTest.cc \
|
||||
$(am__append_1) $(am__append_2) $(am__append_3) \
|
||||
$(am__append_4) $(am__append_5)
|
||||
|
||||
#aria2c_CXXFLAGS = ${CPPUNIT_CFLAGS} -I../src -I../lib -Wall -D_FILE_OFFSET_BITS=64
|
||||
#aria2c_LDFLAGS = ${CPPUNIT_LIBS}
|
||||
@ -759,6 +760,7 @@ distclean-compile:
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FeatureConfigTest.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FileEntryTest.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FileTest.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FtpConnectionTest.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/GZipDecoderTest.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/GrowSegmentTest.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HandshakeExtensionMessageTest.Po@am__quote@
|
||||
|
Loading…
Reference in New Issue
Block a user