diff --git a/ChangeLog b/ChangeLog index 1b8486cb..e16cd29b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,23 @@ +2010-01-22 Tatsuhiro Tsujikawa + + aria2 now returns gzip compressed XML-RPC response if XML-RPC + client accepts gzip content encoding. + * src/A2STR.cc + * src/A2STR.h + * src/GZipEncoder.cc + * src/GZipEncoder.h + * src/HttpHeader.cc + * src/HttpHeader.h + * src/HttpServer.cc + * src/HttpServer.h + * src/HttpServerBodyCommand.cc + * src/HttpServerCommand.cc + * src/Makefile.am + * src/XmlRpcResponse.cc + * src/XmlRpcResponse.h + * test/GZipEncoderTest.cc + * test/Makefile.am + 2010-01-18 Tatsuhiro Tsujikawa Added XML-RPC client sample code in Python. diff --git a/src/A2STR.cc b/src/A2STR.cc index dbe3c238..bcd6d76f 100644 --- a/src/A2STR.cc +++ b/src/A2STR.cc @@ -60,4 +60,6 @@ const std::string A2STR::UNDERSCORE_C("_"); const std::string A2STR::BACK_SLASH_C("\\"); +const std::string A2STR::COMMA_C(","); + } // namespace aria2 diff --git a/src/A2STR.h b/src/A2STR.h index ebd00584..1eb94e98 100644 --- a/src/A2STR.h +++ b/src/A2STR.h @@ -66,6 +66,8 @@ public: static const std::string UNDERSCORE_C; static const std::string BACK_SLASH_C; + + static const std::string COMMA_C; }; } // namespace aria2 diff --git a/src/GZipEncoder.cc b/src/GZipEncoder.cc new file mode 100644 index 00000000..0f605b66 --- /dev/null +++ b/src/GZipEncoder.cc @@ -0,0 +1,145 @@ +/* */ +#include "GZipEncoder.h" + +#include + +#include "StringFormat.h" +#include "DlAbortEx.h" +#include "util.h" + +namespace aria2 { + +namespace { +const int OUTBUF_LENGTH = 4096; +} + +GZipEncoder::GZipEncoder():_strm(0), _finished(false) {} + +GZipEncoder::~GZipEncoder() +{ + release(); +} + +void GZipEncoder::init() +{ + _finished = false; + release(); + _strm = new z_stream(); + _strm->zalloc = Z_NULL; + _strm->zfree = Z_NULL; + _strm->opaque = Z_NULL; + _strm->avail_in = 0; + _strm->next_in = Z_NULL; + + if(Z_OK != deflateInit2(_strm, 9, Z_DEFLATED, 31, 9, Z_DEFAULT_STRATEGY)) { + throw DL_ABORT_EX("Initializing z_stream failed."); + } +} + +void GZipEncoder::release() +{ + if(_strm) { + deflateEnd(_strm); + delete _strm; + _strm = 0; + } +} + +std::string GZipEncoder::encode +(const unsigned char* in, size_t length, int flush) +{ + std::string out; + + _strm->avail_in = length; + _strm->next_in = const_cast(in); + + unsigned char outbuf[OUTBUF_LENGTH]; + while(1) { + _strm->avail_out = OUTBUF_LENGTH; + _strm->next_out = outbuf; + + int ret = ::deflate(_strm, flush); + + if(ret == Z_STREAM_END) { + _finished = true; + } else if(ret != Z_OK) { + throw DL_ABORT_EX(StringFormat("libz::deflate() failed. cause:%s", + _strm->msg).str()); + } + + size_t produced = OUTBUF_LENGTH-_strm->avail_out; + + out.append(&outbuf[0], &outbuf[produced]); + + if(_strm->avail_out > 0) { + break; + } + } + return out; +} + +bool GZipEncoder::finished() +{ + return _finished; +} + +std::string GZipEncoder::str() +{ + _internalBuf += encode(0, 0, Z_FINISH); + return _internalBuf; +} + +GZipEncoder& GZipEncoder::operator<<(const char* s) +{ + _internalBuf += encode(reinterpret_cast(s), strlen(s)); + return *this; +} + +GZipEncoder& GZipEncoder::operator<<(const std::string& s) +{ + _internalBuf += encode + (reinterpret_cast(s.data()), s.size()); + return *this; +} + +GZipEncoder& GZipEncoder::operator<<(int64_t i) +{ + std::string s = util::itos(i); + (*this) << s; + return *this; +} + +} // namespace aria2 diff --git a/src/GZipEncoder.h b/src/GZipEncoder.h new file mode 100644 index 00000000..4336b271 --- /dev/null +++ b/src/GZipEncoder.h @@ -0,0 +1,96 @@ +/* */ +#ifndef _D_GZIP_ENCODER_H_ +#define _D_GZIP_ENCODER_H_ + +#include + +#include + +namespace aria2 { + +class GZipEncoder { +private: + z_stream* _strm; + + bool _finished; + + // Internal buffer for deflated data. + std::string _internalBuf; + + std::string encode(const unsigned char* in, size_t length, int flush); +public: + GZipEncoder(); + + ~GZipEncoder(); + + // Initializes deflator. + void init(); + + // Feeds NULL-terminated c-string s to deflater. The deflated + // result is kept in this class. + GZipEncoder& operator<<(const char* s); + + // Feeds binary data in s to deflater. The deflated result is kept + // in this class. + GZipEncoder& operator<<(const std::string& s); + + // Feeds integer to deflator. Before passed to deflator, i is + // converted to std::string using util::itos(). The deflated result + // is kept in this class. + GZipEncoder& operator<<(int64_t i); + + // Feeds binary data pointed by in with size length to deflator and + // returns compressed output available so far. Don't use this + // method with operator<< methods. + std::string encode(const unsigned char* in, size_t length) + { + return encode(in, length, Z_NO_FLUSH); + } + + // Returns true if deflator finished. + bool finished(); + + // Releases allocated resources. + void release(); + + // Returns deflated result kept internally. After this function + // call, further calls to operator<<() and encode() are not allowed. + std::string str(); +}; + +} // namespace aria2 + +#endif // _D_GZIP_ENCODER_H_ diff --git a/src/HttpHeader.cc b/src/HttpHeader.cc index 17b042ff..635cca5c 100644 --- a/src/HttpHeader.cc +++ b/src/HttpHeader.cc @@ -72,6 +72,8 @@ const std::string HttpHeader::CONTENT_RANGE("Content-Range"); const std::string HttpHeader::LAST_MODIFIED("Last-Modified"); +const std::string HttpHeader::ACCEPT_ENCODING("Accept-Encoding"); + const std::string HttpHeader::HTTP_1_1("HTTP/1.1"); const std::string HttpHeader::S200("200"); diff --git a/src/HttpHeader.h b/src/HttpHeader.h index aff2b07c..1a42ff4b 100644 --- a/src/HttpHeader.h +++ b/src/HttpHeader.h @@ -140,6 +140,8 @@ public: static const std::string LAST_MODIFIED; + static const std::string ACCEPT_ENCODING; + static const std::string HTTP_1_1; static const std::string S200; diff --git a/src/HttpServer.cc b/src/HttpServer.cc index 12ad34a2..16efce3c 100644 --- a/src/HttpServer.cc +++ b/src/HttpServer.cc @@ -56,7 +56,10 @@ HttpServer::HttpServer(const SharedHandle& socket, _e(e), _headerProcessor(new HttpHeaderProcessor()), _logger(LogFactory::getInstance()), - _keepAlive(true) + _keepAlive(true), + _gzip(false), + _acceptsPersistentConnection(true), + _acceptsGZip(false) {} HttpServer::~HttpServer() {} @@ -88,8 +91,21 @@ SharedHandle HttpServer::receiveRequest() _lastContentLength = _lastRequestHeader->getFirstAsUInt(HttpHeader::CONTENT_LENGTH); _headerProcessor->clear(); - } + std::string connection = + util::toLower(_lastRequestHeader->getFirst(HttpHeader::CONNECTION)); + _acceptsPersistentConnection = + connection.find(HttpHeader::CLOSE) == std::string::npos && + (_lastRequestHeader->getVersion() == HttpHeader::HTTP_1_1 || + connection.find("keep-alive") != std::string::npos); + + std::vector acceptEncodings; + util::split(_lastRequestHeader->getFirst(HttpHeader::ACCEPT_ENCODING), + std::back_inserter(acceptEncodings), A2STR::COMMA_C, true); + _acceptsGZip = + std::find(acceptEncodings.begin(), acceptEncodings.end(), "gzip") + != acceptEncodings.end(); + } return header; } @@ -121,20 +137,6 @@ const std::string& HttpServer::getRequestPath() const return _lastRequestHeader->getRequestPath(); } -bool HttpServer::supportsPersistentConnection() const -{ - if(!_keepAlive) { - return false; - } - - std::string connection = - util::toLower(_lastRequestHeader->getFirst(HttpHeader::CONNECTION)); - - return connection.find(HttpHeader::CLOSE) == std::string::npos && - (_lastRequestHeader->getVersion() == HttpHeader::HTTP_1_1 || - connection.find("keep-alive") != std::string::npos); -} - void HttpServer::feedResponse(const std::string& text, const std::string& contentType) { feedResponse("200 OK", "", text, contentType); @@ -149,7 +151,9 @@ void HttpServer::feedResponse(const std::string& status, strappend(header, status, "\r\n", "Content-Type: ", contentType, "\r\n", "Content-Length: ", util::uitos(text.size()), "\r\n"); - + if(supportsGZip()) { + header += "Content-Encoding: gzip\r\n"; + } if(!supportsPersistentConnection()) { header += "Connection: close\r\n"; } diff --git a/src/HttpServer.h b/src/HttpServer.h index 8fc57386..604eb717 100644 --- a/src/HttpServer.h +++ b/src/HttpServer.h @@ -39,6 +39,7 @@ #include #include +#include #include "SharedHandle.h" #include "SocketBuffer.h" @@ -62,8 +63,11 @@ private: uint64_t _lastContentLength; std::stringstream _lastBody; bool _keepAlive; + bool _gzip; std::string _username; std::string _password; + bool _acceptsPersistentConnection; + bool _acceptsGZip; public: HttpServer(const SharedHandle& socket, DownloadEngine* e); @@ -97,12 +101,24 @@ public: bool sendBufferIsEmpty() const; - bool supportsPersistentConnection() const; + bool supportsPersistentConnection() const + { + return _keepAlive && _acceptsPersistentConnection; + } + + bool supportsGZip() const + { + return _gzip && _acceptsGZip; + } void enableKeepAlive() { _keepAlive = true; } void disableKeepAlive() { _keepAlive = false; } + void enableGZip() { _gzip = true; } + + void disableGZip() { _gzip = false; } + uint64_t getContentLength() const { return _lastContentLength; } }; diff --git a/src/HttpServerBodyCommand.cc b/src/HttpServerBodyCommand.cc index 07ac5d7a..25eeab47 100644 --- a/src/HttpServerBodyCommand.cc +++ b/src/HttpServerBodyCommand.cc @@ -90,7 +90,9 @@ bool HttpServerBodyCommand::execute() SharedHandle method = xmlrpc::XmlRpcMethodFactory::create(req._methodName); xmlrpc::XmlRpcResponse res = method->execute(req, _e); - _httpServer->feedResponse(res.toXml(), "text/xml"); + bool gzip = _httpServer->supportsGZip(); + std::string responseData = res.toXml(gzip); + _httpServer->feedResponse(responseData, "text/xml"); Command* command = new HttpServerResponseCommand(cuid, _httpServer, _e, _socket); _e->commands.push_back(command); diff --git a/src/HttpServerCommand.cc b/src/HttpServerCommand.cc index 03edd761..4a6bec49 100644 --- a/src/HttpServerCommand.cc +++ b/src/HttpServerCommand.cc @@ -61,6 +61,11 @@ HttpServerCommand::HttpServerCommand(int32_t cuid, DownloadEngine* e, _e->addSocketForReadCheck(_socket, this); _httpServer->setUsernamePassword(_e->option->get(PREF_XML_RPC_USER), _e->option->get(PREF_XML_RPC_PASSWD)); +#ifdef HAVE_LIBZ + _httpServer->enableGZip(); +#else // !HAVE_LIBZ + _httpServer->disableGZip(); +#endif // !HAVE_LIBZ } HttpServerCommand::HttpServerCommand(int32_t cuid, diff --git a/src/Makefile.am b/src/Makefile.am index 93868128..b49eb8c4 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -252,7 +252,8 @@ SRCS += LibsslTLSContext.cc LibsslTLSContext.h endif # HAVE_LIBSSL if HAVE_LIBZ -SRCS += GZipDecoder.cc GZipDecoder.h +SRCS += GZipDecoder.cc GZipDecoder.h\ + GZipEncoder.cc GZipEncoder.h endif # HAVE_LIBZ if HAVE_SQLITE3 diff --git a/src/Makefile.in b/src/Makefile.in index dd6ea663..8d1c9301 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -61,7 +61,9 @@ bin_PROGRAMS = aria2c$(EXEEXT) @ENABLE_SSL_TRUE@am__append_6 = TLSContext.h @HAVE_LIBGNUTLS_TRUE@am__append_7 = LibgnutlsTLSContext.cc LibgnutlsTLSContext.h @HAVE_LIBSSL_TRUE@am__append_8 = LibsslTLSContext.cc LibsslTLSContext.h -@HAVE_LIBZ_TRUE@am__append_9 = GZipDecoder.cc GZipDecoder.h +@HAVE_LIBZ_TRUE@am__append_9 = GZipDecoder.cc GZipDecoder.h\ +@HAVE_LIBZ_TRUE@ GZipEncoder.cc GZipEncoder.h + @HAVE_SQLITE3_TRUE@am__append_10 = Sqlite3MozCookieParser.cc Sqlite3MozCookieParser.h @ENABLE_ASYNC_DNS_TRUE@am__append_11 = AsyncNameResolver.cc AsyncNameResolver.h @ENABLE_MESSAGE_DIGEST_TRUE@am__append_12 = IteratableChunkChecksumValidator.cc IteratableChunkChecksumValidator.h\ @@ -441,9 +443,10 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \ EpollEventPoll.cc EpollEventPoll.h TLSContext.h \ LibgnutlsTLSContext.cc LibgnutlsTLSContext.h \ LibsslTLSContext.cc LibsslTLSContext.h GZipDecoder.cc \ - GZipDecoder.h Sqlite3MozCookieParser.cc \ - Sqlite3MozCookieParser.h AsyncNameResolver.cc \ - AsyncNameResolver.h IteratableChunkChecksumValidator.cc \ + GZipDecoder.h GZipEncoder.cc GZipEncoder.h \ + Sqlite3MozCookieParser.cc Sqlite3MozCookieParser.h \ + AsyncNameResolver.cc AsyncNameResolver.h \ + IteratableChunkChecksumValidator.cc \ IteratableChunkChecksumValidator.h \ IteratableChecksumValidator.cc IteratableChecksumValidator.h \ CheckIntegrityDispatcherCommand.cc \ @@ -607,7 +610,8 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \ am__objects_6 = @HAVE_LIBGNUTLS_TRUE@am__objects_7 = LibgnutlsTLSContext.$(OBJEXT) @HAVE_LIBSSL_TRUE@am__objects_8 = LibsslTLSContext.$(OBJEXT) -@HAVE_LIBZ_TRUE@am__objects_9 = GZipDecoder.$(OBJEXT) +@HAVE_LIBZ_TRUE@am__objects_9 = GZipDecoder.$(OBJEXT) \ +@HAVE_LIBZ_TRUE@ GZipEncoder.$(OBJEXT) @HAVE_SQLITE3_TRUE@am__objects_10 = Sqlite3MozCookieParser.$(OBJEXT) @ENABLE_ASYNC_DNS_TRUE@am__objects_11 = AsyncNameResolver.$(OBJEXT) @ENABLE_MESSAGE_DIGEST_TRUE@am__objects_12 = IteratableChunkChecksumValidator.$(OBJEXT) \ @@ -1437,6 +1441,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FtpTunnelRequestCommand.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FtpTunnelResponseCommand.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/GZipDecoder.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/GZipEncoder.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/GrowSegment.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HandshakeExtensionMessage.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HaveEraseCommand.Po@am__quote@ diff --git a/src/XmlRpcResponse.cc b/src/XmlRpcResponse.cc index b37247fb..94e80384 100644 --- a/src/XmlRpcResponse.cc +++ b/src/XmlRpcResponse.cc @@ -38,16 +38,20 @@ #include #include "util.h" +#ifdef HAVE_LIBZ +# include "GZipEncoder.h" +#endif // HAVE_LIBZ namespace aria2 { namespace xmlrpc { -static void encodeValue(const BDE& value, std::ostream& o); +template +static void encodeValue(const BDE& value, OutputStream& o); -template +template static void encodeArray -(InputIterator first, InputIterator last, std::ostream& o) +(InputIterator first, InputIterator last, OutputStream& o) { o << "" << ""; for(; first != last; ++first) { @@ -56,9 +60,9 @@ static void encodeArray o << "" << ""; } -template +template static void encodeStruct -(InputIterator first, InputIterator last, std::ostream& o) +(InputIterator first, InputIterator last, OutputStream& o) { o << ""; for(; first != last; ++first) { @@ -70,7 +74,8 @@ static void encodeStruct o << ""; } -static void encodeValue(const BDE& value, std::ostream& o) +template +static void encodeValue(const BDE& value, OutputStream& o) { o << ""; if(value.isString()) { @@ -85,23 +90,39 @@ static void encodeValue(const BDE& value, std::ostream& o) o << ""; } -std::string XmlRpcResponse::toXml() const +template +std::string encodeAll(OutputStream& o, int code, const BDE& param) { - std::stringstream o; o << "" << ""; - if(_code == 0) { + if(code == 0) { o << "" << ""; - encodeValue(_param, o); + encodeValue(param, o); o << "" << ""; } else { o << ""; - encodeValue(_param, o); + encodeValue(param, o); o << ""; } o << ""; return o.str(); } +std::string XmlRpcResponse::toXml(bool gzip) const +{ + if(gzip) { +#ifdef HAVE_LIBZ + GZipEncoder o; + o.init(); + return encodeAll(o, _code, _param); +#else // !HAVE_LIBZ + abort(); +#endif // !HAVE_LIBZ + } else { + std::stringstream o; + return encodeAll(o, _code, _param); + } +} + } // namespace xmlrpc } // namespace aria2 diff --git a/src/XmlRpcResponse.h b/src/XmlRpcResponse.h index bcbe46a2..384d9910 100644 --- a/src/XmlRpcResponse.h +++ b/src/XmlRpcResponse.h @@ -53,7 +53,7 @@ struct XmlRpcResponse { XmlRpcResponse(int code, const BDE& param):_code(code), _param(param) {} - std::string toXml() const; + std::string toXml(bool gzip = false) const; }; } // namespace xmlrpc diff --git a/test/GZipEncoderTest.cc b/test/GZipEncoderTest.cc new file mode 100644 index 00000000..8322d4a1 --- /dev/null +++ b/test/GZipEncoderTest.cc @@ -0,0 +1,48 @@ +#include "GZipEncoder.h" + +#include + +#include "GZipDecoder.h" +#include "util.h" + +namespace aria2 { + +class GZipEncoderTest:public CppUnit::TestFixture { + + CPPUNIT_TEST_SUITE(GZipEncoderTest); + CPPUNIT_TEST(testEncode); + CPPUNIT_TEST_SUITE_END(); +public: + void testEncode(); +}; + + +CPPUNIT_TEST_SUITE_REGISTRATION(GZipEncoderTest); + +void GZipEncoderTest::testEncode() +{ + GZipEncoder encoder; + encoder.init(); + + std::vector inputs; + inputs.push_back("Hello World"); + inputs.push_back("9223372036854775807"); + inputs.push_back("Fox"); + + encoder << inputs[0]; + encoder << util::parseLLInt(inputs[1]); + encoder << inputs[2].c_str(); + + std::string gzippedData = encoder.str(); + + GZipDecoder decoder; + decoder.init(); + std::string gunzippedData = + decoder.decode(reinterpret_cast(gzippedData.data()), + gzippedData.size()); + CPPUNIT_ASSERT(decoder.finished()); + CPPUNIT_ASSERT_EQUAL(strjoin(inputs.begin(), inputs.end(), ""), + gunzippedData); +} + +} // namespace aria2 diff --git a/test/Makefile.am b/test/Makefile.am index 1741a2ed..0e684b78 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -84,7 +84,8 @@ aria2c_SOURCES += FallocFileAllocationIteratorTest.cc endif # HAVE_POSIX_FALLOCATE if HAVE_LIBZ -aria2c_SOURCES += GZipDecoderTest.cc +aria2c_SOURCES += GZipDecoderTest.cc\ + GZipEncoderTest.cc endif # HAVE_LIBZ if HAVE_SQLITE3 diff --git a/test/Makefile.in b/test/Makefile.in index efdd05ad..e6986c30 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -41,7 +41,9 @@ check_PROGRAMS = $(am__EXEEXT_1) @ENABLE_XML_RPC_TRUE@ XmlRpcMethodTest.cc @HAVE_POSIX_FALLOCATE_TRUE@am__append_2 = FallocFileAllocationIteratorTest.cc -@HAVE_LIBZ_TRUE@am__append_3 = GZipDecoderTest.cc +@HAVE_LIBZ_TRUE@am__append_3 = GZipDecoderTest.cc\ +@HAVE_LIBZ_TRUE@ GZipEncoderTest.cc + @HAVE_SQLITE3_TRUE@am__append_4 = Sqlite3MozCookieParserTest.cc @ENABLE_MESSAGE_DIGEST_TRUE@am__append_5 = MessageDigestHelperTest.cc\ @ENABLE_MESSAGE_DIGEST_TRUE@ IteratableChunkChecksumValidatorTest.cc\ @@ -212,7 +214,8 @@ am__aria2c_SOURCES_DIST = AllTest.cc TestUtil.cc TestUtil.h \ DownloadContextTest.cc XmlRpcRequestParserControllerTest.cc \ XmlRpcRequestProcessorTest.cc XmlRpcMethodTest.cc \ FallocFileAllocationIteratorTest.cc GZipDecoderTest.cc \ - Sqlite3MozCookieParserTest.cc MessageDigestHelperTest.cc \ + GZipEncoderTest.cc Sqlite3MozCookieParserTest.cc \ + MessageDigestHelperTest.cc \ IteratableChunkChecksumValidatorTest.cc \ IteratableChecksumValidatorTest.cc BtAllowedFastMessageTest.cc \ BtBitfieldMessageTest.cc BtCancelMessageTest.cc \ @@ -271,7 +274,8 @@ am__aria2c_SOURCES_DIST = AllTest.cc TestUtil.cc TestUtil.h \ @ENABLE_XML_RPC_TRUE@ XmlRpcRequestProcessorTest.$(OBJEXT) \ @ENABLE_XML_RPC_TRUE@ XmlRpcMethodTest.$(OBJEXT) @HAVE_POSIX_FALLOCATE_TRUE@am__objects_2 = FallocFileAllocationIteratorTest.$(OBJEXT) -@HAVE_LIBZ_TRUE@am__objects_3 = GZipDecoderTest.$(OBJEXT) +@HAVE_LIBZ_TRUE@am__objects_3 = GZipDecoderTest.$(OBJEXT) \ +@HAVE_LIBZ_TRUE@ GZipEncoderTest.$(OBJEXT) @HAVE_SQLITE3_TRUE@am__objects_4 = \ @HAVE_SQLITE3_TRUE@ Sqlite3MozCookieParserTest.$(OBJEXT) @ENABLE_MESSAGE_DIGEST_TRUE@am__objects_5 = \ @@ -810,6 +814,7 @@ distclean-compile: @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)/GZipEncoderTest.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@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HttpHeaderProcessorTest.Po@am__quote@