From e36a3de0f458a9267f4d4907e78e706400b7a18c Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Sat, 30 Jun 2007 09:52:39 +0000 Subject: [PATCH] 2007-06-30 Tatsuhiro Tsujikawa Made -S option work with metalink file and provided selective download to metalink. * src/MetalinkEntry.h, src/MetalinkEntry.cc (filename): Removed. (file): New variable. (size): Removed. (operator=): Updated. (getPath): New function. (getLength): New function. (toFileEntry): New function. * src/TorrentRequestInfo.h, src/TorrentRequestInfo.cc (execute): Use toStream. (showFileEntry): Removed. * src/MetalinkRequestInfo.h (targetFiles): New variable. (setTargetFiles): New variable. * src/MetalinkRequestInfo.cc (execute): Added the ability to print file information included in a metalink file. Added selective download mode to metalink. * src/main.cc (showUsage): Updated to denote that -S and --select-file options are applicable to metalink. * src/FileEntry.h (operator=): New function. (getBasename): New function. (getDirname): New function. * src/Util.h, src/Util.cc (toStream): New function. * src/Xml2MetalinkProcessor.cc: Updated. Made aria2 work with metalink with directory structure. * src/File.h, src/File.cc (getBasename): New function. (getDirname): New function. * src/RequestGroup.h, src/RequestGroup.cc (_topDir): New variable. (setTopDir): New function. (initSegmentMan): A directory structure is added to _segmentMan->dir. Rewrote HTTP header parsing with stringstream. * src/HttpConnection.h, src/HttpConnection.cc (HttpRequestEntry): New class. (headerBuf): Removed. (headerBufLength): Removed. (outstandingHttpRequests): Now its element type is HttpRequestEntryHandle. (findEndOfHeader): Removed. (receiveResponse): Rewritten. Updated doc for -j option to notice that it should be used with -i option. * src/main.cc (showUsage) Removed unused classes. * src/RequestInfo.h (FileInfo): Removed. (checksum): Removed. (fileInfo): Removed. (setChecksum): Removed. (getChecksum): Removed. (getFileInfo): Removed. Use ISO units. * src/ConsoleDownloadEngine.cc * src/TorrentConsoleDownloadEngine.cc * src/Util.cc (abbrevSize) --- ChangeLog | 70 +++++++++++++++++++ src/ConsoleDownloadEngine.cc | 10 ++- src/File.cc | 17 +++++ src/File.h | 4 ++ src/FileEntry.h | 31 ++++++++- src/HttpConnection.cc | 102 ++++++++-------------------- src/HttpConnection.h | 34 ++++++++-- src/Makefile.am | 5 +- src/Makefile.in | 70 +++++++++---------- src/MetalinkEntry.cc | 17 +++-- src/MetalinkEntry.h | 28 ++++++-- src/MetalinkRequestInfo.cc | 33 +++++++-- src/MetalinkRequestInfo.h | 5 ++ src/MultiUrlRequestInfo.cc | 2 + src/MultiUrlRequestInfo.h | 1 + src/RequestGroup.cc | 3 + src/RequestGroup.h | 6 ++ src/RequestInfo.h | 60 +--------------- src/TorrentConsoleDownloadEngine.cc | 4 +- src/TorrentRequestInfo.cc | 19 +----- src/TorrentRequestInfo.h | 1 - src/Util.cc | 19 +++++- src/Util.h | 6 +- src/Xml2MetalinkProcessor.cc | 12 ++-- src/main.cc | 34 +++++++--- 25 files changed, 360 insertions(+), 233 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1b3edc4b..5afa7067 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,73 @@ +2007-06-30 Tatsuhiro Tsujikawa + + Made -S option work with metalink file and provided selective download + to metalink. + * src/MetalinkEntry.h, src/MetalinkEntry.cc + (filename): Removed. + (file): New variable. + (size): Removed. + (operator=): Updated. + (getPath): New function. + (getLength): New function. + (toFileEntry): New function. + * src/TorrentRequestInfo.h, src/TorrentRequestInfo.cc + (execute): Use toStream. + (showFileEntry): Removed. + * src/MetalinkRequestInfo.h + (targetFiles): New variable. + (setTargetFiles): New variable. + * src/MetalinkRequestInfo.cc + (execute): Added the ability to print file information included in + a metalink file. + Added selective download mode to metalink. + * src/main.cc + (showUsage): Updated to denote that -S and --select-file options are + applicable to metalink. + * src/FileEntry.h + (operator=): New function. + (getBasename): New function. + (getDirname): New function. + * src/Util.h, src/Util.cc + (toStream): New function. + * src/Xml2MetalinkProcessor.cc: Updated. + + Made aria2 work with metalink with directory structure. + * src/File.h, src/File.cc + (getBasename): New function. + (getDirname): New function. + * src/RequestGroup.h, src/RequestGroup.cc + (_topDir): New variable. + (setTopDir): New function. + (initSegmentMan): A directory structure is added to _segmentMan->dir. + + Rewrote HTTP header parsing with stringstream. + * src/HttpConnection.h, src/HttpConnection.cc + (HttpRequestEntry): New class. + (headerBuf): Removed. + (headerBufLength): Removed. + (outstandingHttpRequests): Now its element type is + HttpRequestEntryHandle. + (findEndOfHeader): Removed. + (receiveResponse): Rewritten. + + Updated doc for -j option to notice that it should be used with -i + option. + * src/main.cc (showUsage) + + Removed unused classes. + * src/RequestInfo.h + (FileInfo): Removed. + (checksum): Removed. + (fileInfo): Removed. + (setChecksum): Removed. + (getChecksum): Removed. + (getFileInfo): Removed. + + Use ISO units. + * src/ConsoleDownloadEngine.cc + * src/TorrentConsoleDownloadEngine.cc + * src/Util.cc (abbrevSize) + 2007-06-23 Tatsuhiro Tsujikawa Added the default listening ports to the help message. diff --git a/src/ConsoleDownloadEngine.cc b/src/ConsoleDownloadEngine.cc index 8be480a1..e5f20c6a 100644 --- a/src/ConsoleDownloadEngine.cc +++ b/src/ConsoleDownloadEngine.cc @@ -64,8 +64,10 @@ void ConsoleDownloadEngine::sendStatistics(long long int currentSize, long long cout << "[" << "#" << firstRequestGroup->getGID() << " " << Util::abbrevSize(firstRequestGroup->getDownloadLength()) + << "B" << "/" - << Util::abbrevSize(firstRequestGroup->getTotalLength()); + << Util::abbrevSize(firstRequestGroup->getTotalLength()) + << "B"; if(firstRequestGroup->getTotalLength() > 0) { cout << "(" << 100*firstRequestGroup->getDownloadLength()/firstRequestGroup->getTotalLength() @@ -81,7 +83,7 @@ void ConsoleDownloadEngine::sendStatistics(long long int currentSize, long long } cout << "]"; } - cout << "[" << fixed << setprecision(2) << speed/1024.0 << "KB/s" << "]"; + cout << "[" << fixed << setprecision(2) << speed/1024.0 << "KiB/s" << "]"; { FileAllocationEntryHandle entry = _fileAllocationMan->getCurrentFileAllocationEntry(); @@ -89,8 +91,10 @@ void ConsoleDownloadEngine::sendStatistics(long long int currentSize, long long cout << "[FileAlloc:" << "#" << entry->getRequestGroup()->getGID() << " " << Util::abbrevSize(entry->getCurrentLength()) + << "B" << "/" << Util::abbrevSize(entry->getTotalLength()) + << "B" << "(" << 100*entry->getCurrentLength()/entry->getTotalLength() << "%)"; @@ -108,8 +112,10 @@ void ConsoleDownloadEngine::sendStatistics(long long int currentSize, long long cout << "[Checksum:" << "#" << entry->getRequestGroup()->getGID() << " " << Util::abbrevSize(entry->getCurrentLength()) + << "B" << "/" << Util::abbrevSize(entry->getTotalLength()) + << "B" << "(" << 100*entry->getCurrentLength()/entry->getTotalLength() << "%)"; diff --git a/src/File.cc b/src/File.cc index 7ddc71a2..0d55a250 100644 --- a/src/File.cc +++ b/src/File.cc @@ -37,6 +37,7 @@ #include #include #include +#include File::File(const string& name):name(name) {} @@ -120,3 +121,19 @@ mode_t File::mode() } return fstat.st_mode; } + +string File::getBasename() const +{ + char* s = strdup(name.c_str()); + string bname = basename(s); + free(s); + return bname; +} + +string File::getDirname() const +{ + char* s = strdup(name.c_str()); + string dname = dirname(s); + free(s); + return dname; +} diff --git a/src/File.h b/src/File.h index db75c344..32519089 100644 --- a/src/File.h +++ b/src/File.h @@ -86,6 +86,10 @@ public: int64_t size(); mode_t mode(); + + string getBasename() const; + + string getDirname() const; }; #endif // _D_FILE_H_ diff --git a/src/FileEntry.h b/src/FileEntry.h index 0113921a..eb162bfe 100644 --- a/src/FileEntry.h +++ b/src/FileEntry.h @@ -36,24 +36,49 @@ #define _D_FILE_ENTRY_H_ #include "common.h" +#include "File.h" class FileEntry { private: string path; - long long int length; - long long int offset; + int64_t length; + int64_t offset; bool extracted; bool requested; public: + FileEntry():length(0), offset(0), extracted(false), requested(false) {} + FileEntry(const string& path, long long int length, long long int offset); + FileEntry& operator=(const FileEntry& entry) + { + if(this != &entry) { + path = entry.path; + length = entry.length; + offset = entry.offset; + extracted = entry.extracted; + requested = entry.requested; + } + return *this; + } + ~FileEntry(); + string getBasename() const + { + return File(path).getBasename(); + } + + string getDirname() const + { + return File(path).getDirname(); + } + const string& getPath() const { return path; } void setPath(const string& path) { this->path = path; } - long long int getLength() const { return length; } + int64_t getLength() const { return length; } void setLength(long long int length) { this->length = length; } diff --git a/src/HttpConnection.cc b/src/HttpConnection.cc index c35273ed..7f93bb26 100644 --- a/src/HttpConnection.cc +++ b/src/HttpConnection.cc @@ -34,6 +34,7 @@ /* copyright --> */ #include "HttpConnection.h" #include "DlRetryEx.h" +#include "DlAbortEx.h" #include "Util.h" #include "Base64.h" #include "message.h" @@ -44,9 +45,8 @@ HttpConnection::HttpConnection(int cuid, const SocketHandle& socket, const Option* op): - cuid(cuid), socket(socket), option(op), headerBufLength(0) { - logger = LogFactory::getInstance(); -} + cuid(cuid), socket(socket), option(op), logger(LogFactory::getInstance()) +{} string HttpConnection::eraseConfidentialInfo(const string& request) { @@ -70,7 +70,8 @@ void HttpConnection::sendRequest(const HttpRequestHandle& httpRequest) string request = httpRequest->createRequest(); logger->info(MSG_SENDING_REQUEST, cuid, eraseConfidentialInfo(request).c_str()); socket->writeData(request.c_str(), request.size()); - outstandingHttpRequests.push_back(httpRequest); + outstandingHttpRequests.push_back(new HttpRequestEntry(httpRequest, + new HttpHeaderProcessor())); } void HttpConnection::sendProxyRequest(const HttpRequestHandle& httpRequest) @@ -78,88 +79,41 @@ void HttpConnection::sendProxyRequest(const HttpRequestHandle& httpRequest) string request = httpRequest->createProxyRequest(); logger->info(MSG_SENDING_REQUEST, cuid, eraseConfidentialInfo(request).c_str()); socket->writeData(request.c_str(), request.size()); - outstandingHttpRequests.push_back(httpRequest); -} - -int HttpConnection::findEndOfHeader(const char* buf, const char* substr, int bufLength) const { - const char* p = buf; - while(bufLength > p-buf && bufLength-(p-buf) >= (int)strlen(substr)) { - if(memcmp(p, substr, strlen(substr)) == 0) { - return p-buf; - } - p++; - } - return -1; + outstandingHttpRequests.push_back(new HttpRequestEntry(httpRequest, + new HttpHeaderProcessor())); } HttpResponseHandle HttpConnection::receiveResponse() { - //char buf[512]; - string header; - int delimiterSwitch = 0; - char* delimiters[] = { "\r\n", "\n" }; - - int size = HEADERBUF_SIZE-headerBufLength; - if(size < 0) { - // TODO too large header - throw new DlRetryEx("too large header > 4096"); + if(outstandingHttpRequests.size() == 0) { + throw new DlAbortEx("No HttpRequestEntry found."); } - socket->peekData(headerBuf+headerBufLength, size); + HttpRequestEntryHandle entry = outstandingHttpRequests.front(); + HttpHeaderProcessorHandle proc = entry->getHttpHeaderProcessor(); + + char buf[512]; + int32_t size = sizeof(buf); + socket->peekData(buf, size); if(size == 0) { throw new DlRetryEx(EX_INVALID_RESPONSE); } - //buf[size] = '\0'; - int hlenTemp = headerBufLength+size; - //header += buf; - //string::size_type p; - int eohIndex; - - if((eohIndex = findEndOfHeader(headerBuf, "\r\n\r\n", hlenTemp)) == -1 && - (eohIndex = findEndOfHeader(headerBuf, "\n\n", hlenTemp)) == -1) { - socket->readData(headerBuf+headerBufLength, size); - headerBufLength += size; - } else { - if(headerBuf[eohIndex] == '\n') { - // for crapping non-standard HTTP server - delimiterSwitch = 1; - } else { - delimiterSwitch = 0; - } - headerBuf[eohIndex+strlen(delimiters[delimiterSwitch])*2] = '\0'; - header = headerBuf; - size = eohIndex+strlen(delimiters[delimiterSwitch])*2-headerBufLength; - socket->readData(headerBuf+headerBufLength, size); - } - if(!Util::endsWith(header, "\r\n\r\n") && !Util::endsWith(header, "\n\n")) { + proc->update(buf, size); + if(!proc->eoh()) { + socket->readData(buf, size); return 0; } + int32_t putbackDataLength = proc->getPutBackDataLength(); + size -= putbackDataLength; + socket->readData(buf, size); + // OK, we got all headers. - logger->info(MSG_RECEIVE_RESPONSE, cuid, header.c_str()); - string::size_type p, np; - p = np = 0; - np = header.find(delimiters[delimiterSwitch], p); - if(np == string::npos) { - throw new DlRetryEx(EX_NO_STATUS_HEADER); - } - // check HTTP status value - if(header.size() <= 12) { - throw new DlRetryEx(EX_NO_STATUS_HEADER); - } - string status = header.substr(9, 3); - p = np+2; - HttpHeaderHandle httpHeader = new HttpHeader(); - // retreive status name-value pairs, then push these into map - while((np = header.find(delimiters[delimiterSwitch], p)) != string::npos && np != p) { - string line = header.substr(p, np-p); - p = np+2; - pair hp; - Util::split(hp, line, ':'); - httpHeader->put(hp.first, hp.second); - } + logger->info(MSG_RECEIVE_RESPONSE, cuid, proc->getHeaderString().c_str()); + + pair httpStatusHeader = proc->getHttpStatusHeader(); HttpResponseHandle httpResponse = new HttpResponse(); httpResponse->setCuid(cuid); - httpResponse->setStatus(strtol(status.c_str(), 0, 10)); - httpResponse->setHttpHeader(httpHeader); - httpResponse->setHttpRequest(outstandingHttpRequests.front()); + httpResponse->setStatus(strtol(httpStatusHeader.first.c_str(), 0, 10)); + httpResponse->setHttpHeader(httpStatusHeader.second); + httpResponse->setHttpRequest(entry->getHttpRequest()); outstandingHttpRequests.pop_front(); diff --git a/src/HttpConnection.h b/src/HttpConnection.h index 61c4ee87..96ab0f77 100644 --- a/src/HttpConnection.h +++ b/src/HttpConnection.h @@ -43,10 +43,35 @@ #include "common.h" #include "Logger.h" #include "HttpResponse.h" +#include "HttpHeaderProcessor.h" #include #include -#define HEADERBUF_SIZE 4096 +class HttpRequestEntry { +private: + HttpRequestHandle _httpRequest; + HttpHeaderProcessorHandle _proc; +public: + HttpRequestEntry(const HttpRequestHandle& httpRequest, + const HttpHeaderProcessorHandle& proc): + _httpRequest(httpRequest), + _proc(proc) {} + + ~HttpRequestEntry() {} + + HttpRequestHandle getHttpRequest() const + { + return _httpRequest; + } + + HttpHeaderProcessorHandle getHttpHeaderProcessor() const + { + return _proc; + } +}; + +typedef SharedHandle HttpRequestEntryHandle; +typedef deque HttpRequestEntries; class HttpConnection { private: @@ -54,12 +79,9 @@ private: SocketHandle socket; const Option* option; const Logger* logger; - char headerBuf[HEADERBUF_SIZE+1]; - int headerBufLength; - HttpRequests outstandingHttpRequests; + HttpRequestEntries outstandingHttpRequests; - int findEndOfHeader(const char* buf, const char* substr, int bufLength) const; string eraseConfidentialInfo(const string& request); public: HttpConnection(int cuid, @@ -96,7 +118,7 @@ public: HttpRequestHandle getFirstHttpRequest() const { if(outstandingHttpRequests.size() > 0) { - return outstandingHttpRequests.front(); + return outstandingHttpRequests.front()->getHttpRequest(); } else { return 0; } diff --git a/src/Makefile.am b/src/Makefile.am index bf034904..0ff3f071 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -103,7 +103,9 @@ SRCS = Socket.h\ RequestGroupEntry.cc RequestGroupEntry.h\ Cookie.cc Cookie.h\ CookieParser.cc CookieParser.h\ - CookieBoxFactory.cc CookieBoxFactory.h + CookieBoxFactory.cc CookieBoxFactory.h\ + HttpHeaderProcessor.cc HttpHeaderProcessor.h\ + FileEntry.cc FileEntry.h # debug_new.cpp if ENABLE_BITTORRENT @@ -133,7 +135,6 @@ SRCS += MetaEntry.h\ CopyDiskAdaptor.cc CopyDiskAdaptor.h\ DirectDiskAdaptor.cc DirectDiskAdaptor.h\ MultiDiskAdaptor.cc MultiDiskAdaptor.h\ - FileEntry.cc FileEntry.h\ TrackerUpdateCommand.cc TrackerUpdateCommand.h\ ByteArrayDiskWriter.cc ByteArrayDiskWriter.h\ PeerChokeCommand.cc PeerChokeCommand.h\ diff --git a/src/Makefile.in b/src/Makefile.in index 4dc57634..e81e1b66 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -65,7 +65,6 @@ bin_PROGRAMS = aria2c$(EXEEXT) @ENABLE_BITTORRENT_TRUE@ CopyDiskAdaptor.cc CopyDiskAdaptor.h\ @ENABLE_BITTORRENT_TRUE@ DirectDiskAdaptor.cc DirectDiskAdaptor.h\ @ENABLE_BITTORRENT_TRUE@ MultiDiskAdaptor.cc MultiDiskAdaptor.h\ -@ENABLE_BITTORRENT_TRUE@ FileEntry.cc FileEntry.h\ @ENABLE_BITTORRENT_TRUE@ TrackerUpdateCommand.cc TrackerUpdateCommand.h\ @ENABLE_BITTORRENT_TRUE@ ByteArrayDiskWriter.cc ByteArrayDiskWriter.h\ @ENABLE_BITTORRENT_TRUE@ PeerChokeCommand.cc PeerChokeCommand.h\ @@ -242,12 +241,13 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \ CheckIntegrityEntry.h CheckIntegrityMan.h ProgressAwareEntry.h \ RequestGroupEntry.cc RequestGroupEntry.h Cookie.cc Cookie.h \ CookieParser.cc CookieParser.h CookieBoxFactory.cc \ - CookieBoxFactory.h MetaEntry.h Data.cc Data.h Dictionary.cc \ - Dictionary.h List.cc List.h MetaFileUtil.cc MetaFileUtil.h \ - MetaEntryVisitor.h ShaVisitor.cc ShaVisitor.h \ - PeerConnection.cc PeerConnection.h PeerMessageUtil.cc \ - PeerMessageUtil.h PeerAbstractCommand.cc PeerAbstractCommand.h \ - PeerInitiateConnectionCommand.cc \ + CookieBoxFactory.h HttpHeaderProcessor.cc \ + HttpHeaderProcessor.h FileEntry.cc FileEntry.h MetaEntry.h \ + Data.cc Data.h Dictionary.cc Dictionary.h List.cc List.h \ + MetaFileUtil.cc MetaFileUtil.h MetaEntryVisitor.h \ + ShaVisitor.cc ShaVisitor.h PeerConnection.cc PeerConnection.h \ + PeerMessageUtil.cc PeerMessageUtil.h PeerAbstractCommand.cc \ + PeerAbstractCommand.h PeerInitiateConnectionCommand.cc \ PeerInitiateConnectionCommand.h PeerInteractionCommand.cc \ PeerInteractionCommand.h Peer.cc Peer.h \ TorrentDownloadEngine.cc TorrentDownloadEngine.h \ @@ -259,31 +259,30 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \ DiskAdaptor.cc DiskAdaptor.h AbstractSingleDiskAdaptor.cc \ AbstractSingleDiskAdaptor.h CopyDiskAdaptor.cc \ CopyDiskAdaptor.h DirectDiskAdaptor.cc DirectDiskAdaptor.h \ - MultiDiskAdaptor.cc MultiDiskAdaptor.h FileEntry.cc \ - FileEntry.h TrackerUpdateCommand.cc TrackerUpdateCommand.h \ - ByteArrayDiskWriter.cc ByteArrayDiskWriter.h \ - PeerChokeCommand.cc PeerChokeCommand.h HaveEraseCommand.cc \ - HaveEraseCommand.h TorrentRequestInfo.cc TorrentRequestInfo.h \ - SeedCriteria.h TimeSeedCriteria.h ShareRatioSeedCriteria.h \ - UnionSeedCriteria.h SeedCheckCommand.cc SeedCheckCommand.h \ - PeerListProcessor.h DefaultPeerListProcessor.cc \ - DefaultPeerListProcessor.h CompactPeerListProcessor.cc \ - CompactPeerListProcessor.h DelegatingPeerListProcessor.cc \ - DelegatingPeerListProcessor.h AnnounceTier.h AnnounceList.h \ - AnnounceList.cc BtContext.h DefaultBtContext.cc \ - DefaultBtContext.h PieceStorage.h DefaultPieceStorage.cc \ - DefaultPieceStorage.h DefaultPeerStorage.cc \ - DefaultPeerStorage.h BtAnnounce.h DefaultBtAnnounce.cc \ - DefaultBtAnnounce.h BtRegistry.cc BtRegistry.h BtRuntime.h \ - BtProgressInfoFile.h DefaultBtProgressInfoFile.cc \ - DefaultBtProgressInfoFile.h BtContextAwareCommand.cc \ - BtContextAwareCommand.h BtMessage.h AbstractBtMessage.h \ - SimpleBtMessage.cc SimpleBtMessage.h BtAllowedFastMessage.cc \ - BtAllowedFastMessage.h BtBitfieldMessage.cc \ - BtBitfieldMessage.h BtCancelMessage.cc BtCancelMessage.h \ - BtChokeMessage.cc BtChokeMessage.h BtHaveAllMessage.cc \ - BtHaveAllMessage.h BtHaveMessage.cc BtHaveMessage.h \ - BtHaveNoneMessage.cc BtHaveNoneMessage.h \ + MultiDiskAdaptor.cc MultiDiskAdaptor.h TrackerUpdateCommand.cc \ + TrackerUpdateCommand.h ByteArrayDiskWriter.cc \ + ByteArrayDiskWriter.h PeerChokeCommand.cc PeerChokeCommand.h \ + HaveEraseCommand.cc HaveEraseCommand.h TorrentRequestInfo.cc \ + TorrentRequestInfo.h SeedCriteria.h TimeSeedCriteria.h \ + ShareRatioSeedCriteria.h UnionSeedCriteria.h \ + SeedCheckCommand.cc SeedCheckCommand.h PeerListProcessor.h \ + DefaultPeerListProcessor.cc DefaultPeerListProcessor.h \ + CompactPeerListProcessor.cc CompactPeerListProcessor.h \ + DelegatingPeerListProcessor.cc DelegatingPeerListProcessor.h \ + AnnounceTier.h AnnounceList.h AnnounceList.cc BtContext.h \ + DefaultBtContext.cc DefaultBtContext.h PieceStorage.h \ + DefaultPieceStorage.cc DefaultPieceStorage.h \ + DefaultPeerStorage.cc DefaultPeerStorage.h BtAnnounce.h \ + DefaultBtAnnounce.cc DefaultBtAnnounce.h BtRegistry.cc \ + BtRegistry.h BtRuntime.h BtProgressInfoFile.h \ + DefaultBtProgressInfoFile.cc DefaultBtProgressInfoFile.h \ + BtContextAwareCommand.cc BtContextAwareCommand.h BtMessage.h \ + AbstractBtMessage.h SimpleBtMessage.cc SimpleBtMessage.h \ + BtAllowedFastMessage.cc BtAllowedFastMessage.h \ + BtBitfieldMessage.cc BtBitfieldMessage.h BtCancelMessage.cc \ + BtCancelMessage.h BtChokeMessage.cc BtChokeMessage.h \ + BtHaveAllMessage.cc BtHaveAllMessage.h BtHaveMessage.cc \ + BtHaveMessage.h BtHaveNoneMessage.cc BtHaveNoneMessage.h \ BtInterestedMessage.cc BtInterestedMessage.h \ BtKeepAliveMessage.cc BtKeepAliveMessage.h \ BtNotInterestedMessage.cc BtNotInterestedMessage.h \ @@ -336,7 +335,6 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \ @ENABLE_BITTORRENT_TRUE@ CopyDiskAdaptor.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ DirectDiskAdaptor.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ MultiDiskAdaptor.$(OBJEXT) \ -@ENABLE_BITTORRENT_TRUE@ FileEntry.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ TrackerUpdateCommand.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ ByteArrayDiskWriter.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ PeerChokeCommand.$(OBJEXT) \ @@ -429,6 +427,7 @@ am__objects_3 = SocketCore.$(OBJEXT) Command.$(OBJEXT) \ ChecksumCommand.$(OBJEXT) CheckIntegrityEntry.$(OBJEXT) \ RequestGroupEntry.$(OBJEXT) Cookie.$(OBJEXT) \ CookieParser.$(OBJEXT) CookieBoxFactory.$(OBJEXT) \ + HttpHeaderProcessor.$(OBJEXT) FileEntry.$(OBJEXT) \ $(am__objects_1) $(am__objects_2) am_libaria2c_a_OBJECTS = $(am__objects_3) libaria2c_a_OBJECTS = $(am_libaria2c_a_OBJECTS) @@ -663,7 +662,9 @@ SRCS = Socket.h SocketCore.cc SocketCore.h Command.cc Command.h \ CheckIntegrityEntry.h CheckIntegrityMan.h ProgressAwareEntry.h \ RequestGroupEntry.cc RequestGroupEntry.h Cookie.cc Cookie.h \ CookieParser.cc CookieParser.h CookieBoxFactory.cc \ - CookieBoxFactory.h $(am__append_1) $(am__append_2) + CookieBoxFactory.h HttpHeaderProcessor.cc \ + HttpHeaderProcessor.h FileEntry.cc FileEntry.h $(am__append_1) \ + $(am__append_2) noinst_LIBRARIES = libaria2c.a libaria2c_a_SOURCES = $(SRCS) aria2c_LDADD = libaria2c.a @LIBINTL@ @ALLOCA@ @LIBGNUTLS_LIBS@\ @@ -839,6 +840,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HttpConnection.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HttpDownloadCommand.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HttpHeader.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HttpHeaderProcessor.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HttpInitiateConnectionCommand.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HttpProxyRequestCommand.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HttpProxyResponseCommand.Po@am__quote@ diff --git a/src/MetalinkEntry.cc b/src/MetalinkEntry.cc index 6c77f848..e4c1497d 100644 --- a/src/MetalinkEntry.cc +++ b/src/MetalinkEntry.cc @@ -36,11 +36,9 @@ #include "Util.h" #include -MetalinkEntry::MetalinkEntry(): - size(0) +MetalinkEntry::MetalinkEntry() #ifdef ENABLE_MESSAGE_DIGEST - , - checksum(0), + :checksum(0), chunkChecksum(0) #endif // ENABLE_MESSAGE_DIGEST {} @@ -102,3 +100,14 @@ void MetalinkEntry::dropUnsupportedResource() { partition(resources.begin(), resources.end(), Supported()); resources.erase(split, resources.end()); } + +FileEntries MetalinkEntry::toFileEntry(const MetalinkEntries& metalinkEntries) +{ + FileEntries entries; + for(MetalinkEntries::const_iterator itr = metalinkEntries.begin(); + itr != metalinkEntries.end(); ++itr) { + entries.push_back((*itr)->file); + } + return entries; +} + diff --git a/src/MetalinkEntry.h b/src/MetalinkEntry.h index bc9aa4e2..37b966f7 100644 --- a/src/MetalinkEntry.h +++ b/src/MetalinkEntry.h @@ -39,15 +39,20 @@ #include "MetalinkResource.h" #include "Checksum.h" #include "MetalinkChunkChecksum.h" +#include "FileEntry.h" #include +class MetalinkEntry; + +typedef SharedHandle MetalinkEntryHandle; +typedef deque MetalinkEntries; + class MetalinkEntry { public: - string filename; + FileEntryHandle file; string version; string language; string os; - int64_t size; ChecksumHandle checksum; public: MetalinkResources resources; @@ -56,15 +61,15 @@ public: #endif // ENABLE_MESSAGE_DIGEST public: MetalinkEntry(); + ~MetalinkEntry(); MetalinkEntry& operator=(const MetalinkEntry& metalinkEntry) { if(this != &metalinkEntry) { - this->filename = metalinkEntry.filename; + this->file = metalinkEntry.file; this->version = metalinkEntry.version; this->language = metalinkEntry.language; this->os = metalinkEntry.os; - this->size = metalinkEntry.size; this->checksum = metalinkEntry.checksum; #ifdef ENABLE_MESSAGE_DIGEST this->chunkChecksum = metalinkEntry.chunkChecksum; @@ -73,14 +78,23 @@ public: return *this; } + string getPath() const + { + return file->getPath(); + } + + int64_t getLength() const + { + return file->getLength(); + } + void dropUnsupportedResource(); void reorderResourcesByPreference(); void setLocationPreference(const string& location, int preferenceToAdd); + + static FileEntries toFileEntry(const MetalinkEntries& metalinkEntries); }; -typedef SharedHandle MetalinkEntryHandle; -typedef deque MetalinkEntries; - #endif // _D_METALINK_ENTRY_H_ diff --git a/src/MetalinkRequestInfo.cc b/src/MetalinkRequestInfo.cc index 2af1188d..3081fb27 100644 --- a/src/MetalinkRequestInfo.cc +++ b/src/MetalinkRequestInfo.cc @@ -37,6 +37,7 @@ #include "prefs.h" #include "DlAbortEx.h" #include "MultiUrlRequestInfo.h" +#include "Util.h" class AccumulateNonP2PUrl { private: @@ -87,19 +88,42 @@ RequestInfos MetalinkRequestInfo::execute() { printf("No file matched with your preference.\n"); throw new DlAbortEx("No file matched with your preference."); } + if(op->get(PREF_SHOW_FILES) == V_TRUE) { + Util::toStream(cout, MetalinkEntry::toFileEntry(entries)); + return RequestInfos(); + } + bool useIndex; + Integers selectIndexes; + Util::unfoldRange(op->get(PREF_SELECT_FILE), selectIndexes); + if(selectIndexes.size()) { + useIndex = true; + } else { + useIndex = false; + } RequestGroups groups; + int32_t count = 0; for(MetalinkEntries::iterator itr = entries.begin(); itr != entries.end(); - itr++) { + itr++, ++count) { MetalinkEntryHandle& entry = *itr; if(op->defined(PREF_METALINK_LOCATION)) { entry->setLocationPreference(op->get(PREF_METALINK_LOCATION), 100); } + if(useIndex) { + if(find(selectIndexes.begin(), selectIndexes.end(), count+1) == selectIndexes.end()) { + continue; + } + } else if(!targetFiles.empty()) { + if(find(targetFiles.begin(), targetFiles.end(), entry->getPath()) == targetFiles.end()) { + continue; + } + } + entry->dropUnsupportedResource(); if(entry->resources.size() == 0) { continue; } logger->info("Metalink: Queueing %s for download.", - entry->filename.c_str()); + entry->getPath().c_str()); MetalinkResources::iterator itr = find_if(entry->resources.begin(), entry->resources.end(), @@ -119,8 +143,9 @@ RequestInfos MetalinkRequestInfo::execute() { urls.push_back((*itr)->url); } RequestGroupHandle rg = new RequestGroup(urls, op); - rg->setHintFilename(entry->filename); - rg->setHintTotalLength(entry->size); + rg->setHintFilename(entry->file->getBasename()); + rg->setTopDir(entry->file->getDirname()); + rg->setHintTotalLength(entry->getLength()); rg->setNumConcurrentCommand(op->getAsInt(PREF_METALINK_SERVERS)); #ifdef ENABLE_MESSAGE_DIGEST diff --git a/src/MetalinkRequestInfo.h b/src/MetalinkRequestInfo.h index 2e52c3a2..c89c3787 100644 --- a/src/MetalinkRequestInfo.h +++ b/src/MetalinkRequestInfo.h @@ -40,6 +40,7 @@ class MetalinkRequestInfo : public RequestInfo { private: string metalinkFile; + Strings targetFiles; public: MetalinkRequestInfo(const string& metalinkFile, Option* op): RequestInfo(op), @@ -47,6 +48,10 @@ public: virtual ~MetalinkRequestInfo() {} virtual RequestInfos execute(); + + void setTargetFiles(const Strings& targetFiles) { + this->targetFiles = targetFiles; + } }; #endif // _D_METALINK_REQUEST_INFO_H_ diff --git a/src/MultiUrlRequestInfo.cc b/src/MultiUrlRequestInfo.cc index 8683ec2c..ced6c0d8 100644 --- a/src/MultiUrlRequestInfo.cc +++ b/src/MultiUrlRequestInfo.cc @@ -40,6 +40,8 @@ #include "DNSCache.h" #include "TorrentRequestInfo.h" #include "MetalinkRequestInfo.h" +#include "Util.h" +#include extern volatile sig_atomic_t haltRequested; diff --git a/src/MultiUrlRequestInfo.h b/src/MultiUrlRequestInfo.h index 17227136..de065a43 100644 --- a/src/MultiUrlRequestInfo.h +++ b/src/MultiUrlRequestInfo.h @@ -36,6 +36,7 @@ #define _D_MULTI_URL_REQUEST_INFO_H_ #include "RequestInfo.h" +#include "RequestGroup.h" class MultiUrlRequestInfo : public RequestInfo { private: diff --git a/src/RequestGroup.cc b/src/RequestGroup.cc index 286a4c25..be1af6d7 100644 --- a/src/RequestGroup.cc +++ b/src/RequestGroup.cc @@ -53,6 +53,9 @@ SegmentManHandle RequestGroup::initSegmentMan() { _segmentMan = _segmentManFactory->createNewInstance(); _segmentMan->ufilename = _ufilename; + if(!_topDir.empty() && _topDir != ".") { + _segmentMan->dir += "/"+_topDir; + } return _segmentMan; } diff --git a/src/RequestGroup.h b/src/RequestGroup.h index 930b1d07..edde7cf7 100644 --- a/src/RequestGroup.h +++ b/src/RequestGroup.h @@ -54,6 +54,7 @@ private: int64_t _hintTotalLength; string _hintFilename; string _ufilename; + string _topDir; Strings _uris; Strings _spentUris; SegmentManHandle _segmentMan; @@ -288,6 +289,11 @@ public: { return _gid; } + + void setTopDir(const string& topDir) + { + _topDir = topDir; + } }; typedef SharedHandle RequestGroupHandle; diff --git a/src/RequestInfo.h b/src/RequestInfo.h index 99e43beb..69365963 100644 --- a/src/RequestInfo.h +++ b/src/RequestInfo.h @@ -38,52 +38,6 @@ #include "common.h" #include "LogFactory.h" #include "Option.h" -#include "DownloadEngine.h" -#include "Util.h" -#include "Checksum.h" -#include - -class FileInfo { -public: - string filename; - long long int length; - Checksum checksum; -public: - FileInfo():length(0) {} - ~FileInfo() {} - - bool isEmpty() const { - return filename.size() == 0 && length == 0; - } - - bool checkReady() const { -#ifdef ENABLE_MESSAGE_DIGEST - return !isEmpty() && !checksum.isEmpty(); -#else - return false; -#endif // ENABLE_MESSAGE_DIGEST - } - - bool check() const { -#ifdef ENABLE_MESSAGE_DIGEST - unsigned char md[MAX_MD_LENGTH]; - Util::fileChecksum(filename, md, checksum.getDigestAlgo()); - return Util::toHex(md, - MessageDigestContext::digestLength(checksum.getDigestAlgo())) - == checksum.getMessageDigest(); -#else - return false; -#endif // ENABLE_MESSAGE_DIGEST - } - - bool isTorrentFile() const { - return Util::endsWith(filename, ".torrent"); - } - - bool isMetalinkFile() const { - return Util::endsWith(filename, ".metalink"); - } -}; class RequestInfo; @@ -94,8 +48,6 @@ class RequestInfo { protected: Option* op; const Logger* logger; - Checksum checksum; - FileInfo fileInfo; bool fail; void printDownloadCompeleteMessage(const string& filename) { @@ -114,21 +66,15 @@ protected: public: RequestInfo(Option* op): op(op), + logger(LogFactory::getInstance()), fail(false) - { - logger = LogFactory::getInstance(); - } + {} + virtual ~RequestInfo() {} virtual RequestInfos execute() = 0; bool isFail() const { return fail; } - - void setChecksum(const Checksum& checksum) { - this->checksum = checksum; - } - const Checksum& getChecksum() const { return checksum; } - const FileInfo& getFileInfo() const { return fileInfo; } }; #endif // _D_REQUEST_INFO_H_ diff --git a/src/TorrentConsoleDownloadEngine.cc b/src/TorrentConsoleDownloadEngine.cc index da582e0c..ad036147 100644 --- a/src/TorrentConsoleDownloadEngine.cc +++ b/src/TorrentConsoleDownloadEngine.cc @@ -48,7 +48,7 @@ void TorrentConsoleDownloadEngine::sendStatistics() { if(pieceStorage->downloadFinished()) { printf("Download Completed."); } else { - printf("%s/%sB %d%% %s D:%.2f", + printf("%sB/%sB %d%% %s D:%.2f", Util::abbrevSize(downloadLength).c_str(), Util::abbrevSize(totalLength).c_str(), (totalLength == 0 ? @@ -56,7 +56,7 @@ void TorrentConsoleDownloadEngine::sendStatistics() { avgSpeed == 0 ? "-" : Util::secfmt(eta).c_str(), downloadSpeed/1024.0); } - printf(" U:%.2f(%s) %d peers", + printf(" U:%.2f(%sB) %d peers", uploadSpeed/1024.0, Util::abbrevSize(uploadLength).c_str(), btRuntime->getConnections()); diff --git a/src/TorrentRequestInfo.cc b/src/TorrentRequestInfo.cc index 0068c1ca..d37d45e8 100644 --- a/src/TorrentRequestInfo.cc +++ b/src/TorrentRequestInfo.cc @@ -42,6 +42,7 @@ #include "message.h" #include "RecoverableException.h" #include "DNSCache.h" +#include extern volatile sig_atomic_t btHaltRequested; @@ -59,7 +60,7 @@ RequestInfos TorrentRequestInfo::execute() { btContext->load(torrentFile); if(op->get(PREF_SHOW_FILES) == V_TRUE) { - showFileEntry(btContext); + Util::toStream(cout, btContext->getFileEntries()); return RequestInfos(); } // set max_tries to 1. AnnounceList handles retries. @@ -120,19 +121,3 @@ RequestInfos TorrentRequestInfo::execute() { return RequestInfos(); } - -void TorrentRequestInfo::showFileEntry(const BtContextHandle& btContext) -{ - FileEntries fileEntries = btContext->getFileEntries(); - cout << _("Files:") << endl; - cout << "idx|path/length" << endl; - cout << "===+===========================================================================" << endl; - int count = 1; - for(FileEntries::const_iterator itr = fileEntries.begin(); - itr != fileEntries.end(); count++, itr++) { - printf("%3d|%s\n |%s Bytes\n", count, - (*itr)->getPath().c_str(), - Util::llitos((*itr)->getLength(), true).c_str()); - cout << "---+---------------------------------------------------------------------------" << endl; - } -} diff --git a/src/TorrentRequestInfo.h b/src/TorrentRequestInfo.h index e9c1774d..7b71d89b 100644 --- a/src/TorrentRequestInfo.h +++ b/src/TorrentRequestInfo.h @@ -44,7 +44,6 @@ private: string torrentFile; Strings targetFiles; - void showFileEntry(const BtContextHandle& btContext); public: TorrentRequestInfo(const string& torrentFile, Option* op): RequestInfo(op), diff --git a/src/Util.cc b/src/Util.cc index 1a48c9f9..9ff90376 100644 --- a/src/Util.cc +++ b/src/Util.cc @@ -47,6 +47,7 @@ #include #include #include +#include template @@ -705,8 +706,8 @@ string Util::abbrevSize(int64_t size) for(; i < numUnit-1 && size >= 1024; ++i) { r = size&0x3ff; size >>= 10; - } - return Util::llitos(size, true)+"."+Util::itos(r*10/1024)+units[i]; + } + return Util::llitos(size, true)+"."+Util::itos(r*10/1024)+units[i]+"i"; } time_t Util::httpGMT(const string& httpStdTime) @@ -717,3 +718,17 @@ time_t Util::httpGMT(const string& httpStdTime) time_t thetime = timegm(&tm); return thetime; } + +void Util::toStream(ostream& os, const FileEntries& fileEntries) +{ + os << _("Files:") << "\n"; + os << "idx|path/length" << "\n"; + os << "===+===========================================================================" << "\n"; + int count = 1; + for(FileEntries::const_iterator itr = fileEntries.begin(); + itr != fileEntries.end(); count++, itr++) { + os << setw(3) << count << "|" << (*itr)->getPath() << "\n"; + os << " |" << Util::llitos((*itr)->getLength(), true) << " bytes" << "\n"; + os << "---+---------------------------------------------------------------------------" << "\n"; + } +} diff --git a/src/Util.h b/src/Util.h index 7748dbfe..29b1962b 100644 --- a/src/Util.h +++ b/src/Util.h @@ -36,6 +36,7 @@ #define _D_UTIL_H_ #include "common.h" +#include "FileEntry.h" #ifdef ENABLE_MESSAGE_DIGEST #include "messageDigest.h" #endif // ENABLE_MESSAGE_DIGEST @@ -44,8 +45,7 @@ #include #include #include - -using namespace std; +#include #define STRTOLL(X) strtoll(X, (char**)NULL, 10); @@ -152,6 +152,8 @@ public: static string abbrevSize(int64_t size); static time_t httpGMT(const string& httpTimeFormat); + + static void toStream(ostream& os, const FileEntries& entries); }; #endif // _D_UTIL_H_ diff --git a/src/Xml2MetalinkProcessor.cc b/src/Xml2MetalinkProcessor.cc index 8289e551..7c754056 100644 --- a/src/Xml2MetalinkProcessor.cc +++ b/src/Xml2MetalinkProcessor.cc @@ -98,13 +98,15 @@ MetalinkEntryHandle Xml2MetalinkProcessor::getEntry(const string& xpath) { MetalinkEntryHandle entry(new MetalinkEntry()); - entry->filename = filename; + FileEntryHandle fileEntry = new FileEntry(filename, 0, 0); + string sizeStr = Util::trim(xpathContent(xpath+"/m:size")); if(sizeStr == "") { - entry->size = 0; + fileEntry->setLength(0); } else { - entry->size = STRTOLL(sizeStr.c_str()); + fileEntry->setLength(strtoll(sizeStr.c_str(), 0, 10)); } + entry->file = fileEntry; entry->version = Util::trim(xpathContent(xpath+"/m:version")); entry->language = Util::trim(xpathContent(xpath+"/m:language")); entry->os = Util::trim(xpathContent(xpath+"/m:os")); @@ -127,9 +129,9 @@ MetalinkEntryHandle Xml2MetalinkProcessor::getEntry(const string& xpath) { string sha1PiecesPath = piecesPath+"[@type=\"sha1\"]"; string md5PiecesPath = piecesPath+"[@type=\"md5\"]"; if(xpathExists(sha1PiecesPath)) { - entry->chunkChecksum = getPieceHash(sha1PiecesPath, entry->size); + entry->chunkChecksum = getPieceHash(sha1PiecesPath, entry->getLength()); } else if(xpathExists(md5PiecesPath)) { - entry->chunkChecksum = getPieceHash(md5PiecesPath, entry->size); + entry->chunkChecksum = getPieceHash(md5PiecesPath, entry->getLength()); } #endif // ENABLE_MESSAGE_DIGEST for(int index = 1; 1; index++) { diff --git a/src/main.cc b/src/main.cc index ef1e92c2..7fd9a940 100644 --- a/src/main.cc +++ b/src/main.cc @@ -37,7 +37,6 @@ #include "Util.h" #include "prefs.h" #include "FeatureConfig.h" -#include "UrlRequestInfo.h" #include "MultiUrlRequestInfo.h" #include "TorrentRequestInfo.h" #include "BitfieldManFactory.h" @@ -211,16 +210,28 @@ void showUsage() { " multiple URIs for a single entity: deliminate\n" " URIs by Tab in a single line.") << endl; cout << _(" -j, --max-concurrent-downloads=N Set maximum number of concurrent downloads.\n" + " It should be used with -i option.\n" " Default: 5") << endl; cout << _(" --load-cookies=FILE Load cookies from FILE. The format of FILE is\n" " one used by Netscape and Mozilla.") << endl; +#if defined ENABLE_BITTORRENT || ENABLE_METALINK + cout << _(" -S, --show-files Print file listing of .torrent or .metalink file\n" + " and exit.") << endl; + cout << _(" --select-file=INDEX... Set file to download by specifing its index.\n" + " You can know file index through --show-files\n" + " option. Multiple indexes can be specified by using\n" + " ',' like \"3,6\".\n" + " You can also use '-' to specify rangelike \"1-5\".\n" + " ',' and '-' can be used together.\n" + " When used with -M option, index may vary depending\n" + " on the query(see --metalink-* options).") << endl; +#endif // ENABLE_BITTORRENT || ENABLE_METALINK #ifdef ENABLE_BITTORRENT cout << _(" -T, --torrent-file=TORRENT_FILE The file path to .torrent file.") << endl; cout << _(" --follow-torrent=true|false Setting this option to false prevents aria2 to\n" " enter BitTorrent mode even if the filename of\n" " downloaded file ends with .torrent.\n" " Default: true") << endl; - cout << _(" -S, --show-files Print file listing of .torrent file and exit.") << endl; cout << _(" --direct-file-mapping=true|false Directly read from and write to each file\n" " mentioned in .torrent file.\n" " Default: true") << endl; @@ -230,12 +241,6 @@ void showUsage() { " 0 means unrestricted.\n" " You can append K or M(1K = 1024, 1M = 1024K).\n" " Default: 0") << endl; - cout << _(" --select-file=INDEX... Set file to download by specifing its index.\n" - " You can know file index through --show-files\n" - " option. Multiple indexes can be specified by using\n" - " ',' like \"3,6\".\n" - " You can also use '-' to specify rangelike \"1-5\".\n" - " ',' and '-' can be used together.") << endl; cout << _(" --seed-time=MINUTES Specify seeding time in minutes. See also\n" " --seed-ratio option.") << endl; cout << _(" --seed-ratio=RATIO Specify share ratio. Seed completed torrents until\n" @@ -405,16 +410,18 @@ int main(int argc, char* argv[]) { { "input-file", required_argument, 0, 'i' }, { "max-concurrent-downloads", required_argument, 0, 'j' }, { "load-cookies", required_argument, &lopt, 205 }, +#if defined ENABLE_BITTORRENT || ENABLE_METALINK + { "show-files", no_argument, NULL, 'S' }, + { "select-file", required_argument, &lopt, 21 }, +#endif // ENABLE_BITTORRENT || ENABLE_METALINK #ifdef ENABLE_BITTORRENT { "torrent-file", required_argument, NULL, 'T' }, { "listen-port", required_argument, &lopt, 15 }, { "follow-torrent", required_argument, &lopt, 16 }, - { "show-files", no_argument, NULL, 'S' }, { "no-preallocation", no_argument, &lopt, 18 }, { "direct-file-mapping", required_argument, &lopt, 19 }, // TODO remove upload-limit. //{ "upload-limit", required_argument, &lopt, 20 }, - { "select-file", required_argument, &lopt, 21 }, { "seed-time", required_argument, &lopt, 22 }, { "seed-ratio", required_argument, &lopt, 23 }, { "max-upload-limit", required_argument, &lopt, 24 }, @@ -709,7 +716,7 @@ int main(int argc, char* argv[]) { Util::setGlobalSignalHandler(SIGPIPE, SIG_IGN, 0); - RequestInfo* firstReqInfo = 0; + RequestInfo* firstReqInfo; #ifdef ENABLE_BITTORRENT if(op->defined(PREF_TORRENT_FILE)) { firstReqInfo = new TorrentRequestInfo(op->get(PREF_TORRENT_FILE), @@ -726,6 +733,11 @@ int main(int argc, char* argv[]) { if(op->defined(PREF_METALINK_FILE)) { firstReqInfo = new MetalinkRequestInfo(op->get(PREF_METALINK_FILE), op); + Strings targetFiles; + if(op->defined(PREF_METALINK_FILE) && !args.empty()) { + targetFiles = args; + } + ((MetalinkRequestInfo*)firstReqInfo)->setTargetFiles(targetFiles); } else #endif // ENABLE_METALINK