mirror of https://github.com/aria2/aria2
				
				
				
			2008-11-27 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
Fixed the bug that prevents aria2 from downloading 0-length files via HTTP/FTP. * src/DefaultBtContext.cc * src/DefaultBtContext.h * src/DownloadContext.h * src/FtpNegotiationCommand.cc * src/HttpResponseCommand.cc * src/HttpResponseCommand.h * src/RequestGroup.cc * src/SingleFileDownloadContext.cc * src/SingleFileDownloadContext.h * test/BtPostDownloadHandlerTest.cc * test/MetalinkPostDownloadHandlerTest.cc * test/MockBtContext.hpull/1/head
							parent
							
								
									b1eee48ee3
								
							
						
					
					
						commit
						b1edad42ff
					
				
							
								
								
									
										17
									
								
								ChangeLog
								
								
								
								
							
							
						
						
									
										17
									
								
								ChangeLog
								
								
								
								
							|  | @ -1,3 +1,20 @@ | |||
| 2008-11-27  Tatsuhiro Tsujikawa  <t-tujikawa@users.sourceforge.net> | ||||
| 
 | ||||
| 	Fixed the bug that prevents aria2 from downloading 0-length files | ||||
| 	via HTTP/FTP. | ||||
| 	* src/DefaultBtContext.cc | ||||
| 	* src/DefaultBtContext.h | ||||
| 	* src/DownloadContext.h | ||||
| 	* src/FtpNegotiationCommand.cc | ||||
| 	* src/HttpResponseCommand.cc | ||||
| 	* src/HttpResponseCommand.h | ||||
| 	* src/RequestGroup.cc | ||||
| 	* src/SingleFileDownloadContext.cc | ||||
| 	* src/SingleFileDownloadContext.h | ||||
| 	* test/BtPostDownloadHandlerTest.cc | ||||
| 	* test/MetalinkPostDownloadHandlerTest.cc | ||||
| 	* test/MockBtContext.h | ||||
| 
 | ||||
| 2008-11-26  Tatsuhiro Tsujikawa  <t-tujikawa@users.sourceforge.net> | ||||
| 
 | ||||
| 	Fixed the bug that -pfalse and -ptrue are not recognized properly. | ||||
|  |  | |||
|  | @ -391,6 +391,11 @@ uint64_t DefaultBtContext::getTotalLength() const { | |||
|   return totalLength; | ||||
| } | ||||
| 
 | ||||
| bool DefaultBtContext::knowsTotalLength() const | ||||
| { | ||||
|   return true; | ||||
| } | ||||
| 
 | ||||
| BtContext::FILE_MODE DefaultBtContext::getFileMode() const { | ||||
|   return fileMode; | ||||
| } | ||||
|  |  | |||
|  | @ -110,6 +110,8 @@ private: | |||
| 
 | ||||
|   virtual uint64_t getTotalLength() const; | ||||
| 
 | ||||
|   virtual bool knowsTotalLength() const; | ||||
| 
 | ||||
|   virtual FILE_MODE getFileMode() const; | ||||
| 
 | ||||
|   virtual std::deque<SharedHandle<FileEntry> > getFileEntries() const; | ||||
|  |  | |||
|  | @ -75,6 +75,8 @@ public: | |||
| 
 | ||||
|   virtual uint64_t getTotalLength() const = 0; | ||||
| 
 | ||||
|   virtual bool knowsTotalLength() const = 0; | ||||
| 
 | ||||
|   virtual FILE_MODE getFileMode() const = 0; | ||||
| 
 | ||||
|   virtual std::deque<SharedHandle<FileEntry> > getFileEntries() const = 0; | ||||
|  |  | |||
|  | @ -333,10 +333,29 @@ bool FtpNegotiationCommand::onFileSizeDetermined(uint64_t totalLength) | |||
|   } | ||||
|   if(totalLength == 0) { | ||||
| 
 | ||||
|     if(e->option->getAsBool(PREF_FTP_PASV)) { | ||||
|       sequence = SEQ_SEND_PASV; | ||||
|     } else { | ||||
|       sequence = SEQ_PREPARE_SERVER_SOCKET; | ||||
|     } | ||||
|     _requestGroup->initPieceStorage(); | ||||
|     if(dctx->knowsTotalLength() && | ||||
|        _requestGroup->downloadFinishedByFileLength()) { | ||||
|       sequence = SEQ_DOWNLOAD_ALREADY_COMPLETED; | ||||
| 
 | ||||
|       poolConnection(); | ||||
| 
 | ||||
|       return false; | ||||
|     } | ||||
|     _requestGroup->shouldCancelDownloadForSafety(); | ||||
|     _requestGroup->getPieceStorage()->getDiskAdaptor()->initAndOpenFile(); | ||||
| 
 | ||||
|     if(dctx->knowsTotalLength()) { | ||||
|       sequence = SEQ_DOWNLOAD_ALREADY_COMPLETED; | ||||
|       poolConnection(); | ||||
|       return false; | ||||
|     } | ||||
| 
 | ||||
|     return true; | ||||
|   } else { | ||||
|     _requestGroup->initPieceStorage(); | ||||
|  | @ -387,12 +406,10 @@ bool FtpNegotiationCommand::recvSize() { | |||
|     // command, resuming and segmented downloading are disabled when the first
 | ||||
|     // contacted FTP server doesn't support it.
 | ||||
|     if(_requestGroup->getPieceStorage().isNull()) { | ||||
| 
 | ||||
|       if(e->option->getAsBool(PREF_FTP_PASV)) { | ||||
| 	sequence = SEQ_SEND_PASV; | ||||
|       } else { | ||||
| 	sequence = SEQ_PREPARE_SERVER_SOCKET; | ||||
|       } | ||||
|       SingleFileDownloadContextHandle dctx = | ||||
| 	dynamic_pointer_cast<SingleFileDownloadContext> | ||||
| 	(_requestGroup->getDownloadContext()); | ||||
|       dctx->markTotalLengthIsUnknown(); | ||||
|       return onFileSizeDetermined(0); | ||||
| 
 | ||||
|     } | ||||
|  |  | |||
|  | @ -140,6 +140,11 @@ bool HttpResponseCommand::executeInternal() | |||
|        shouldInflateContentEncoding(httpResponse)) { | ||||
|       // we ignore content-length when transfer-encoding is set
 | ||||
|       dctx->setTotalLength(0); | ||||
|       if(req->getMethod() == Request::METHOD_GET && | ||||
| 	 (totalLength != 0 || | ||||
| 	  !httpResponse->getHttpHeader()->defined(HttpHeader::CONTENT_LENGTH))){ | ||||
| 	dctx->markTotalLengthIsUnknown(); | ||||
|       } | ||||
|       return handleOtherEncoding(httpResponse); | ||||
|     } else { | ||||
|       return handleDefaultEncoding(httpResponse); | ||||
|  | @ -213,9 +218,7 @@ bool HttpResponseCommand::handleDefaultEncoding(const HttpResponseHandle& httpRe | |||
|     } | ||||
|     prepareForNextAction(command); | ||||
|     if(req->getMethod() == Request::METHOD_HEAD) { | ||||
|       if(req->supportsPersistentConnection()) { | ||||
| 	e->poolSocket(req, isProxyDefined(), socket); | ||||
|       } | ||||
|       poolConnection(); | ||||
|       req->setMethod(Request::METHOD_GET); | ||||
|     } | ||||
|   } catch(Exception& e) { | ||||
|  | @ -261,17 +264,30 @@ static SharedHandle<Decoder> getContentEncodingDecoder | |||
| } | ||||
| 
 | ||||
| bool HttpResponseCommand::handleOtherEncoding(const HttpResponseHandle& httpResponse) { | ||||
|   // We assume that RequestGroup::getTotalLength() == 0 here
 | ||||
|   HttpRequestHandle httpRequest = httpResponse->getHttpRequest(); | ||||
|   if(req->getMethod() == Request::METHOD_HEAD) { | ||||
|     if(req->supportsPersistentConnection()) { | ||||
|       e->poolSocket(req, isProxyDefined(), socket); | ||||
|     } | ||||
|     poolConnection(); | ||||
|     req->setMethod(Request::METHOD_GET); | ||||
|     return prepareForRetry(0); | ||||
|   } | ||||
|   _requestGroup->initPieceStorage(); | ||||
| 
 | ||||
|   // For zero-length file, check existing file comparing its size
 | ||||
|   if(_requestGroup->getDownloadContext()->knowsTotalLength() && | ||||
|      _requestGroup->downloadFinishedByFileLength()) { | ||||
|     poolConnection(); | ||||
|     return true; | ||||
|   } | ||||
| 
 | ||||
|   _requestGroup->shouldCancelDownloadForSafety(); | ||||
|   _requestGroup->getPieceStorage()->getDiskAdaptor()->initAndOpenFile(); | ||||
| 
 | ||||
|   if(_requestGroup->getDownloadContext()->knowsTotalLength()) { | ||||
|     poolConnection(); | ||||
|     return true; | ||||
|   } | ||||
| 
 | ||||
|   e->commands.push_back | ||||
|     (createHttpDownloadCommand(httpResponse, | ||||
| 			       getTransferEncodingDecoder(httpResponse), | ||||
|  | @ -332,4 +348,11 @@ HttpDownloadCommand* HttpResponseCommand::createHttpDownloadCommand | |||
|   return command; | ||||
| } | ||||
| 
 | ||||
| void HttpResponseCommand::poolConnection() | ||||
| { | ||||
|   if(req->supportsPersistentConnection()) { | ||||
|     e->poolSocket(req, isProxyDefined(), socket); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| } // namespace aria2
 | ||||
|  |  | |||
|  | @ -62,6 +62,8 @@ private: | |||
| 			    = SharedHandle<Decoder>()); | ||||
| 
 | ||||
|   void updateLastModifiedTime(const Time& lastModified); | ||||
| 
 | ||||
|   void poolConnection(); | ||||
| protected: | ||||
|   bool executeInternal(); | ||||
| 
 | ||||
|  |  | |||
|  | @ -347,14 +347,16 @@ void RequestGroup::processCheckIntegrityEntry(std::deque<Command*>& commands, | |||
| 
 | ||||
| void RequestGroup::initPieceStorage() | ||||
| { | ||||
|   if(_downloadContext->getTotalLength() == 0) { | ||||
|     UnknownLengthPieceStorageHandle ps(new UnknownLengthPieceStorage(_downloadContext, _option)); | ||||
|   if(_downloadContext->knowsTotalLength()) { | ||||
|     DefaultPieceStorageHandle ps | ||||
|       (new DefaultPieceStorage(_downloadContext, _option)); | ||||
|     if(!_diskWriterFactory.isNull()) { | ||||
|       ps->setDiskWriterFactory(_diskWriterFactory); | ||||
|     } | ||||
|     _pieceStorage = ps; | ||||
|   } else { | ||||
|     DefaultPieceStorageHandle ps(new DefaultPieceStorage(_downloadContext, _option)); | ||||
|     UnknownLengthPieceStorageHandle ps | ||||
|       (new UnknownLengthPieceStorage(_downloadContext, _option)); | ||||
|     if(!_diskWriterFactory.isNull()) { | ||||
|       ps->setDiskWriterFactory(_diskWriterFactory); | ||||
|     } | ||||
|  |  | |||
|  | @ -46,7 +46,8 @@ SingleFileDownloadContext::SingleFileDownloadContext(size_t pieceLength, | |||
|   _pieceLength(pieceLength), | ||||
|   _fileEntry(new FileEntry(filename, totalLength, 0)), | ||||
|   _filename(filename), | ||||
|   _ufilename(ufilename) | ||||
|   _ufilename(ufilename), | ||||
|   _knowsTotalLength(true) | ||||
| { | ||||
|   updateFileEntry(); | ||||
| } | ||||
|  | @ -73,6 +74,11 @@ uint64_t SingleFileDownloadContext::getTotalLength() const | |||
|   return _fileEntry->getLength(); | ||||
| } | ||||
| 
 | ||||
| bool SingleFileDownloadContext::knowsTotalLength() const | ||||
| { | ||||
|   return _knowsTotalLength; | ||||
| } | ||||
| 
 | ||||
| FileEntries | ||||
| SingleFileDownloadContext::getFileEntries() const | ||||
| { | ||||
|  | @ -96,6 +102,11 @@ void SingleFileDownloadContext::setTotalLength(uint64_t totalLength) | |||
|   _fileEntry->setLength(totalLength); | ||||
| } | ||||
| 
 | ||||
| void SingleFileDownloadContext::markTotalLengthIsUnknown() | ||||
| { | ||||
|   _knowsTotalLength = false; | ||||
| } | ||||
| 
 | ||||
| const std::string& SingleFileDownloadContext::getName() const | ||||
| { | ||||
|   return _fileEntry->getPath(); | ||||
|  |  | |||
|  | @ -66,6 +66,8 @@ private: | |||
|   std::string _checksum; | ||||
|   std::string _checksumHashAlgo; | ||||
| 
 | ||||
|   bool _knowsTotalLength; | ||||
| 
 | ||||
|   void updateFileEntry(); | ||||
| public: | ||||
|   SingleFileDownloadContext(size_t pieceLength, | ||||
|  | @ -88,6 +90,9 @@ public: | |||
| 
 | ||||
|   virtual uint64_t getTotalLength() const; | ||||
| 
 | ||||
|   virtual bool knowsTotalLength() const; | ||||
| 
 | ||||
| 
 | ||||
|   virtual FILE_MODE getFileMode() const | ||||
|   { | ||||
|     return SINGLE; | ||||
|  | @ -150,6 +155,8 @@ public: | |||
| 
 | ||||
|   void setTotalLength(uint64_t totalLength); | ||||
| 
 | ||||
|   void markTotalLengthIsUnknown(); | ||||
| 
 | ||||
|   void setPieceHashAlgo(const std::string& algo) | ||||
|   { | ||||
|     _pieceHashAlgo = algo; | ||||
|  |  | |||
|  | @ -65,7 +65,7 @@ void BtPostDownloadHandlerTest::testGetNextRequestGroups() | |||
| { | ||||
|   Option op; | ||||
|   SharedHandle<SingleFileDownloadContext> dctx | ||||
|     (new SingleFileDownloadContext(0, 0, "test.torrent")); | ||||
|     (new SingleFileDownloadContext(1024, 0, "test.torrent")); | ||||
|   RequestGroup rg(&op, std::deque<std::string>()); | ||||
|   rg.setDownloadContext(dctx); | ||||
|   rg.initPieceStorage(); | ||||
|  |  | |||
|  | @ -64,7 +64,7 @@ void MetalinkPostDownloadHandlerTest::testGetNextRequestGroups() | |||
| { | ||||
|   Option op; | ||||
|   SharedHandle<SingleFileDownloadContext> dctx | ||||
|     (new SingleFileDownloadContext(0, 0, "test.xml")); | ||||
|     (new SingleFileDownloadContext(1024, 0, "test.xml")); | ||||
|   RequestGroup rg(&op, std::deque<std::string>()); | ||||
|   rg.setDownloadContext(dctx); | ||||
|   rg.initPieceStorage(); | ||||
|  |  | |||
|  | @ -64,6 +64,11 @@ public: | |||
|     return totalLength; | ||||
|   } | ||||
| 
 | ||||
|   virtual bool knowsTotalLength() const | ||||
|   { | ||||
|     return true; | ||||
|   } | ||||
| 
 | ||||
|   void setTotalLength(uint64_t length) { | ||||
|     this->totalLength = length; | ||||
|   } | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Tatsuhiro Tsujikawa
						Tatsuhiro Tsujikawa