2008-09-02 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>

Made files whose name ends with ".gz", ".tgz" not inflated by 
Content
	Encoding Decoder. Removed size threshold for turning off on the 
fly
	inflation because resulting file may or may not be inflated 
depending
	on the file size and I think it is not expected by users.
	This change fixes segmentation fault when Metalink file contains 
gzipped
	file and its filesize is provided.
	* src/HttpResponseCommand.cc
	* src/HttpResponseCommand.h
pull/1/head
Tatsuhiro Tsujikawa 2008-09-01 15:06:29 +00:00
parent 6779c72b5d
commit d4215a82b7
3 changed files with 49 additions and 28 deletions

View File

@ -1,3 +1,14 @@
2008-09-02 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
Made files whose name ends with ".gz", ".tgz" not inflated by Content
Encoding Decoder. Removed size threshold for turning off on the fly
inflation because resulting file may or may not be inflated depending
on the file size and I think it is not expected by users.
This change fixes segmentation fault when Metalink file contains gzipped
file and its filesize is provided.
* src/HttpResponseCommand.cc
* src/HttpResponseCommand.h
2008-09-01 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com> 2008-09-01 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
Made Cookie immutable. Made Cookie immutable.

View File

@ -61,7 +61,6 @@
#include "StringFormat.h" #include "StringFormat.h"
#include "HttpSkipResponseCommand.h" #include "HttpSkipResponseCommand.h"
#include "HttpHeader.h" #include "HttpHeader.h"
#include "Decoder.h"
#include "LogFactory.h" #include "LogFactory.h"
#include "CookieStorage.h" #include "CookieStorage.h"
@ -137,6 +136,13 @@ bool HttpResponseCommand::executeInternal()
} }
} }
static bool fileIsGzipped(const SharedHandle<HttpResponse>& httpResponse)
{
std::string filename =
Util::toLower(httpResponse->getHttpRequest()->getRequest()->getFile());
return Util::endsWith(filename, ".gz") || Util::endsWith(filename, ".tgz");
}
bool HttpResponseCommand::shouldInflateContentEncoding bool HttpResponseCommand::shouldInflateContentEncoding
(const SharedHandle<HttpResponse>& httpResponse) (const SharedHandle<HttpResponse>& httpResponse)
{ {
@ -144,14 +150,11 @@ bool HttpResponseCommand::shouldInflateContentEncoding
// because in each segment we don't know where the date should be written. // because in each segment we don't know where the date should be written.
// So turn off segmented downloading. // So turn off segmented downloading.
// Meanwhile, Some server returns content-encoding: gzip for .tgz files. // Meanwhile, Some server returns content-encoding: gzip for .tgz files.
// Those files tend to be large enough to speed up using segmented // I think those files should not be inflated by clients, because it is the
// downloading. Therefore, I choose threshold size to determine on the fly // original format of those files. So I made filename ending ".gz" or ".tgz"
// inflation should be done. I expect gzipped content such as metalink xml // (case-insensitive) not inflated.
// files tend to be smaller than the threshold size, those contents are
// inflated on the fly properly.
return httpResponse->isContentEncodingSpecified() && return httpResponse->isContentEncodingSpecified() &&
httpResponse->getEntityLength() <= !fileIsGzipped(httpResponse);
static_cast<uint64_t>(e->option->getAsInt(PREF_SEGMENT_SIZE));
} }
bool HttpResponseCommand::handleDefaultEncoding(const HttpResponseHandle& httpResponse) bool HttpResponseCommand::handleDefaultEncoding(const HttpResponseHandle& httpResponse)
@ -195,19 +198,6 @@ bool HttpResponseCommand::handleDefaultEncoding(const HttpResponseHandle& httpRe
return true; return true;
} }
bool HttpResponseCommand::handleOtherEncoding(const HttpResponseHandle& httpResponse) {
HttpRequestHandle httpRequest = httpResponse->getHttpRequest();
// quick hack for method 'head',, is it necessary?
if(httpRequest->getMethod() == Request::METHOD_HEAD) {
return true;
}
_requestGroup->initPieceStorage();
_requestGroup->shouldCancelDownloadForSafety();
_requestGroup->getPieceStorage()->getDiskAdaptor()->initAndOpenFile();
e->commands.push_back(createHttpDownloadCommand(httpResponse));
return true;
}
static SharedHandle<Decoder> getTransferEncodingDecoder static SharedHandle<Decoder> getTransferEncodingDecoder
(const SharedHandle<HttpResponse>& httpResponse) (const SharedHandle<HttpResponse>& httpResponse)
{ {
@ -243,6 +233,22 @@ static SharedHandle<Decoder> getContentEncodingDecoder
return decoder; return decoder;
} }
bool HttpResponseCommand::handleOtherEncoding(const HttpResponseHandle& httpResponse) {
HttpRequestHandle httpRequest = httpResponse->getHttpRequest();
// quick hack for method 'head',, is it necessary?
if(httpRequest->getMethod() == Request::METHOD_HEAD) {
return true;
}
_requestGroup->initPieceStorage();
_requestGroup->shouldCancelDownloadForSafety();
_requestGroup->getPieceStorage()->getDiskAdaptor()->initAndOpenFile();
e->commands.push_back
(createHttpDownloadCommand(httpResponse,
getTransferEncodingDecoder(httpResponse),
getContentEncodingDecoder(httpResponse)));
return true;
}
bool HttpResponseCommand::skipResponseBody bool HttpResponseCommand::skipResponseBody
(const SharedHandle<HttpResponse>& httpResponse) (const SharedHandle<HttpResponse>& httpResponse)
{ {
@ -267,12 +273,10 @@ bool HttpResponseCommand::skipResponseBody
} }
HttpDownloadCommand* HttpResponseCommand::createHttpDownloadCommand HttpDownloadCommand* HttpResponseCommand::createHttpDownloadCommand
(const HttpResponseHandle& httpResponse) (const HttpResponseHandle& httpResponse,
const SharedHandle<Decoder>& transferEncodingDecoder,
const SharedHandle<Decoder>& contentEncodingDecoder)
{ {
SharedHandle<Decoder> transferEncodingDecoder =
getTransferEncodingDecoder(httpResponse);
SharedHandle<Decoder> contentEncodingDecoder =
getContentEncodingDecoder(httpResponse);
HttpDownloadCommand* command = HttpDownloadCommand* command =
new HttpDownloadCommand(cuid, req, _requestGroup, httpConnection, e, new HttpDownloadCommand(cuid, req, _requestGroup, httpConnection, e,
@ -284,7 +288,7 @@ HttpDownloadCommand* HttpResponseCommand::createHttpDownloadCommand
(e->option->getAsInt(PREF_LOWEST_SPEED_LIMIT)); (e->option->getAsInt(PREF_LOWEST_SPEED_LIMIT));
command->setTransferEncodingDecoder(transferEncodingDecoder); command->setTransferEncodingDecoder(transferEncodingDecoder);
if(shouldInflateContentEncoding(httpResponse)) { if(!contentEncodingDecoder.isNull()) {
command->setContentEncodingDecoder(contentEncodingDecoder); command->setContentEncodingDecoder(contentEncodingDecoder);
// Since the compressed file's length are returned in the response header // Since the compressed file's length are returned in the response header
// and the decompressed file size is unknown at this point, disable file // and the decompressed file size is unknown at this point, disable file

View File

@ -36,6 +36,7 @@
#define _D_HTTP_RESPONSE_COMMAND_H_ #define _D_HTTP_RESPONSE_COMMAND_H_
#include "AbstractCommand.h" #include "AbstractCommand.h"
#include "Decoder.h"
namespace aria2 { namespace aria2 {
@ -52,7 +53,12 @@ private:
bool handleOtherEncoding(const SharedHandle<HttpResponse>& httpResponse); bool handleOtherEncoding(const SharedHandle<HttpResponse>& httpResponse);
bool skipResponseBody(const SharedHandle<HttpResponse>& httpResponse); bool skipResponseBody(const SharedHandle<HttpResponse>& httpResponse);
HttpDownloadCommand* createHttpDownloadCommand(const SharedHandle<HttpResponse>& httpResponse); HttpDownloadCommand*
createHttpDownloadCommand(const SharedHandle<HttpResponse>& httpResponse,
const SharedHandle<Decoder>& transferEncodingDecoder
= SharedHandle<Decoder>(),
const SharedHandle<Decoder>& contentEncodingDecoder
= SharedHandle<Decoder>());
protected: protected:
bool executeInternal(); bool executeInternal();