From d791807addd686660fd75d721b3cb0cf14d52f67 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Sun, 29 Jun 2008 14:29:36 +0000 Subject: [PATCH] 2008-06-29 Tatsuhiro Tsujikawa Added gzip, deflate decoding support in HTTP using libz. If compiled with this feature, aria2 sends "Accept-Encoding: deflate, gzip" header to a HTTP server. If a server returns "Content-Encoding: gzip" or "Content-Encoding: deflate" then, aria2 decodes the response body on the fly and writes decoded data to a local disk. * README * README.html * configure.ac * m4/aria2_arg.m4: Added ARIA2_ARG_WITH and ARIA2_ARG_ENABLE, they are wrapper function for AC_ARG_WITH and AC_ARG_ENABLE respectively. * m4/libz.m4 * src/Decoder.h * src/DownloadCommand.cc * src/DownloadCommand.h * src/Exception.h * src/GZipDecoder.cc * src/GZipDecoder.h * src/HttpHeader.cc * src/HttpHeader.h * src/HttpRequest.cc * src/HttpRequest.h * src/HttpResponse.cc * src/HttpResponse.h * src/HttpResponseCommand.cc * src/Makefile.am * test/GZipDecoderTest.cc * test/HttpRequestTest.cc * test/HttpResponseTest.cc * test/Makefile.am * test/Makefile.in * test/gzip_decode_test.gz --- ChangeLog | 34 +++++++ Makefile.in | 30 ++++--- README | 18 ++-- README.html | 177 ++++++++++++++++++++++--------------- aclocal.m4 | 2 + config.h.in | 3 + configure | 153 ++++++++++++++++++++++++++++++-- configure.ac | 8 ++ doc/Makefile.in | 30 ++++--- lib/Makefile.in | 30 ++++--- m4/Makefile.in | 30 ++++--- m4/aria2_arg.m4 | 15 ++++ m4/libz.m4 | 33 +++++++ src/Decoder.h | 60 +++++++++++++ src/DownloadCommand.cc | 71 +++++++++------ src/DownloadCommand.h | 5 ++ src/Exception.h | 2 +- src/GZipDecoder.cc | 119 +++++++++++++++++++++++++ src/GZipDecoder.h | 72 +++++++++++++++ src/HttpHeader.cc | 6 ++ src/HttpHeader.h | 6 ++ src/HttpRequest.cc | 21 +++++ src/HttpRequest.h | 6 ++ src/HttpResponse.cc | 25 ++++++ src/HttpResponse.h | 7 ++ src/HttpResponseCommand.cc | 37 +++++++- src/Makefile.am | 11 ++- src/Makefile.in | 112 ++++++++++++----------- test/GZipDecoderTest.cc | 59 +++++++++++++ test/HttpRequestTest.cc | 39 ++++++++ test/HttpResponseTest.cc | 70 +++++++++++++++ test/Makefile.am | 9 +- test/Makefile.in | 60 +++++++------ test/gzip_decode_test.gz | Bin 0 -> 79842 bytes 34 files changed, 1107 insertions(+), 253 deletions(-) create mode 100644 m4/aria2_arg.m4 create mode 100644 m4/libz.m4 create mode 100644 src/Decoder.h create mode 100644 src/GZipDecoder.cc create mode 100644 src/GZipDecoder.h create mode 100644 test/GZipDecoderTest.cc create mode 100644 test/gzip_decode_test.gz diff --git a/ChangeLog b/ChangeLog index 4fcec43b..679b270d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,37 @@ +2008-06-29 Tatsuhiro Tsujikawa + + Added gzip, deflate decoding support in HTTP using libz. If compiled + with this feature, aria2 sends "Accept-Encoding: deflate, gzip" header + to a HTTP server. If a server returns "Content-Encoding: gzip" or + "Content-Encoding: deflate" then, aria2 decodes the response body on the + fly and writes decoded data to a local disk. + * README + * README.html + * configure.ac + * m4/aria2_arg.m4: Added ARIA2_ARG_WITH and ARIA2_ARG_ENABLE, they are + wrapper function for AC_ARG_WITH and AC_ARG_ENABLE respectively. + * m4/libz.m4 + * src/Decoder.h + * src/DownloadCommand.cc + * src/DownloadCommand.h + * src/Exception.h + * src/GZipDecoder.cc + * src/GZipDecoder.h + * src/HttpHeader.cc + * src/HttpHeader.h + * src/HttpRequest.cc + * src/HttpRequest.h + * src/HttpResponse.cc + * src/HttpResponse.h + * src/HttpResponseCommand.cc + * src/Makefile.am + * test/GZipDecoderTest.cc + * test/HttpRequestTest.cc + * test/HttpResponseTest.cc + * test/Makefile.am + * test/Makefile.in + * test/gzip_decode_test.gz + 2008-06-29 Tatsuhiro Tsujikawa Clarified usage of -j option. diff --git a/Makefile.in b/Makefile.in index c85f0388..7a8ecbb6 100644 --- a/Makefile.in +++ b/Makefile.in @@ -42,24 +42,24 @@ DIST_COMMON = README $(am__configure_deps) $(dist_doc_DATA) \ config.guess config.rpath config.sub depcomp install-sh \ missing mkinstalldirs ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/codeset.m4 \ - $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/glibc2.m4 \ - $(top_srcdir)/m4/glibc21.m4 $(top_srcdir)/m4/iconv.m4 \ - $(top_srcdir)/m4/intdiv0.m4 $(top_srcdir)/m4/intl.m4 \ - $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intmax.m4 \ - $(top_srcdir)/m4/inttypes-pri.m4 \ +am__aclocal_m4_deps = $(top_srcdir)/m4/aria2_arg.m4 \ + $(top_srcdir)/m4/codeset.m4 $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/glibc2.m4 $(top_srcdir)/m4/glibc21.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intdiv0.m4 \ + $(top_srcdir)/m4/intl.m4 $(top_srcdir)/m4/intlmacosx.m4 \ + $(top_srcdir)/m4/intmax.m4 $(top_srcdir)/m4/inttypes-pri.m4 \ $(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/lcmessage.m4 \ $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \ $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libares.m4 \ $(top_srcdir)/m4/libcares.m4 $(top_srcdir)/m4/libexpat.m4 \ - $(top_srcdir)/m4/lock.m4 $(top_srcdir)/m4/longlong.m4 \ - $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/openssl.m4 \ - $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/printf-posix.m4 \ - $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/size_max.m4 \ - $(top_srcdir)/m4/stdint_h.m4 $(top_srcdir)/m4/uintmax_t.m4 \ - $(top_srcdir)/m4/visibility.m4 $(top_srcdir)/m4/wchar_t.m4 \ - $(top_srcdir)/m4/wint_t.m4 $(top_srcdir)/m4/xsize.m4 \ - $(top_srcdir)/configure.ac + $(top_srcdir)/m4/libz.m4 $(top_srcdir)/m4/lock.m4 \ + $(top_srcdir)/m4/longlong.m4 $(top_srcdir)/m4/nls.m4 \ + $(top_srcdir)/m4/openssl.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/printf-posix.m4 $(top_srcdir)/m4/progtest.m4 \ + $(top_srcdir)/m4/size_max.m4 $(top_srcdir)/m4/stdint_h.m4 \ + $(top_srcdir)/m4/uintmax_t.m4 $(top_srcdir)/m4/visibility.m4 \ + $(top_srcdir)/m4/wchar_t.m4 $(top_srcdir)/m4/wint_t.m4 \ + $(top_srcdir)/m4/xsize.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ @@ -175,6 +175,8 @@ LIBPTH = @LIBPTH@ LIBPTH_PREFIX = @LIBPTH_PREFIX@ LIBS = @LIBS@ LIBTHREAD = @LIBTHREAD@ +LIBZ_CPPFLAGS = @LIBZ_CPPFLAGS@ +LIBZ_LIBS = @LIBZ_LIBS@ LTLIBC = @LTLIBC@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ diff --git a/README b/README index 51f4b984..88df5ba9 100644 --- a/README +++ b/README @@ -39,14 +39,15 @@ Dependency .External Library Dependency [frame="all", grid="all"] -`---------`--------------------------- -features dependency --------------------------------------- -HTTPS GnuTLS or OpenSSL -BitTorrent GnuTLS+Libgcrypt or OpenSSL -Metalink libxml2 or Expat. -Checksum GnuTLS+Libgcrypt or OpenSSL --------------------------------------- +`--------------------`--------------------------- +features dependency +------------------------------------------------- +HTTPS GnuTLS or OpenSSL +BitTorrent GnuTLS+Libgcrypt or OpenSSL +Metalink libxml2 or Expat. +Checksum GnuTLS+Libgcrypt or OpenSSL +gzip, deflate in HTTP zlib +------------------------------------------------- Note;; GNU TLS has precedence over OpenSSL if both libraries are installed. @@ -74,6 +75,7 @@ packages(package name may vary depending on the distribution you use): * libgcrypt-dev (Required for BitTorrent, Checksum support) * libares-dev (Required for async DNS support) * libxml2-dev (Required for Metalink support) +* libz1g-dev (Required for gzip, deflate decoding support in HTTP) You can use libssl-dev instead of libgnutls-dev,libgpg-error-dev,libgcrypt-dev: diff --git a/README.html b/README.html index 78dd4caf..fc45f6bf 100644 --- a/README.html +++ b/README.html @@ -3,7 +3,7 @@ - + aria2 - The ultra fast download utility @@ -306,16 +330,16 @@ div#toc a:visited { color: blue; } Tatsuhiro Tsujikawa
<tujikawa_at_users_dot_sourceforge_dot_net>
-

1. Disclaimer

+

1. Disclaimer

-

This program comes with no warranty. -You must use this program at your own risk.

+

This program comes with no warranty. +You must use this program at your own risk.

-

2. Introduction

+

2. Introduction

-

aria2 is a utility for downloading files. The supported protocols are HTTP(S), FTP, BitTorrent, and Metalink. It has a powerful segmented downloading ability, downloading a file from multiple sources and multiple protocols and utilizing your download bandwidth to the maximum. It supports downloading a file from HTTP(S)/FTP and BitTorrent at the same time, while the data downloaded from HTTP(S)/FTP is uploaded to the BitTorrent swarm. Using Metalink's chunk checksums, aria2 automatically validates chunks of data while downloading a file like BitTorrent.

-

Here is a list of features.

-
    +

    aria2 is a utility for downloading files. The supported protocols are HTTP(S), FTP, BitTorrent, and Metalink. It has a powerful segmented downloading ability, downloading a file from multiple sources and multiple protocols and utilizing your download bandwidth to the maximum. It supports downloading a file from HTTP(S)/FTP and BitTorrent at the same time, while the data downloaded from HTTP(S)/FTP is uploaded to the BitTorrent swarm. Using Metalink's chunk checksums, aria2 automatically validates chunks of data while downloading a file like BitTorrent.

    +

    Here is a list of features.

    +
    • HTTP Proxy support @@ -407,16 +431,16 @@ Integrates HTTP/FTP/BitTorrent downloads; downloading a file from several different sources.

    • -
    +
-

3. Dependency

+

3. Dependency

-+ @@ -461,10 +485,18 @@ cellspacing="0" cellpadding="4"> GnuTLS+Libgcrypt or OpenSSL + + + +
Table: External Library Dependency
+ gzip, deflate in HTTP + + zlib +
-
+
Note
@@ -483,11 +515,11 @@ Note If you prefer Expat, run configure with "—without-libxml2".

-
-

You can disable BitTorrent, Metalink support by providing —disable-bittorrent, -—disable-metalink respectively to configure script.

-

In order to enable async DNS support, you need c-ares or ares.

-
    +
+

You can disable BitTorrent, Metalink support by providing —disable-bittorrent, +—disable-metalink respectively to configure script.

+

In order to enable async DNS support, you need c-ares or ares.

+
  • c-ares: http://daniel.haxx.se/projects/c-ares/ @@ -498,13 +530,13 @@ c-ares: http://daniel.haxx.se/projects/c-ares/ ares: ftp://athena-dist.mit.edu/pub/ATHENA/ares

  • -
+
-

4. How to build

+

4. How to build

-

In order to build aria2 from the source package, you need following development -packages(package name may vary depending on the distribution you use):

-
    +

    In order to build aria2 from the source package, you need following development +packages(package name may vary depending on the distribution you use):

    +
    • libgnutls-dev (Required for HTTPS, BitTorrent, Checksum support) @@ -530,36 +562,41 @@ libares-dev (Required for async DNS support) libxml2-dev (Required for Metalink support)

    • -
    -

    You can use libssl-dev instead of libgnutls-dev,libgpg-error-dev,libgcrypt-dev:

    -
      +
    • +

      +libz1g-dev (Required for gzip, deflate decoding support in HTTP) +

      +
    • +
    +

    You can use libssl-dev instead of libgnutls-dev,libgpg-error-dev,libgcrypt-dev:

    +
    • libssl-dev (Required for HTTPS, BitTorrent, Checksum support)

    • -
    -

    You can use libexpat1-dev instead of libxml2-dev:

    -
      +
    +

    You can use libexpat1-dev instead of libxml2-dev:

    +
    • libexpat1-dev (Required for Metalink support)

    • -
    -

    The build process is fairly standard way for *nix programs:

    +
+

The build process is fairly standard way for *nix programs:

$ ./configure
 $ make
-

The executable is aria2c in src directory.

+

The executable is aria2c in src directory.

-

5. BitTorrrent

+

5. BitTorrrent

-

5.1. About filename

-

The filename of the downloaded file is determined as follows:

-
+

5.1. About filename

+

The filename of the downloaded file is determined as follows:

+
single-file mode
@@ -583,25 +620,25 @@ multi-file mode specified by -d option.

-
-

In the default behavior, before download starts, complete directory structure +

+

In the default behavior, before download starts, complete directory structure is created if needed. Then aria2 opens all files mentioned in .torrent file, directly writes to and reads from these files. -NOTE: Even in selective download, all files are opened.

-

If "—direct-file-mapping" option set to be false, aria2 creates temporary +NOTE: Even in selective download, all files are opened.

+

If "—direct-file-mapping" option set to be false, aria2 creates temporary file in the store directory. The length of this file is the sum of length of the files in .torrent file, so at least 2 times more disk space than the file size itself is required. Writing and reading is done against this file. After download completes, aria2 creates complete directory structure if needed, -and copies whole file or a part of it to the destination.

-

5.2. DHT

-

As of release 0.13.0, aria2 supports DHT. The routing table is saved to $HOME/.aria2/dht.dat.

-
+and copies whole file or a part of it to the destination.

+

5.2. DHT

+

As of release 0.13.0, aria2 supports DHT. The routing table is saved to $HOME/.aria2/dht.dat.

+
Note
-
    +
    • -o option is used to change the filename of .torrent file itself, not a filename of a file in .torrent file. @@ -629,36 +666,36 @@ As of release 0.10.0, aria2 stops sending request message after selective download completes,

    • -
    +
- + -

6. Metalink

+
-

The current implementation supports HTTP/FTP/BitTorrent. -The other P2P protocols are ignored.

-

For checksum checking, MD5, SHA1, SHA256 are supported. If multiple hash +

The current implementation supports HTTP/FTP/BitTorrent. +The other P2P protocols are ignored.

+

For checksum checking, MD5, SHA1, SHA256 are supported. If multiple hash algorithms are provided, aria2 uses SHA1. If checksum checking is failed, aria2 -doesn't retry the download and just exits with non-zero return code.

-

The supported user preferences are version, language, location, protocol and -os.

-

If chunk checksums are provided in Metalink file, aria2 automatically validate +doesn't retry the download and just exits with non-zero return code.

+

The supported user preferences are version, language, location, protocol and +os.

+

If chunk checksums are provided in Metalink file, aria2 automatically validate a chunk of file while downloading it. This behavior can be turned off by -a command-line option.

+a command-line option.

-

7. netrc

+

7. netrc

-

netrc support is enabled by default in ftp. +

netrc support is enabled by default in ftp. To disable netrc support, specify -n command-line option. -Your .netrc file should have correct permissions(600).

+Your .netrc file should have correct permissions(600).

-

8. Configuration file

+

8. Configuration file

-

Configuration file must be placed under $HOME/.aria2 and must be named as aria2.conf. +

Configuration file must be placed under $HOME/.aria2 and must be named as aria2.conf. In each line, there is 1 parameter whose syntax is name=value pair, where name is the long command-line option name without prefix. -The lines beginning # are treated as comments.

-

Example:

+The lines beginning # are treated as comments.

+

Example:

# sample configuration file for aria2c
@@ -671,7 +708,7 @@ ftp-pasv=true
diff --git a/aclocal.m4 b/aclocal.m4 index 50347a8f..2da01362 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -1418,6 +1418,7 @@ AC_SUBST([am__tar]) AC_SUBST([am__untar]) ]) # _AM_PROG_TAR +m4_include([m4/aria2_arg.m4]) m4_include([m4/codeset.m4]) m4_include([m4/gettext.m4]) m4_include([m4/glibc2.m4]) @@ -1436,6 +1437,7 @@ m4_include([m4/lib-prefix.m4]) m4_include([m4/libares.m4]) m4_include([m4/libcares.m4]) m4_include([m4/libexpat.m4]) +m4_include([m4/libz.m4]) m4_include([m4/lock.m4]) m4_include([m4/longlong.m4]) m4_include([m4/nls.m4]) diff --git a/config.h.in b/config.h.in index 74e7cb53..9b0efe18 100644 --- a/config.h.in +++ b/config.h.in @@ -220,6 +220,9 @@ /* Define to 1 if you have libxml2. */ #undef HAVE_LIBXML2 +/* Define to 1 if you have libz. */ +#undef HAVE_LIBZ + /* Define to 1 if you have the header file. */ #undef HAVE_LIMITS_H diff --git a/configure b/configure index a5898c31..bd59a47b 100755 --- a/configure +++ b/configure @@ -738,6 +738,8 @@ LIBCARES_LIBS LIBCARES_CPPFLAGS LIBARES_LIBS LIBARES_CPPFLAGS +LIBZ_LIBS +LIBZ_CPPFLAGS ENABLE_MESSAGE_DIGEST_TRUE ENABLE_MESSAGE_DIGEST_FALSE ENABLE_BITTORRENT_TRUE @@ -750,6 +752,8 @@ ENABLE_LIBEXPAT_TRUE ENABLE_LIBEXPAT_FALSE ENABLE_ASYNC_DNS_TRUE ENABLE_ASYNC_DNS_FALSE +HAVE_LIBZ_TRUE +HAVE_LIBZ_FALSE ALLOCA USE_NLS GETTEXT_MACRO_VERSION @@ -1436,6 +1440,7 @@ Optional Packages: --with-libexpat use libexpat library if installed. Default: yes --with-libares use ares library if installed. Default: yes --with-libcares use c-ares library if installed. Default: yes + --with-libz use libz if it is installed. --with-xml-prefix=PFX Prefix where libxml is installed (optional) --with-xml-exec-prefix=PFX Exec prefix where libxml is installed (optional) --with-libexpat-prefix=PREFIX Prefix where libexpat installed (optional) @@ -1445,6 +1450,7 @@ Optional Packages: --with-openssl-prefix=PREFIX Prefix where OpenSSL installed (optional) --with-libcares-prefix=PREFIX Prefix where libcares installed (optional) --with-libares-prefix=PREFIX Prefix where libares installed (optional) + --with-libz-prefix=PREFIX Prefix where libz installed (optional) --with-gnu-ld assume the C compiler uses GNU ld default=no --with-libpth-prefix[=DIR] search for libpth in DIR/include and DIR/lib --without-libpth-prefix don't search for libpth in includedir and libdir @@ -2727,6 +2733,15 @@ else fi +# Check whether --with-libz was given. +if test "${with_libz+set}" = set; then + withval=$with_libz; with_libz=$withval +else + with_libz=yes +fi + + + # Check whether --enable-bittorrent was given. if test "${enable_bittorrent+set}" = set; then enableval=$enable_bittorrent; enable_bittorrent=$enableval @@ -6982,6 +6997,113 @@ CPPFLAGS=$CPPFLAGS_save fi fi +if test "x$with_libz" = "xyes"; then + + +# Check whether --with-libz-prefix was given. +if test "${with_libz_prefix+set}" = set; then + withval=$with_libz_prefix; libz_prefix=$withval +else + libz_prefix="" +fi + + +if test "x$libz_prefix" = "x"; then + libz_prefix="/usr" +fi + +libz_prefix_lib=$libz_prefix/lib +libz_prefix_include=$libz_prefix/include + +LIBS_save=$LIBS +CPPFLAGS_save=$CPPFLAGS + +LIBS="-L$libz_prefix_lib $LIBS" +CPPFLAGS="-I$libz_prefix_include $CPPFLAGS" + +{ echo "$as_me:$LINENO: checking for zlibVersion in -lz" >&5 +echo $ECHO_N "checking for zlibVersion in -lz... $ECHO_C" >&6; } +if test "${ac_cv_lib_z_zlibVersion+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lz $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char zlibVersion (); +int +main () +{ +return zlibVersion (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + ac_cv_lib_z_zlibVersion=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_z_zlibVersion=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_z_zlibVersion" >&5 +echo "${ECHO_T}$ac_cv_lib_z_zlibVersion" >&6; } +if test $ac_cv_lib_z_zlibVersion = yes; then + have_libz=yes +fi + +if test "x$have_libz" = "xyes"; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_LIBZ 1 +_ACEOF + + LIBZ_LIBS="-L$libz_prefix_lib -lz" + LIBZ_CPPFLAGS="-I$libz_prefix_include" + + +fi + +LIBS=$LIBS_save +CPPFLAGS=$CPPFLAGS_save + + +fi + # Define variables based on the result of the checks for libraries. if test "x$have_libgnutls" = "xyes" || test "x$have_openssl" = "xyes"; then @@ -7111,6 +7233,15 @@ fi fi + if test "x$have_libz" = "xyes"; then + HAVE_LIBZ_TRUE= + HAVE_LIBZ_FALSE='#' +else + HAVE_LIBZ_TRUE='#' + HAVE_LIBZ_FALSE= +fi + + # Checks for header files. # The Ultrix 4.2 mips builtin alloca declared by alloca.h only works # for constant arguments. Useless! @@ -21306,6 +21437,13 @@ echo "$as_me: error: conditional \"ENABLE_ASYNC_DNS\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi +if test -z "${HAVE_LIBZ_TRUE}" && test -z "${HAVE_LIBZ_FALSE}"; then + { { echo "$as_me:$LINENO: error: conditional \"HAVE_LIBZ\" was never defined. +Usually this means the macro was only invoked conditionally." >&5 +echo "$as_me: error: conditional \"HAVE_LIBZ\" was never defined. +Usually this means the macro was only invoked conditionally." >&2;} + { (exit 1); exit 1; }; } +fi if test -z "${HAVE_ASCTIME_R_TRUE}" && test -z "${HAVE_ASCTIME_R_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"HAVE_ASCTIME_R\" was never defined. Usually this means the macro was only invoked conditionally." >&5 @@ -22154,6 +22292,8 @@ LIBCARES_LIBS!$LIBCARES_LIBS$ac_delim LIBCARES_CPPFLAGS!$LIBCARES_CPPFLAGS$ac_delim LIBARES_LIBS!$LIBARES_LIBS$ac_delim LIBARES_CPPFLAGS!$LIBARES_CPPFLAGS$ac_delim +LIBZ_LIBS!$LIBZ_LIBS$ac_delim +LIBZ_CPPFLAGS!$LIBZ_CPPFLAGS$ac_delim ENABLE_MESSAGE_DIGEST_TRUE!$ENABLE_MESSAGE_DIGEST_TRUE$ac_delim ENABLE_MESSAGE_DIGEST_FALSE!$ENABLE_MESSAGE_DIGEST_FALSE$ac_delim ENABLE_BITTORRENT_TRUE!$ENABLE_BITTORRENT_TRUE$ac_delim @@ -22166,6 +22306,8 @@ ENABLE_LIBEXPAT_TRUE!$ENABLE_LIBEXPAT_TRUE$ac_delim ENABLE_LIBEXPAT_FALSE!$ENABLE_LIBEXPAT_FALSE$ac_delim ENABLE_ASYNC_DNS_TRUE!$ENABLE_ASYNC_DNS_TRUE$ac_delim ENABLE_ASYNC_DNS_FALSE!$ENABLE_ASYNC_DNS_FALSE$ac_delim +HAVE_LIBZ_TRUE!$HAVE_LIBZ_TRUE$ac_delim +HAVE_LIBZ_FALSE!$HAVE_LIBZ_FALSE$ac_delim ALLOCA!$ALLOCA$ac_delim USE_NLS!$USE_NLS$ac_delim GETTEXT_MACRO_VERSION!$GETTEXT_MACRO_VERSION$ac_delim @@ -22224,10 +22366,6 @@ HAVE_GETADDRINFO_TRUE!$HAVE_GETADDRINFO_TRUE$ac_delim HAVE_GETADDRINFO_FALSE!$HAVE_GETADDRINFO_FALSE$ac_delim HAVE_GETTIMEOFDAY_TRUE!$HAVE_GETTIMEOFDAY_TRUE$ac_delim HAVE_GETTIMEOFDAY_FALSE!$HAVE_GETTIMEOFDAY_FALSE$ac_delim -HAVE_INET_ATON_TRUE!$HAVE_INET_ATON_TRUE$ac_delim -HAVE_INET_ATON_FALSE!$HAVE_INET_ATON_FALSE$ac_delim -HAVE_LOCALTIME_R_TRUE!$HAVE_LOCALTIME_R_TRUE$ac_delim -HAVE_LOCALTIME_R_FALSE!$HAVE_LOCALTIME_R_FALSE$ac_delim _ACEOF if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 97; then @@ -22269,6 +22407,10 @@ _ACEOF ac_delim='%!_!# ' for ac_last_try in false false false false false :; do cat >conf$$subs.sed <<_ACEOF +HAVE_INET_ATON_TRUE!$HAVE_INET_ATON_TRUE$ac_delim +HAVE_INET_ATON_FALSE!$HAVE_INET_ATON_FALSE$ac_delim +HAVE_LOCALTIME_R_TRUE!$HAVE_LOCALTIME_R_TRUE$ac_delim +HAVE_LOCALTIME_R_FALSE!$HAVE_LOCALTIME_R_FALSE$ac_delim HAVE_STRPTIME_TRUE!$HAVE_STRPTIME_TRUE$ac_delim HAVE_STRPTIME_FALSE!$HAVE_STRPTIME_FALSE$ac_delim HAVE_TIMEGM_TRUE!$HAVE_TIMEGM_TRUE$ac_delim @@ -22276,7 +22418,7 @@ HAVE_TIMEGM_FALSE!$HAVE_TIMEGM_FALSE$ac_delim LTLIBOBJS!$LTLIBOBJS$ac_delim _ACEOF - if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 5; then + if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 9; then break elif $ac_last_try; then { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 @@ -23003,5 +23145,6 @@ echo "LibXML2: $have_libxml2" echo "LibExpat: $have_libexpat" echo "LibAres: $have_libares" echo "LibCares: $have_libcares" +echo "Libz: $have_libz" echo "Bittorrent: $enable_bittorrent" echo "Metalink: $enable_metalink" diff --git a/configure.ac b/configure.ac index 5be30a93..c36ce03b 100644 --- a/configure.ac +++ b/configure.ac @@ -30,6 +30,7 @@ AC_ARG_WITH([libxml2], [ --with-libxml2 use libxml2 library if inst AC_ARG_WITH([libexpat], [ --with-libexpat use libexpat library if installed. Default: yes], [with_libexpat=$withval], [with_libexpat=yes]) AC_ARG_WITH([libares], [ --with-libares use ares library if installed. Default: yes], [with_libares=$withval], [with_libares=yes]) AC_ARG_WITH([libcares], [ --with-libcares use c-ares library if installed. Default: yes], [with_libcares=$withval], [with_libcares=yes]) +ARIA2_ARG_WITH([libz]) AC_ARG_ENABLE([bittorrent], [ --enable-bittorrent enable BitTorrent support. Default: yes], [enable_bittorrent=$enableval], [enable_bittorrent=yes]) AC_ARG_ENABLE([metalink], [ --enable-metalink enable Metalink support. Default: yes], [enable_metalink=$enableval], [enable_metalink=yes]) @@ -92,6 +93,10 @@ if test "x$have_libcares" = "x"; then fi fi +if test "x$with_libz" = "xyes"; then + AM_PATH_LIBZ +fi + # Define variables based on the result of the checks for libraries. if test "x$have_libgnutls" = "xyes" || test "x$have_openssl" = "xyes"; then AC_DEFINE([ENABLE_SSL], [1], [Define to 1 if ssl support is enabled.]) @@ -131,6 +136,8 @@ else AM_CONDITIONAL([ENABLE_ASYNC_DNS], false) fi +AM_CONDITIONAL([HAVE_LIBZ], [test "x$have_libz" = "xyes"]) + # Checks for header files. AC_FUNC_ALLOCA AC_HEADER_STDC @@ -249,5 +256,6 @@ echo "LibXML2: $have_libxml2" echo "LibExpat: $have_libexpat" echo "LibAres: $have_libares" echo "LibCares: $have_libcares" +echo "Libz: $have_libz" echo "Bittorrent: $enable_bittorrent" echo "Metalink: $enable_metalink" diff --git a/doc/Makefile.in b/doc/Makefile.in index 68f328b6..a66d12ef 100644 --- a/doc/Makefile.in +++ b/doc/Makefile.in @@ -37,24 +37,24 @@ subdir = doc DIST_COMMON = $(dist_doc_DATA) $(srcdir)/Makefile.am \ $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/codeset.m4 \ - $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/glibc2.m4 \ - $(top_srcdir)/m4/glibc21.m4 $(top_srcdir)/m4/iconv.m4 \ - $(top_srcdir)/m4/intdiv0.m4 $(top_srcdir)/m4/intl.m4 \ - $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intmax.m4 \ - $(top_srcdir)/m4/inttypes-pri.m4 \ +am__aclocal_m4_deps = $(top_srcdir)/m4/aria2_arg.m4 \ + $(top_srcdir)/m4/codeset.m4 $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/glibc2.m4 $(top_srcdir)/m4/glibc21.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intdiv0.m4 \ + $(top_srcdir)/m4/intl.m4 $(top_srcdir)/m4/intlmacosx.m4 \ + $(top_srcdir)/m4/intmax.m4 $(top_srcdir)/m4/inttypes-pri.m4 \ $(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/lcmessage.m4 \ $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \ $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libares.m4 \ $(top_srcdir)/m4/libcares.m4 $(top_srcdir)/m4/libexpat.m4 \ - $(top_srcdir)/m4/lock.m4 $(top_srcdir)/m4/longlong.m4 \ - $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/openssl.m4 \ - $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/printf-posix.m4 \ - $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/size_max.m4 \ - $(top_srcdir)/m4/stdint_h.m4 $(top_srcdir)/m4/uintmax_t.m4 \ - $(top_srcdir)/m4/visibility.m4 $(top_srcdir)/m4/wchar_t.m4 \ - $(top_srcdir)/m4/wint_t.m4 $(top_srcdir)/m4/xsize.m4 \ - $(top_srcdir)/configure.ac + $(top_srcdir)/m4/libz.m4 $(top_srcdir)/m4/lock.m4 \ + $(top_srcdir)/m4/longlong.m4 $(top_srcdir)/m4/nls.m4 \ + $(top_srcdir)/m4/openssl.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/printf-posix.m4 $(top_srcdir)/m4/progtest.m4 \ + $(top_srcdir)/m4/size_max.m4 $(top_srcdir)/m4/stdint_h.m4 \ + $(top_srcdir)/m4/uintmax_t.m4 $(top_srcdir)/m4/visibility.m4 \ + $(top_srcdir)/m4/wchar_t.m4 $(top_srcdir)/m4/wint_t.m4 \ + $(top_srcdir)/m4/xsize.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs @@ -149,6 +149,8 @@ LIBPTH = @LIBPTH@ LIBPTH_PREFIX = @LIBPTH_PREFIX@ LIBS = @LIBS@ LIBTHREAD = @LIBTHREAD@ +LIBZ_CPPFLAGS = @LIBZ_CPPFLAGS@ +LIBZ_LIBS = @LIBZ_LIBS@ LTLIBC = @LTLIBC@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ diff --git a/lib/Makefile.in b/lib/Makefile.in index 77fe0124..564dc4e6 100644 --- a/lib/Makefile.in +++ b/lib/Makefile.in @@ -35,24 +35,24 @@ target_triplet = @target@ subdir = lib DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/codeset.m4 \ - $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/glibc2.m4 \ - $(top_srcdir)/m4/glibc21.m4 $(top_srcdir)/m4/iconv.m4 \ - $(top_srcdir)/m4/intdiv0.m4 $(top_srcdir)/m4/intl.m4 \ - $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intmax.m4 \ - $(top_srcdir)/m4/inttypes-pri.m4 \ +am__aclocal_m4_deps = $(top_srcdir)/m4/aria2_arg.m4 \ + $(top_srcdir)/m4/codeset.m4 $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/glibc2.m4 $(top_srcdir)/m4/glibc21.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intdiv0.m4 \ + $(top_srcdir)/m4/intl.m4 $(top_srcdir)/m4/intlmacosx.m4 \ + $(top_srcdir)/m4/intmax.m4 $(top_srcdir)/m4/inttypes-pri.m4 \ $(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/lcmessage.m4 \ $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \ $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libares.m4 \ $(top_srcdir)/m4/libcares.m4 $(top_srcdir)/m4/libexpat.m4 \ - $(top_srcdir)/m4/lock.m4 $(top_srcdir)/m4/longlong.m4 \ - $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/openssl.m4 \ - $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/printf-posix.m4 \ - $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/size_max.m4 \ - $(top_srcdir)/m4/stdint_h.m4 $(top_srcdir)/m4/uintmax_t.m4 \ - $(top_srcdir)/m4/visibility.m4 $(top_srcdir)/m4/wchar_t.m4 \ - $(top_srcdir)/m4/wint_t.m4 $(top_srcdir)/m4/xsize.m4 \ - $(top_srcdir)/configure.ac + $(top_srcdir)/m4/libz.m4 $(top_srcdir)/m4/lock.m4 \ + $(top_srcdir)/m4/longlong.m4 $(top_srcdir)/m4/nls.m4 \ + $(top_srcdir)/m4/openssl.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/printf-posix.m4 $(top_srcdir)/m4/progtest.m4 \ + $(top_srcdir)/m4/size_max.m4 $(top_srcdir)/m4/stdint_h.m4 \ + $(top_srcdir)/m4/uintmax_t.m4 $(top_srcdir)/m4/visibility.m4 \ + $(top_srcdir)/m4/wchar_t.m4 $(top_srcdir)/m4/wint_t.m4 \ + $(top_srcdir)/m4/xsize.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs @@ -135,6 +135,8 @@ LIBPTH = @LIBPTH@ LIBPTH_PREFIX = @LIBPTH_PREFIX@ LIBS = @LIBS@ LIBTHREAD = @LIBTHREAD@ +LIBZ_CPPFLAGS = @LIBZ_CPPFLAGS@ +LIBZ_LIBS = @LIBZ_LIBS@ LTLIBC = @LTLIBC@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ diff --git a/m4/Makefile.in b/m4/Makefile.in index 1756a8d7..24cb4e7b 100644 --- a/m4/Makefile.in +++ b/m4/Makefile.in @@ -35,24 +35,24 @@ target_triplet = @target@ subdir = m4 DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ChangeLog ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/codeset.m4 \ - $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/glibc2.m4 \ - $(top_srcdir)/m4/glibc21.m4 $(top_srcdir)/m4/iconv.m4 \ - $(top_srcdir)/m4/intdiv0.m4 $(top_srcdir)/m4/intl.m4 \ - $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intmax.m4 \ - $(top_srcdir)/m4/inttypes-pri.m4 \ +am__aclocal_m4_deps = $(top_srcdir)/m4/aria2_arg.m4 \ + $(top_srcdir)/m4/codeset.m4 $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/glibc2.m4 $(top_srcdir)/m4/glibc21.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intdiv0.m4 \ + $(top_srcdir)/m4/intl.m4 $(top_srcdir)/m4/intlmacosx.m4 \ + $(top_srcdir)/m4/intmax.m4 $(top_srcdir)/m4/inttypes-pri.m4 \ $(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/lcmessage.m4 \ $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \ $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libares.m4 \ $(top_srcdir)/m4/libcares.m4 $(top_srcdir)/m4/libexpat.m4 \ - $(top_srcdir)/m4/lock.m4 $(top_srcdir)/m4/longlong.m4 \ - $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/openssl.m4 \ - $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/printf-posix.m4 \ - $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/size_max.m4 \ - $(top_srcdir)/m4/stdint_h.m4 $(top_srcdir)/m4/uintmax_t.m4 \ - $(top_srcdir)/m4/visibility.m4 $(top_srcdir)/m4/wchar_t.m4 \ - $(top_srcdir)/m4/wint_t.m4 $(top_srcdir)/m4/xsize.m4 \ - $(top_srcdir)/configure.ac + $(top_srcdir)/m4/libz.m4 $(top_srcdir)/m4/lock.m4 \ + $(top_srcdir)/m4/longlong.m4 $(top_srcdir)/m4/nls.m4 \ + $(top_srcdir)/m4/openssl.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/printf-posix.m4 $(top_srcdir)/m4/progtest.m4 \ + $(top_srcdir)/m4/size_max.m4 $(top_srcdir)/m4/stdint_h.m4 \ + $(top_srcdir)/m4/uintmax_t.m4 $(top_srcdir)/m4/visibility.m4 \ + $(top_srcdir)/m4/wchar_t.m4 $(top_srcdir)/m4/wint_t.m4 \ + $(top_srcdir)/m4/xsize.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs @@ -135,6 +135,8 @@ LIBPTH = @LIBPTH@ LIBPTH_PREFIX = @LIBPTH_PREFIX@ LIBS = @LIBS@ LIBTHREAD = @LIBTHREAD@ +LIBZ_CPPFLAGS = @LIBZ_CPPFLAGS@ +LIBZ_LIBS = @LIBZ_LIBS@ LTLIBC = @LTLIBC@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ diff --git a/m4/aria2_arg.m4 b/m4/aria2_arg.m4 new file mode 100644 index 00000000..6fad9d0f --- /dev/null +++ b/m4/aria2_arg.m4 @@ -0,0 +1,15 @@ +dnl ARIA2_ARG_WITH(PACKAGE) +dnl wrapper for AC_ARG_WITH with default value 'yes'. +AC_DEFUN([ARIA2_ARG_WITH], +[AC_ARG_WITH([$1], + AC_HELP_STRING([--with-$1], [use $1 if it is installed.]), + [with_$1=$withval], [with_$1=yes])] +) + +dnl ARIA2_ARG_ENABLE(FEATURE) +dnl wrapper for AC_ARG_ENABLE with default value 'yes'. +AC_DEFUN([ARIA2_ARG_ENABLE], +[AC_ARG_ENABLE([$1], + AC_HELP_STRING([--enable-$1], [enable $1 support.]), + [enable_$1=$withval], [enable_$1=yes])] +) diff --git a/m4/libz.m4 b/m4/libz.m4 new file mode 100644 index 00000000..59de67c8 --- /dev/null +++ b/m4/libz.m4 @@ -0,0 +1,33 @@ +AC_DEFUN([AM_PATH_LIBZ], +[ +AC_ARG_WITH([libz-prefix], + [ --with-libz-prefix=PREFIX Prefix where libz installed (optional)], + [libz_prefix=$withval], + [libz_prefix=""]) + +if test "x$libz_prefix" = "x"; then + libz_prefix="/usr" +fi + +libz_prefix_lib=$libz_prefix/lib +libz_prefix_include=$libz_prefix/include + +LIBS_save=$LIBS +CPPFLAGS_save=$CPPFLAGS + +LIBS="-L$libz_prefix_lib $LIBS" +CPPFLAGS="-I$libz_prefix_include $CPPFLAGS" + +AC_CHECK_LIB([z], [zlibVersion], [have_libz=yes]) +if test "x$have_libz" = "xyes"; then + AC_DEFINE([HAVE_LIBZ], [1], [Define to 1 if you have libz.]) + LIBZ_LIBS="-L$libz_prefix_lib -lz" + LIBZ_CPPFLAGS="-I$libz_prefix_include" + AC_SUBST(LIBZ_LIBS) + AC_SUBST(LIBZ_CPPFLAGS) +fi + +LIBS=$LIBS_save +CPPFLAGS=$CPPFLAGS_save + +]) diff --git a/src/Decoder.h b/src/Decoder.h new file mode 100644 index 00000000..3b5c0df0 --- /dev/null +++ b/src/Decoder.h @@ -0,0 +1,60 @@ +/* */ +#ifndef _D_DECODER_H_ +#define _D_DECODER_H_ + +#include "common.h" +#include + +namespace aria2 { + +class Decoder { +public: + virtual ~Decoder() {} + + virtual void init() = 0; + + virtual std::string decode(const unsigned char* inbuf, size_t inlen) = 0; + + virtual bool finished() = 0; + + virtual void release() = 0; + + virtual const std::string& getName() const = 0; +}; + +} // namespace aria2 + +#endif // _D_DECODER_H_ diff --git a/src/DownloadCommand.cc b/src/DownloadCommand.cc index e15023e7..2b4cfa7b 100644 --- a/src/DownloadCommand.cc +++ b/src/DownloadCommand.cc @@ -55,6 +55,7 @@ #include "message.h" #include "prefs.h" #include "StringFormat.h" +#include "Decoder.h" #ifdef ENABLE_MESSAGE_DIGEST # include "MessageDigestHelper.h" #endif // ENABLE_MESSAGE_DIGEST @@ -119,46 +120,47 @@ bool DownloadCommand::executeInternal() { } socket->readData(buf, bufSize); + const SharedHandle& diskAdaptor = + _requestGroup->getPieceStorage()->getDiskAdaptor(); + + unsigned char* bufFinal; + size_t bufSizeFinal; + if(transferDecoder.isNull()) { - _requestGroup->getPieceStorage()->getDiskAdaptor()->writeData(buf, bufSize, - segment->getPositionToWrite()); - //logger->debug("bufSize = %d, posToWrite = %lld", bufSize, segment->getPositionToWrite()); -#ifdef ENABLE_MESSAGE_DIGEST - - if(_pieceHashValidationEnabled) { - segment->updateHash(segment->getWrittenLength(), buf, bufSize); - } - -#endif // ENABLE_MESSAGE_DIGEST - - segment->updateWrittenLength(bufSize); - - - //logger->debug("overflow length = %d, next posToWrite = %lld", segment->getOverflowLength(), segment->getPositionToWrite()); - //logger->debug("%s", Util::toHex(segment->getPiece()->getBitfield(), - //segment->getPiece()->getBitfieldLength()).c_str()); - //segment->writtenLength += bufSize; - peerStat->updateDownloadLength(bufSize); + bufFinal = buf; + bufSizeFinal = bufSize; } else { size_t infbufSize = 16*1024; unsigned char infbuf[infbufSize]; transferDecoder->inflate(infbuf, infbufSize, buf, bufSize); - _requestGroup->getPieceStorage()->getDiskAdaptor()->writeData(infbuf, infbufSize, - segment->getPositionToWrite()); + + bufFinal = infbuf; + bufSizeFinal = infbufSize; + } + + if(_contentEncodingDecoder.isNull()) { + diskAdaptor->writeData(bufFinal, bufSizeFinal, + segment->getPositionToWrite()); + } else { + std::string out = _contentEncodingDecoder->decode(bufFinal, bufSizeFinal); + diskAdaptor->writeData(reinterpret_cast(out.data()), + out.size(), + segment->getPositionToWrite()); + bufSizeFinal = out.size(); + } #ifdef ENABLE_MESSAGE_DIGEST - if(_pieceHashValidationEnabled) { - segment->updateHash(segment->getWrittenLength(), infbuf, infbufSize); - } + if(_pieceHashValidationEnabled) { + segment->updateHash(segment->getWrittenLength(), bufFinal, bufSizeFinal); + } #endif // ENABLE_MESSAGE_DIGEST - segment->updateWrittenLength(infbufSize); + segment->updateWrittenLength(bufSizeFinal); + + peerStat->updateDownloadLength(bufSize); - //segment->writtenLength += infbufSize; - peerStat->updateDownloadLength(infbufSize); - } if(_requestGroup->getTotalLength() != 0 && bufSize == 0) { throw DlRetryEx(EX_GOT_EOF); } @@ -168,6 +170,13 @@ bool DownloadCommand::executeInternal() { if(!transferDecoder.isNull()) transferDecoder->end(); logger->info(MSG_SEGMENT_DOWNLOAD_COMPLETED, cuid); + if(!_contentEncodingDecoder.isNull() && + !_contentEncodingDecoder->finished()) { + logger->warn("CUID#%d - Transfer was completed, but inflate operation" + " have not finished. Maybe the file is broken in the server" + " side.", cuid); + } + #ifdef ENABLE_MESSAGE_DIGEST { @@ -280,4 +289,10 @@ void DownloadCommand::setTransferDecoder(const TransferEncodingHandle& transferD this->transferDecoder = transferDecoder; } +void DownloadCommand::setContentEncodingDecoder +(const SharedHandle& decoder) +{ + _contentEncodingDecoder = decoder; +} + } // namespace aria2 diff --git a/src/DownloadCommand.h b/src/DownloadCommand.h index a87b62ee..e4388e5a 100644 --- a/src/DownloadCommand.h +++ b/src/DownloadCommand.h @@ -40,6 +40,7 @@ namespace aria2 { class TransferEncoding; +class Decoder; class PeerStat; #ifdef ENABLE_MESSAGE_DIGEST class MessageDigestContext; @@ -68,6 +69,8 @@ private: protected: SharedHandle transferDecoder; + SharedHandle _contentEncodingDecoder; + virtual bool executeInternal(); virtual bool prepareForNextSegment(); @@ -82,6 +85,8 @@ public: void setTransferDecoder(const SharedHandle& transferDecoder); + void setContentEncodingDecoder(const SharedHandle& decoder); + void setMaxDownloadSpeedLimit(unsigned int maxDownloadSpeedLimit) { this->maxDownloadSpeedLimit = maxDownloadSpeedLimit; } diff --git a/src/Exception.h b/src/Exception.h index f788483d..a0fedb39 100644 --- a/src/Exception.h +++ b/src/Exception.h @@ -51,7 +51,7 @@ protected: virtual SharedHandle copy() const = 0; public: - Exception(const std::string& msg); + explicit Exception(const std::string& msg); Exception(const std::string& msg, const Exception& cause); diff --git a/src/GZipDecoder.cc b/src/GZipDecoder.cc new file mode 100644 index 00000000..81f46d2c --- /dev/null +++ b/src/GZipDecoder.cc @@ -0,0 +1,119 @@ +/* */ +#include "GZipDecoder.h" +#include "StringFormat.h" +#include "DlAbortEx.h" + +namespace aria2 { + +const std::string GZipDecoder::NAME("GZipDecoder"); + +GZipDecoder::GZipDecoder():_strm(0), _finished(false) {} + +GZipDecoder::~GZipDecoder() +{ + release(); +} + +void GZipDecoder::init() +{ + _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; + + // initalize z_stream with gzip/zlib format auto detection enabled. + if(Z_OK != inflateInit2(_strm, 47)) { + throw DlAbortEx("Initializing z_stream failed."); + } +} + +void GZipDecoder::release() +{ + if(_strm) { + inflateEnd(_strm); + _strm = 0; + } +} + +std::string GZipDecoder::decode(const unsigned char* in, size_t length) +{ + std::string out; + + if(length == 0) { + return 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 = ::inflate(_strm, Z_NO_FLUSH); + + if(ret == Z_STREAM_END) { + _finished = true; + } else if(ret != Z_OK) { + throw DlAbortEx(StringFormat("libz::inflate() failed. cause:%s", + _strm->msg).str()); + } + + size_t produced = OUTBUF_LENGTH-_strm->avail_out; + + out.insert(out.end(), &outbuf[0], &outbuf[produced]); + + if(_strm->avail_out > 0) { + break; + } + } + return out; +} + +bool GZipDecoder::finished() +{ + return _finished; +} + +const std::string& GZipDecoder::getName() const +{ + return NAME; +} + +} // namespace aria2 diff --git a/src/GZipDecoder.h b/src/GZipDecoder.h new file mode 100644 index 00000000..79151d5a --- /dev/null +++ b/src/GZipDecoder.h @@ -0,0 +1,72 @@ +/* */ +#ifndef _D_GZIP_DECODER_H_ +#define _D_GZIP_DECODER_H_ + +#include "Decoder.h" +#include + +namespace aria2 { + +// GZipDecoder can decode both gzip and deflate format. +class GZipDecoder : public Decoder { +private: + z_stream* _strm; + + bool _finished; + + static const size_t OUTBUF_LENGTH = 16*1024; + + static const std::string NAME; +public: + GZipDecoder(); + + virtual ~GZipDecoder(); + + virtual void init(); + + virtual std::string decode(const unsigned char* inbuf, size_t inlen); + + virtual bool finished(); + + virtual void release(); + + virtual const std::string& getName() const; + +}; + +} // namespace aria2 + +#endif // _D_GZIP_DECODER_H_ diff --git a/src/HttpHeader.cc b/src/HttpHeader.cc index 9194c808..2fcfed9e 100644 --- a/src/HttpHeader.cc +++ b/src/HttpHeader.cc @@ -44,12 +44,18 @@ const std::string HttpHeader::LOCATION("Location"); const std::string HttpHeader::TRANSFER_ENCODING("Transfer-Encoding"); +const std::string HttpHeader::CONTENT_ENCODING("Content-Encoding"); + const std::string HttpHeader::CONTENT_DISPOSITION("Content-Disposition"); const std::string HttpHeader::SET_COOKIE("Set-Cookie"); const std::string HttpHeader::CHUNKED("chunked"); +const std::string HttpHeader::GZIP("gzip"); + +const std::string HttpHeader::DEFLATE("deflate"); + const std::string HttpHeader::CONTENT_TYPE("Content-Type"); const std::string HttpHeader::RETRY_AFTER("Retry-After"); diff --git a/src/HttpHeader.h b/src/HttpHeader.h index c11862e7..286e6eb7 100644 --- a/src/HttpHeader.h +++ b/src/HttpHeader.h @@ -83,12 +83,18 @@ public: static const std::string TRANSFER_ENCODING; + static const std::string CONTENT_ENCODING; + static const std::string CONTENT_DISPOSITION; static const std::string SET_COOKIE; static const std::string CHUNKED; + static const std::string GZIP; + + static const std::string DEFLATE; + static const std::string CONTENT_TYPE; static const std::string RETRY_AFTER; diff --git a/src/HttpRequest.cc b/src/HttpRequest.cc index 7940315d..f0b4d89d 100644 --- a/src/HttpRequest.cc +++ b/src/HttpRequest.cc @@ -55,6 +55,7 @@ HttpRequest::HttpRequest():entityLength(0), authEnabled(false), proxyEnabled(false), proxyAuthEnabled(false), + _contentEncodingEnabled(true), userAgent(USER_AGENT) {} @@ -155,6 +156,16 @@ std::string HttpRequest::createRequest() const } requestLine += "\r\n"; + if(_contentEncodingEnabled) { + std::string acceptableEncodings; +#ifdef HAVE_LIBZ + acceptableEncodings += "deflate, gzip"; +#endif // HAVE_LIBZ + if(!acceptableEncodings.empty()) { + requestLine += "Accept-Encoding: "+acceptableEncodings+"\r\n"; + } + } + requestLine += "Host: "+getHostText(getHost(), getPort())+"\r\n"+ "Pragma: no-cache\r\n"+ @@ -235,6 +246,16 @@ std::string HttpRequest::getProxyAuthString() const { Base64::encode(AuthConfigFactorySingleton::instance()->createAuthConfigForHttpProxy(request)->getAuthText())+"\r\n"; } +void HttpRequest::enableContentEncoding() +{ + _contentEncodingEnabled = true; +} + +void HttpRequest::disableContentEncoding() +{ + _contentEncodingEnabled = false; +} + void HttpRequest::addHeader(const std::string& headersString) { std::deque headers; diff --git a/src/HttpRequest.h b/src/HttpRequest.h index ba5c55a9..2dce737b 100644 --- a/src/HttpRequest.h +++ b/src/HttpRequest.h @@ -64,6 +64,8 @@ private: bool proxyAuthEnabled; + bool _contentEncodingEnabled; + std::string userAgent; std::deque _headers; @@ -166,6 +168,10 @@ public: this->authEnabled = authEnabled; } + void enableContentEncoding(); + + void disableContentEncoding(); + void setUserAgent(const std::string& userAgent) { this->userAgent = userAgent; diff --git a/src/HttpResponse.cc b/src/HttpResponse.cc index d51a806c..5c9c2df4 100644 --- a/src/HttpResponse.cc +++ b/src/HttpResponse.cc @@ -47,6 +47,10 @@ #include "DlAbortEx.h" #include "StringFormat.h" #include "A2STR.h" +#include "Decoder.h" +#ifdef HAVE_LIBZ +# include "GZipDecoder.h" +#endif // HAVE_LIBZ #include namespace aria2 { @@ -150,6 +154,27 @@ TransferEncodingHandle HttpResponse::getTransferDecoder() const return SharedHandle(); } +bool HttpResponse::isContentEncodingSpecified() const +{ + return httpHeader->defined(HttpHeader::CONTENT_ENCODING); +} + +const std::string& HttpResponse::getContentEncoding() const +{ + return httpHeader->getFirst(HttpHeader::CONTENT_ENCODING); +} + +SharedHandle HttpResponse::getContentEncodingDecoder() const +{ +#ifdef HAVE_LIBZ + if(getContentEncoding() == HttpHeader::GZIP || + getContentEncoding() == HttpHeader::DEFLATE) { + return SharedHandle(new GZipDecoder()); + } +#endif // HAVE_LIBZ + return SharedHandle(); +} + uint64_t HttpResponse::getContentLength() const { if(httpHeader.isNull()) { diff --git a/src/HttpResponse.h b/src/HttpResponse.h index 3aeac22a..71d72c43 100644 --- a/src/HttpResponse.h +++ b/src/HttpResponse.h @@ -46,6 +46,7 @@ class HttpRequest; class HttpHeader; class TransferEncoding; class Logger; +class Decoder; class HttpResponse { private: @@ -85,6 +86,12 @@ public: SharedHandle getTransferDecoder() const; + bool isContentEncodingSpecified() const; + + const std::string& getContentEncoding() const; + + SharedHandle getContentEncodingDecoder() const; + uint64_t getContentLength() const; uint64_t getEntityLength() const; diff --git a/src/HttpResponseCommand.cc b/src/HttpResponseCommand.cc index b7522bd6..0cdffcc5 100644 --- a/src/HttpResponseCommand.cc +++ b/src/HttpResponseCommand.cc @@ -62,6 +62,8 @@ #include "StringFormat.h" #include "HttpSkipResponseCommand.h" #include "HttpHeader.h" +#include "Decoder.h" +#include "LogFactory.h" namespace aria2 { @@ -194,10 +196,32 @@ static SharedHandle getTransferEncoding return enc; } +static SharedHandle getContentEncodingDecoder +(const SharedHandle& httpResponse) +{ + SharedHandle decoder; + if(httpResponse->isContentEncodingSpecified()) { + decoder = httpResponse->getContentEncodingDecoder(); + if(decoder.isNull()) { + LogFactory::getInstance()->info + ("Content-Encoding %s is specified, but the current implementation" + "doesn't support it. The decoding process is skipped and the" + "downloaded content will be still encoded.", + httpResponse->getContentEncoding().c_str()); + } else { + decoder->init(); + } + } + return decoder; +} + bool HttpResponseCommand::skipResponseBody (const SharedHandle& httpResponse) { SharedHandle enc(getTransferEncoding(httpResponse)); + // We don't use Content-Encoding here because this response body is just + // thrown away. + HttpSkipResponseCommand* command = new HttpSkipResponseCommand (cuid, req, _requestGroup, httpConnection, httpResponse, e, socket); command->setTransferDecoder(enc); @@ -216,7 +240,10 @@ bool HttpResponseCommand::skipResponseBody HttpDownloadCommand* HttpResponseCommand::createHttpDownloadCommand(const HttpResponseHandle& httpResponse) { - TransferEncodingHandle enc(getTransferEncoding(httpResponse)); + TransferEncodingHandle enc = getTransferEncoding(httpResponse); + SharedHandle contentEncodingDecoder = + getContentEncodingDecoder(httpResponse); + HttpDownloadCommand* command = new HttpDownloadCommand(cuid, req, _requestGroup, httpConnection, e, socket); command->setMaxDownloadSpeedLimit(e->option->getAsInt(PREF_MAX_DOWNLOAD_LIMIT)); @@ -224,6 +251,14 @@ HttpDownloadCommand* HttpResponseCommand::createHttpDownloadCommand(const HttpRe command->setLowestDownloadSpeedLimit(e->option->getAsInt(PREF_LOWEST_SPEED_LIMIT)); command->setTransferDecoder(enc); + if(!contentEncodingDecoder.isNull()) { + command->setContentEncodingDecoder(contentEncodingDecoder); + // Since the compressed file's length are returned in the response header + // and the decompressed file size is unknown at this point, disable file + // allocation here. + _requestGroup->setFileAllocationEnabled(false); + } + return command; } diff --git a/src/Makefile.am b/src/Makefile.am index 7fb7f5ed..937424bc 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -188,7 +188,12 @@ SRCS = Socket.h\ InitiateConnectionCommand.cc InitiateConnectionCommand.h\ FtpFinishDownloadCommand.cc FtpFinishDownloadCommand.h\ A2STR.cc A2STR.h\ - RarestPieceSelector.cc RarestPieceSelector.h + RarestPieceSelector.cc RarestPieceSelector.h\ + Decoder.h + +if HAVE_LIBZ +SRCS += GZipDecoder.cc GZipDecoder.h +endif # HAVE_LIBZ if ENABLE_ASYNC_DNS SRCS += AsyncNameResolver.cc AsyncNameResolver.h @@ -462,10 +467,10 @@ noinst_LIBRARIES = libaria2c.a libaria2c_a_SOURCES = $(SRCS) aria2c_LDADD = libaria2c.a @LIBINTL@ @ALLOCA@ @LIBGNUTLS_LIBS@\ @LIBGCRYPT_LIBS@ @OPENSSL_LIBS@ @XML_LIBS@ @LIBARES_LIBS@\ - @LIBCARES_LIBS@ @WINSOCK_LIBS@ @LIBEXPAT_LIBS@ #-lprofiler + @LIBCARES_LIBS@ @WINSOCK_LIBS@ @LIBEXPAT_LIBS@ @LIBZ_LIBS@ #-lprofiler #aria2c_LDFLAGS = -pg AM_CPPFLAGS = -Wall\ -I../lib -I../intl -I$(top_srcdir)/intl\ @LIBGNUTLS_CFLAGS@ @LIBGCRYPT_CFLAGS@ @OPENSSL_CFLAGS@ @XML_CPPFLAGS@\ @LIBARES_CPPFLAGS@ @LIBCARES_CPPFLAGS@ @LIBEXPAT_CPPFLAGS@\ - -DLOCALEDIR=\"$(localedir)\" @DEFS@ #-pg \ No newline at end of file + @LIBZ_CPPFLAGS@ -DLOCALEDIR=\"$(localedir)\" @DEFS@ #-pg \ No newline at end of file diff --git a/src/Makefile.in b/src/Makefile.in index 38bd3d7b..d15845e4 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -35,8 +35,9 @@ build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ bin_PROGRAMS = aria2c$(EXEEXT) -@ENABLE_ASYNC_DNS_TRUE@am__append_1 = AsyncNameResolver.cc AsyncNameResolver.h -@ENABLE_MESSAGE_DIGEST_TRUE@am__append_2 = IteratableChunkChecksumValidator.cc IteratableChunkChecksumValidator.h\ +@HAVE_LIBZ_TRUE@am__append_1 = GZipDecoder.cc GZipDecoder.h +@ENABLE_ASYNC_DNS_TRUE@am__append_2 = AsyncNameResolver.cc AsyncNameResolver.h +@ENABLE_MESSAGE_DIGEST_TRUE@am__append_3 = IteratableChunkChecksumValidator.cc IteratableChunkChecksumValidator.h\ @ENABLE_MESSAGE_DIGEST_TRUE@ IteratableChecksumValidator.cc IteratableChecksumValidator.h\ @ENABLE_MESSAGE_DIGEST_TRUE@ CheckIntegrityCommand.cc CheckIntegrityCommand.h\ @ENABLE_MESSAGE_DIGEST_TRUE@ ChecksumCheckIntegrityEntry.cc ChecksumCheckIntegrityEntry.h\ @@ -45,7 +46,7 @@ bin_PROGRAMS = aria2c$(EXEEXT) @ENABLE_MESSAGE_DIGEST_TRUE@ Checksum.h\ @ENABLE_MESSAGE_DIGEST_TRUE@ ChunkChecksum.h -@ENABLE_BITTORRENT_TRUE@am__append_3 = MetaEntry.h\ +@ENABLE_BITTORRENT_TRUE@am__append_4 = MetaEntry.h\ @ENABLE_BITTORRENT_TRUE@ Data.cc Data.h\ @ENABLE_BITTORRENT_TRUE@ Dictionary.cc Dictionary.h\ @ENABLE_BITTORRENT_TRUE@ List.cc List.h\ @@ -222,7 +223,7 @@ bin_PROGRAMS = aria2c$(EXEEXT) @ENABLE_BITTORRENT_TRUE@ BtLeecherStateChoke.cc BtLeecherStateChoke.h\ @ENABLE_BITTORRENT_TRUE@ BtSeederStateChoke.cc BtSeederStateChoke.h -@ENABLE_METALINK_TRUE@am__append_4 = Metalinker.cc Metalinker.h\ +@ENABLE_METALINK_TRUE@am__append_5 = Metalinker.cc Metalinker.h\ @ENABLE_METALINK_TRUE@ MetalinkEntry.cc MetalinkEntry.h\ @ENABLE_METALINK_TRUE@ MetalinkResource.cc MetalinkResource.h\ @ENABLE_METALINK_TRUE@ MetalinkProcessor.h\ @@ -250,38 +251,38 @@ bin_PROGRAMS = aria2c$(EXEEXT) @ENABLE_METALINK_TRUE@ MetalinkPostDownloadHandler.cc MetalinkPostDownloadHandler.h\ @ENABLE_METALINK_TRUE@ MetalinkHelper.cc MetalinkHelper.h -@ENABLE_LIBXML2_TRUE@am__append_5 = XML2SAXMetalinkProcessor.cc XML2SAXMetalinkProcessor.h -@ENABLE_LIBEXPAT_TRUE@am__append_6 = ExpatMetalinkProcessor.cc ExpatMetalinkProcessor.h -@HAVE_ASCTIME_R_FALSE@am__append_7 = asctime_r.c asctime_r.h -@HAVE_BASENAME_FALSE@am__append_8 = libgen.c libgen.h -@HAVE_GETADDRINFO_FALSE@am__append_9 = getaddrinfo.c getaddrinfo.h -@HAVE_GAI_STRERROR_FALSE@am__append_10 = gai_strerror.c gai_strerror.h -@HAVE_GETTIMEOFDAY_FALSE@am__append_11 = gettimeofday.c gettimeofday.h -@HAVE_INET_ATON_FALSE@am__append_12 = inet_aton.c inet_aton.h -@HAVE_LOCALTIME_R_FALSE@am__append_13 = localtime_r.c localtime_r.h -@HAVE_STRPTIME_FALSE@am__append_14 = strptime.c strptime.h -@HAVE_TIMEGM_FALSE@am__append_15 = timegm.c timegm.h +@ENABLE_LIBXML2_TRUE@am__append_6 = XML2SAXMetalinkProcessor.cc XML2SAXMetalinkProcessor.h +@ENABLE_LIBEXPAT_TRUE@am__append_7 = ExpatMetalinkProcessor.cc ExpatMetalinkProcessor.h +@HAVE_ASCTIME_R_FALSE@am__append_8 = asctime_r.c asctime_r.h +@HAVE_BASENAME_FALSE@am__append_9 = libgen.c libgen.h +@HAVE_GETADDRINFO_FALSE@am__append_10 = getaddrinfo.c getaddrinfo.h +@HAVE_GAI_STRERROR_FALSE@am__append_11 = gai_strerror.c gai_strerror.h +@HAVE_GETTIMEOFDAY_FALSE@am__append_12 = gettimeofday.c gettimeofday.h +@HAVE_INET_ATON_FALSE@am__append_13 = inet_aton.c inet_aton.h +@HAVE_LOCALTIME_R_FALSE@am__append_14 = localtime_r.c localtime_r.h +@HAVE_STRPTIME_FALSE@am__append_15 = strptime.c strptime.h +@HAVE_TIMEGM_FALSE@am__append_16 = timegm.c timegm.h subdir = src DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in alloca.c ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/codeset.m4 \ - $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/glibc2.m4 \ - $(top_srcdir)/m4/glibc21.m4 $(top_srcdir)/m4/iconv.m4 \ - $(top_srcdir)/m4/intdiv0.m4 $(top_srcdir)/m4/intl.m4 \ - $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intmax.m4 \ - $(top_srcdir)/m4/inttypes-pri.m4 \ +am__aclocal_m4_deps = $(top_srcdir)/m4/aria2_arg.m4 \ + $(top_srcdir)/m4/codeset.m4 $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/glibc2.m4 $(top_srcdir)/m4/glibc21.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intdiv0.m4 \ + $(top_srcdir)/m4/intl.m4 $(top_srcdir)/m4/intlmacosx.m4 \ + $(top_srcdir)/m4/intmax.m4 $(top_srcdir)/m4/inttypes-pri.m4 \ $(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/lcmessage.m4 \ $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \ $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libares.m4 \ $(top_srcdir)/m4/libcares.m4 $(top_srcdir)/m4/libexpat.m4 \ - $(top_srcdir)/m4/lock.m4 $(top_srcdir)/m4/longlong.m4 \ - $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/openssl.m4 \ - $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/printf-posix.m4 \ - $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/size_max.m4 \ - $(top_srcdir)/m4/stdint_h.m4 $(top_srcdir)/m4/uintmax_t.m4 \ - $(top_srcdir)/m4/visibility.m4 $(top_srcdir)/m4/wchar_t.m4 \ - $(top_srcdir)/m4/wint_t.m4 $(top_srcdir)/m4/xsize.m4 \ - $(top_srcdir)/configure.ac + $(top_srcdir)/m4/libz.m4 $(top_srcdir)/m4/lock.m4 \ + $(top_srcdir)/m4/longlong.m4 $(top_srcdir)/m4/nls.m4 \ + $(top_srcdir)/m4/openssl.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/printf-posix.m4 $(top_srcdir)/m4/progtest.m4 \ + $(top_srcdir)/m4/size_max.m4 $(top_srcdir)/m4/stdint_h.m4 \ + $(top_srcdir)/m4/uintmax_t.m4 $(top_srcdir)/m4/visibility.m4 \ + $(top_srcdir)/m4/wchar_t.m4 $(top_srcdir)/m4/wint_t.m4 \ + $(top_srcdir)/m4/xsize.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs @@ -406,8 +407,8 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \ InitiateConnectionCommand.cc InitiateConnectionCommand.h \ FtpFinishDownloadCommand.cc FtpFinishDownloadCommand.h \ A2STR.cc A2STR.h RarestPieceSelector.cc RarestPieceSelector.h \ - AsyncNameResolver.cc AsyncNameResolver.h \ - IteratableChunkChecksumValidator.cc \ + Decoder.h GZipDecoder.cc GZipDecoder.h AsyncNameResolver.cc \ + AsyncNameResolver.h IteratableChunkChecksumValidator.cc \ IteratableChunkChecksumValidator.h \ IteratableChecksumValidator.cc IteratableChecksumValidator.h \ CheckIntegrityCommand.cc CheckIntegrityCommand.h \ @@ -563,14 +564,15 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \ gai_strerror.h gettimeofday.c gettimeofday.h inet_aton.c \ inet_aton.h localtime_r.c localtime_r.h strptime.c strptime.h \ timegm.c timegm.h -@ENABLE_ASYNC_DNS_TRUE@am__objects_1 = AsyncNameResolver.$(OBJEXT) -@ENABLE_MESSAGE_DIGEST_TRUE@am__objects_2 = IteratableChunkChecksumValidator.$(OBJEXT) \ +@HAVE_LIBZ_TRUE@am__objects_1 = GZipDecoder.$(OBJEXT) +@ENABLE_ASYNC_DNS_TRUE@am__objects_2 = AsyncNameResolver.$(OBJEXT) +@ENABLE_MESSAGE_DIGEST_TRUE@am__objects_3 = IteratableChunkChecksumValidator.$(OBJEXT) \ @ENABLE_MESSAGE_DIGEST_TRUE@ IteratableChecksumValidator.$(OBJEXT) \ @ENABLE_MESSAGE_DIGEST_TRUE@ CheckIntegrityCommand.$(OBJEXT) \ @ENABLE_MESSAGE_DIGEST_TRUE@ ChecksumCheckIntegrityEntry.$(OBJEXT) \ @ENABLE_MESSAGE_DIGEST_TRUE@ messageDigest.$(OBJEXT) \ @ENABLE_MESSAGE_DIGEST_TRUE@ MessageDigestHelper.$(OBJEXT) -@ENABLE_BITTORRENT_TRUE@am__objects_3 = Data.$(OBJEXT) \ +@ENABLE_BITTORRENT_TRUE@am__objects_4 = Data.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ Dictionary.$(OBJEXT) List.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ MetaFileUtil.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ BencodeVisitor.$(OBJEXT) \ @@ -683,7 +685,7 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \ @ENABLE_BITTORRENT_TRUE@ MSEHandshake.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ BtLeecherStateChoke.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ BtSeederStateChoke.$(OBJEXT) -@ENABLE_METALINK_TRUE@am__objects_4 = Metalinker.$(OBJEXT) \ +@ENABLE_METALINK_TRUE@am__objects_5 = Metalinker.$(OBJEXT) \ @ENABLE_METALINK_TRUE@ MetalinkEntry.$(OBJEXT) \ @ENABLE_METALINK_TRUE@ MetalinkResource.$(OBJEXT) \ @ENABLE_METALINK_TRUE@ MetalinkProcessorFactory.$(OBJEXT) \ @@ -708,20 +710,20 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \ @ENABLE_METALINK_TRUE@ Metalink2RequestGroup.$(OBJEXT) \ @ENABLE_METALINK_TRUE@ MetalinkPostDownloadHandler.$(OBJEXT) \ @ENABLE_METALINK_TRUE@ MetalinkHelper.$(OBJEXT) -@ENABLE_LIBXML2_TRUE@am__objects_5 = \ +@ENABLE_LIBXML2_TRUE@am__objects_6 = \ @ENABLE_LIBXML2_TRUE@ XML2SAXMetalinkProcessor.$(OBJEXT) -@ENABLE_LIBEXPAT_TRUE@am__objects_6 = \ +@ENABLE_LIBEXPAT_TRUE@am__objects_7 = \ @ENABLE_LIBEXPAT_TRUE@ ExpatMetalinkProcessor.$(OBJEXT) -@HAVE_ASCTIME_R_FALSE@am__objects_7 = asctime_r.$(OBJEXT) -@HAVE_BASENAME_FALSE@am__objects_8 = libgen.$(OBJEXT) -@HAVE_GETADDRINFO_FALSE@am__objects_9 = getaddrinfo.$(OBJEXT) -@HAVE_GAI_STRERROR_FALSE@am__objects_10 = gai_strerror.$(OBJEXT) -@HAVE_GETTIMEOFDAY_FALSE@am__objects_11 = gettimeofday.$(OBJEXT) -@HAVE_INET_ATON_FALSE@am__objects_12 = inet_aton.$(OBJEXT) -@HAVE_LOCALTIME_R_FALSE@am__objects_13 = localtime_r.$(OBJEXT) -@HAVE_STRPTIME_FALSE@am__objects_14 = strptime.$(OBJEXT) -@HAVE_TIMEGM_FALSE@am__objects_15 = timegm.$(OBJEXT) -am__objects_16 = SocketCore.$(OBJEXT) Command.$(OBJEXT) \ +@HAVE_ASCTIME_R_FALSE@am__objects_8 = asctime_r.$(OBJEXT) +@HAVE_BASENAME_FALSE@am__objects_9 = libgen.$(OBJEXT) +@HAVE_GETADDRINFO_FALSE@am__objects_10 = getaddrinfo.$(OBJEXT) +@HAVE_GAI_STRERROR_FALSE@am__objects_11 = gai_strerror.$(OBJEXT) +@HAVE_GETTIMEOFDAY_FALSE@am__objects_12 = gettimeofday.$(OBJEXT) +@HAVE_INET_ATON_FALSE@am__objects_13 = inet_aton.$(OBJEXT) +@HAVE_LOCALTIME_R_FALSE@am__objects_14 = localtime_r.$(OBJEXT) +@HAVE_STRPTIME_FALSE@am__objects_15 = strptime.$(OBJEXT) +@HAVE_TIMEGM_FALSE@am__objects_16 = timegm.$(OBJEXT) +am__objects_17 = SocketCore.$(OBJEXT) Command.$(OBJEXT) \ AbstractCommand.$(OBJEXT) \ InitiateConnectionCommandFactory.$(OBJEXT) \ DownloadCommand.$(OBJEXT) \ @@ -797,8 +799,8 @@ am__objects_16 = SocketCore.$(OBJEXT) Command.$(OBJEXT) \ $(am__objects_5) $(am__objects_6) $(am__objects_7) \ $(am__objects_8) $(am__objects_9) $(am__objects_10) \ $(am__objects_11) $(am__objects_12) $(am__objects_13) \ - $(am__objects_14) $(am__objects_15) -am_libaria2c_a_OBJECTS = $(am__objects_16) + $(am__objects_14) $(am__objects_15) $(am__objects_16) +am_libaria2c_a_OBJECTS = $(am__objects_17) libaria2c_a_OBJECTS = $(am_libaria2c_a_OBJECTS) am__installdirs = "$(DESTDIR)$(bindir)" binPROGRAMS_INSTALL = $(INSTALL_PROGRAM) @@ -898,6 +900,8 @@ LIBPTH = @LIBPTH@ LIBPTH_PREFIX = @LIBPTH_PREFIX@ LIBS = @LIBS@ LIBTHREAD = @LIBTHREAD@ +LIBZ_CPPFLAGS = @LIBZ_CPPFLAGS@ +LIBZ_LIBS = @LIBZ_LIBS@ LTLIBC = @LTLIBC@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ @@ -1113,23 +1117,24 @@ SRCS = Socket.h SocketCore.cc SocketCore.h BinaryStream.h Command.cc \ InitiateConnectionCommand.cc InitiateConnectionCommand.h \ FtpFinishDownloadCommand.cc FtpFinishDownloadCommand.h \ A2STR.cc A2STR.h RarestPieceSelector.cc RarestPieceSelector.h \ - $(am__append_1) $(am__append_2) $(am__append_3) \ + Decoder.h $(am__append_1) $(am__append_2) $(am__append_3) \ $(am__append_4) $(am__append_5) $(am__append_6) \ $(am__append_7) $(am__append_8) $(am__append_9) \ $(am__append_10) $(am__append_11) $(am__append_12) \ - $(am__append_13) $(am__append_14) $(am__append_15) + $(am__append_13) $(am__append_14) $(am__append_15) \ + $(am__append_16) noinst_LIBRARIES = libaria2c.a libaria2c_a_SOURCES = $(SRCS) aria2c_LDADD = libaria2c.a @LIBINTL@ @ALLOCA@ @LIBGNUTLS_LIBS@\ @LIBGCRYPT_LIBS@ @OPENSSL_LIBS@ @XML_LIBS@ @LIBARES_LIBS@\ - @LIBCARES_LIBS@ @WINSOCK_LIBS@ @LIBEXPAT_LIBS@ #-lprofiler + @LIBCARES_LIBS@ @WINSOCK_LIBS@ @LIBEXPAT_LIBS@ @LIBZ_LIBS@ #-lprofiler #aria2c_LDFLAGS = -pg AM_CPPFLAGS = -Wall\ -I../lib -I../intl -I$(top_srcdir)/intl\ @LIBGNUTLS_CFLAGS@ @LIBGCRYPT_CFLAGS@ @OPENSSL_CFLAGS@ @XML_CPPFLAGS@\ @LIBARES_CPPFLAGS@ @LIBCARES_CPPFLAGS@ @LIBEXPAT_CPPFLAGS@\ - -DLOCALEDIR=\"$(localedir)\" @DEFS@ #-pg + @LIBZ_CPPFLAGS@ -DLOCALEDIR=\"$(localedir)\" @DEFS@ #-pg all: all-am @@ -1365,6 +1370,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FtpNegotiationCommand.Po@am__quote@ @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)/GrowSegment.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HandshakeExtensionMessage.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HashMetalinkParserState.Po@am__quote@ diff --git a/test/GZipDecoderTest.cc b/test/GZipDecoderTest.cc new file mode 100644 index 00000000..7b7eaf49 --- /dev/null +++ b/test/GZipDecoderTest.cc @@ -0,0 +1,59 @@ +#include "GZipDecoder.h" +#include "Exception.h" +#include "Util.h" +#ifdef ENABLE_MESSAGE_DIGEST +# include "MessageDigestHelper.h" +#endif // ENABLE_MESSAGE_DIGEST +#include +#include +#include + +namespace aria2 { + +class GZipDecoderTest:public CppUnit::TestFixture { + + CPPUNIT_TEST_SUITE(GZipDecoderTest); + CPPUNIT_TEST(testDecode); + CPPUNIT_TEST_SUITE_END(); +public: + void setUp() {} + + void tearDown() {} + + void testDecode(); +}; + + +CPPUNIT_TEST_SUITE_REGISTRATION(GZipDecoderTest); + +void GZipDecoderTest::testDecode() +{ + GZipDecoder decoder; + decoder.init(); + + std::string outfile("/tmp/aria2_GZipDecoderTest_testDecode"); + + char buf[4096]; + std::ifstream in("gzip_decode_test.gz"); + std::ofstream out(outfile.c_str()); + while(in) { + in.read(buf, sizeof(buf)); + + std::string r = decoder.decode + (reinterpret_cast(buf), in.gcount()); + + out.write(r.data(), r.size()); + } + CPPUNIT_ASSERT(decoder.finished()); + decoder.release(); + + out.close(); + +#ifdef ENABLE_MESSAGE_DIGEST + CPPUNIT_ASSERT_EQUAL(std::string("8b577b33c0411b2be9d4fa74c7402d54a8d21f96"), + MessageDigestHelper::digest(MessageDigestContext::SHA1, + outfile)); +#endif // ENABLE_MESSAGE_DIGEST +} + +} // namespace aria2 diff --git a/test/HttpRequestTest.cc b/test/HttpRequestTest.cc index fead309f..411fcde9 100644 --- a/test/HttpRequestTest.cc +++ b/test/HttpRequestTest.cc @@ -26,6 +26,7 @@ class HttpRequestTest : public CppUnit::TestFixture { CPPUNIT_TEST(testUserAgent); CPPUNIT_TEST(testAddHeader); CPPUNIT_TEST(testAddAcceptType); + CPPUNIT_TEST(testEnableAcceptEncoding); CPPUNIT_TEST_SUITE_END(); private: @@ -43,6 +44,7 @@ public: void testUserAgent(); void testAddHeader(); void testAddAcceptType(); + void testEnableAcceptEncoding(); }; @@ -119,6 +121,7 @@ void HttpRequestTest::testCreateRequest() SharedHandle segment(new PiecedSegment(1024, p)); HttpRequest httpRequest; + httpRequest.disableContentEncoding(); httpRequest.setRequest(request); httpRequest.setSegment(segment); @@ -344,6 +347,7 @@ void HttpRequestTest::testCreateRequest_ftp() SharedHandle p(new Piece(0, 1024*1024)); SharedHandle segment (new PiecedSegment(1024*1024, p)); + httpRequest.disableContentEncoding(); httpRequest.setRequest(request); httpRequest.setSegment(segment); @@ -402,6 +406,7 @@ void HttpRequestTest::testCreateRequest_with_cookie() HttpRequest httpRequest; + httpRequest.disableContentEncoding(); httpRequest.setRequest(request); httpRequest.setSegment(segment); @@ -466,6 +471,7 @@ void HttpRequestTest::testCreateRequest_query() SharedHandle request(new Request()); request->setUrl("http://localhost/wiki?id=9ad5109a-b8a5-4edf-9373-56a1c34ae138"); HttpRequest httpRequest; + httpRequest.disableContentEncoding(); httpRequest.setRequest(request); std::string expectedText = @@ -596,6 +602,7 @@ void HttpRequestTest::testUserAgent() SharedHandle segment(new PiecedSegment(1024, p)); HttpRequest httpRequest; + httpRequest.disableContentEncoding(); httpRequest.setRequest(request); httpRequest.setSegment(segment); httpRequest.setUserAgent("aria2 (Linux)"); @@ -626,6 +633,7 @@ void HttpRequestTest::testAddHeader() request->setUrl("http://localhost/archives/aria2-1.0.0.tar.bz2"); HttpRequest httpRequest; + httpRequest.disableContentEncoding(); httpRequest.setRequest(request); httpRequest.addHeader("X-ARIA2: v0.13\nX-ARIA2-DISTRIBUTE: enabled\n"); @@ -652,6 +660,7 @@ void HttpRequestTest::testAddAcceptType() request->setUrl("http://localhost/archives/aria2-1.0.0.tar.bz2"); HttpRequest httpRequest; + httpRequest.disableContentEncoding(); httpRequest.setRequest(request); httpRequest.addAcceptType(&acceptTypes[0], &acceptTypes[arrayLength(acceptTypes)]); @@ -668,4 +677,34 @@ void HttpRequestTest::testAddAcceptType() CPPUNIT_ASSERT_EQUAL(expectedText, httpRequest.createRequest()); } +void HttpRequestTest::testEnableAcceptEncoding() +{ + SharedHandle request(new Request()); + request->setUrl("http://localhost/archives/aria2-1.0.0.tar.bz2"); + + HttpRequest httpRequest; + httpRequest.setRequest(request); + + std::string acceptEncodings; +#ifdef HAVE_LIBZ + acceptEncodings += "deflate, gzip"; +#endif // HAVE_LIBZ + + std::string expectedText = + "GET /archives/aria2-1.0.0.tar.bz2 HTTP/1.1\r\n" + "User-Agent: aria2\r\n" + "Accept: */*\r\n"; + if(!acceptEncodings.empty()) { + expectedText += "Accept-Encoding: "+acceptEncodings+"\r\n"; + } + expectedText += + "Host: localhost\r\n" + "Pragma: no-cache\r\n" + "Cache-Control: no-cache\r\n" + "Connection: close\r\n" + "\r\n"; + + CPPUNIT_ASSERT_EQUAL(expectedText, httpRequest.createRequest()); +} + } // namespace aria2 diff --git a/test/HttpResponseTest.cc b/test/HttpResponseTest.cc index 2308ea24..919a1de6 100644 --- a/test/HttpResponseTest.cc +++ b/test/HttpResponseTest.cc @@ -7,6 +7,8 @@ #include "HttpHeader.h" #include "HttpRequest.h" #include "Exception.h" +#include "A2STR.h" +#include "Decoder.h" #include #include @@ -29,6 +31,9 @@ class HttpResponseTest : public CppUnit::TestFixture { CPPUNIT_TEST(testIsTransferEncodingSpecified); CPPUNIT_TEST(testGetTransferEncoding); CPPUNIT_TEST(testGetTransferDecoder); + CPPUNIT_TEST(testIsContentEncodingSpecified); + CPPUNIT_TEST(testGetContentEncoding); + CPPUNIT_TEST(testGetContentEncodingDecoder); CPPUNIT_TEST(testValidateResponse); CPPUNIT_TEST(testValidateResponse_good_range); CPPUNIT_TEST(testValidateResponse_bad_range); @@ -54,6 +59,9 @@ public: void testIsTransferEncodingSpecified(); void testGetTransferEncoding(); void testGetTransferDecoder(); + void testIsContentEncodingSpecified(); + void testGetContentEncoding(); + void testGetContentEncodingDecoder(); void testValidateResponse(); void testValidateResponse_good_range(); void testValidateResponse_bad_range(); @@ -240,6 +248,68 @@ void HttpResponseTest::testGetTransferDecoder() CPPUNIT_ASSERT(!httpResponse.getTransferDecoder().isNull()); } +void HttpResponseTest::testIsContentEncodingSpecified() +{ + HttpResponse httpResponse; + SharedHandle httpHeader(new HttpHeader()); + + httpResponse.setHttpHeader(httpHeader); + + CPPUNIT_ASSERT(!httpResponse.isContentEncodingSpecified()); + + httpHeader->put("Content-Encoding", "gzip"); + + CPPUNIT_ASSERT(httpResponse.isContentEncodingSpecified()); +} + +void HttpResponseTest::testGetContentEncoding() +{ + HttpResponse httpResponse; + SharedHandle httpHeader(new HttpHeader()); + + httpResponse.setHttpHeader(httpHeader); + + CPPUNIT_ASSERT_EQUAL(A2STR::NIL, httpResponse.getContentEncoding()); + + httpHeader->put("Content-Encoding", "gzip"); + + CPPUNIT_ASSERT_EQUAL(std::string("gzip"), httpResponse.getContentEncoding()); +} + +void HttpResponseTest::testGetContentEncodingDecoder() +{ + HttpResponse httpResponse; + SharedHandle httpHeader(new HttpHeader()); + + httpResponse.setHttpHeader(httpHeader); + + CPPUNIT_ASSERT(httpResponse.getContentEncodingDecoder().isNull()); + +#ifdef HAVE_LIBZ + httpHeader->put("Content-Encoding", "gzip"); + { + SharedHandle decoder = httpResponse.getContentEncodingDecoder(); + CPPUNIT_ASSERT(!decoder.isNull()); + CPPUNIT_ASSERT_EQUAL(std::string("GZipDecoder"), decoder->getName()); + } + httpHeader.reset(new HttpHeader()); + httpResponse.setHttpHeader(httpHeader); + httpHeader->put("Content-Encoding", "deflate"); + { + SharedHandle decoder = httpResponse.getContentEncodingDecoder(); + CPPUNIT_ASSERT(!decoder.isNull()); + CPPUNIT_ASSERT_EQUAL(std::string("GZipDecoder"), decoder->getName()); + } +#endif // HAVE_LIBZ + httpHeader.reset(new HttpHeader()); + httpResponse.setHttpHeader(httpHeader); + httpHeader->put("Content-Encoding", "bzip2"); + { + SharedHandle decoder = httpResponse.getContentEncodingDecoder(); + CPPUNIT_ASSERT(decoder.isNull()); + } +} + void HttpResponseTest::testValidateResponse() { HttpResponse httpResponse; diff --git a/test/Makefile.am b/test/Makefile.am index dee4e328..915c6df9 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -54,6 +54,10 @@ aria2c_SOURCES = AllTest.cc\ ExceptionTest.cc\ DownloadHandlerFactoryTest.cc +if HAVE_LIBZ +aria2c_SOURCES += GZipDecoderTest.cc +endif # HAVE_LIBZ + if ENABLE_MESSAGE_DIGEST aria2c_SOURCES += MessageDigestHelperTest.cc\ IteratableChunkChecksumValidatorTest.cc\ @@ -170,7 +174,7 @@ endif # ENABLE_METALINK aria2c_LDADD = ../src/libaria2c.a\ @LIBINTL@ @LIBGNUTLS_LIBS@\ @LIBGCRYPT_LIBS@ @OPENSSL_LIBS@ @XML_LIBS@ @LIBARES_LIBS@\ - @LIBCARES_LIBS@ @WINSOCK_LIBS@ @LIBEXPAT_LIBS@\ + @LIBCARES_LIBS@ @WINSOCK_LIBS@ @LIBEXPAT_LIBS@ @LIBZ_LIBS@\ ${CPPUNIT_LIBS} AM_CPPFLAGS = -Wall\ ${CPPUNIT_CFLAGS}\ @@ -178,7 +182,7 @@ AM_CPPFLAGS = -Wall\ -I../lib -I../intl -I$(top_srcdir)/intl\ @LIBGNUTLS_CFLAGS@ @LIBGCRYPT_CFLAGS@ @OPENSSL_CFLAGS@ @XML_CPPFLAGS@\ @LIBARES_CPPFLAGS@ @LIBCARES_CPPFLAGS@ @LIBEXPAT_CPPFLAGS@\ - -DLOCALEDIR=\"$(localedir)\" @DEFS@ + @LIBZ_CPPFLAGS@ -DLOCALEDIR=\"$(localedir)\" @DEFS@ EXTRA_DIST = 4096chunk.txt\ chunkChecksumTestFile250.txt\ @@ -188,6 +192,7 @@ EXTRA_DIST = 4096chunk.txt\ file2r.txt\ file3r.txt\ filelist1.txt\ + gzip_decode_test.gz\ load-nonBt.aria2\ load.aria2\ malformed.netrc\ diff --git a/test/Makefile.in b/test/Makefile.in index 388f90df..5ca4ece8 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -34,11 +34,12 @@ host_triplet = @host@ target_triplet = @target@ TESTS = aria2c$(EXEEXT) check_PROGRAMS = $(am__EXEEXT_1) -@ENABLE_MESSAGE_DIGEST_TRUE@am__append_1 = MessageDigestHelperTest.cc\ +@HAVE_LIBZ_TRUE@am__append_1 = GZipDecoderTest.cc +@ENABLE_MESSAGE_DIGEST_TRUE@am__append_2 = MessageDigestHelperTest.cc\ @ENABLE_MESSAGE_DIGEST_TRUE@ IteratableChunkChecksumValidatorTest.cc\ @ENABLE_MESSAGE_DIGEST_TRUE@ IteratableChecksumValidatorTest.cc -@ENABLE_BITTORRENT_TRUE@am__append_2 = BtAllowedFastMessageTest.cc\ +@ENABLE_BITTORRENT_TRUE@am__append_3 = BtAllowedFastMessageTest.cc\ @ENABLE_BITTORRENT_TRUE@ BtBitfieldMessageTest.cc\ @ENABLE_BITTORRENT_TRUE@ BtCancelMessageTest.cc\ @ENABLE_BITTORRENT_TRUE@ BtChokeMessageTest.cc\ @@ -130,7 +131,7 @@ check_PROGRAMS = $(am__EXEEXT_1) @ENABLE_BITTORRENT_TRUE@ MockPieceStorage.h\ @ENABLE_BITTORRENT_TRUE@ RarestPieceSelectorTest.cc -@ENABLE_METALINK_TRUE@am__append_3 = MetalinkerTest.cc\ +@ENABLE_METALINK_TRUE@am__append_4 = MetalinkerTest.cc\ @ENABLE_METALINK_TRUE@ MetalinkEntryTest.cc\ @ENABLE_METALINK_TRUE@ Metalink2RequestGroupTest.cc\ @ENABLE_METALINK_TRUE@ MetalinkPostDownloadHandlerTest.cc\ @@ -139,26 +140,26 @@ check_PROGRAMS = $(am__EXEEXT_1) @ENABLE_METALINK_TRUE@ MetalinkProcessorTest.cc subdir = test -DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ChangeLog ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/codeset.m4 \ - $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/glibc2.m4 \ - $(top_srcdir)/m4/glibc21.m4 $(top_srcdir)/m4/iconv.m4 \ - $(top_srcdir)/m4/intdiv0.m4 $(top_srcdir)/m4/intl.m4 \ - $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intmax.m4 \ - $(top_srcdir)/m4/inttypes-pri.m4 \ +am__aclocal_m4_deps = $(top_srcdir)/m4/aria2_arg.m4 \ + $(top_srcdir)/m4/codeset.m4 $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/glibc2.m4 $(top_srcdir)/m4/glibc21.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intdiv0.m4 \ + $(top_srcdir)/m4/intl.m4 $(top_srcdir)/m4/intlmacosx.m4 \ + $(top_srcdir)/m4/intmax.m4 $(top_srcdir)/m4/inttypes-pri.m4 \ $(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/lcmessage.m4 \ $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \ $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libares.m4 \ $(top_srcdir)/m4/libcares.m4 $(top_srcdir)/m4/libexpat.m4 \ - $(top_srcdir)/m4/lock.m4 $(top_srcdir)/m4/longlong.m4 \ - $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/openssl.m4 \ - $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/printf-posix.m4 \ - $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/size_max.m4 \ - $(top_srcdir)/m4/stdint_h.m4 $(top_srcdir)/m4/uintmax_t.m4 \ - $(top_srcdir)/m4/visibility.m4 $(top_srcdir)/m4/wchar_t.m4 \ - $(top_srcdir)/m4/wint_t.m4 $(top_srcdir)/m4/xsize.m4 \ - $(top_srcdir)/configure.ac + $(top_srcdir)/m4/libz.m4 $(top_srcdir)/m4/lock.m4 \ + $(top_srcdir)/m4/longlong.m4 $(top_srcdir)/m4/nls.m4 \ + $(top_srcdir)/m4/openssl.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/printf-posix.m4 $(top_srcdir)/m4/progtest.m4 \ + $(top_srcdir)/m4/size_max.m4 $(top_srcdir)/m4/stdint_h.m4 \ + $(top_srcdir)/m4/uintmax_t.m4 $(top_srcdir)/m4/visibility.m4 \ + $(top_srcdir)/m4/wchar_t.m4 $(top_srcdir)/m4/wint_t.m4 \ + $(top_srcdir)/m4/xsize.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs @@ -186,7 +187,8 @@ am__aria2c_SOURCES_DIST = AllTest.cc SocketCoreTest.cc \ FeatureConfigTest.cc SpeedCalcTest.cc MultiDiskAdaptorTest.cc \ MultiFileAllocationIteratorTest.cc FixedNumberRandomizer.h \ ProtocolDetectorTest.cc StringFormatTest.cc ExceptionTest.cc \ - DownloadHandlerFactoryTest.cc MessageDigestHelperTest.cc \ + DownloadHandlerFactoryTest.cc GZipDecoderTest.cc \ + MessageDigestHelperTest.cc \ IteratableChunkChecksumValidatorTest.cc \ IteratableChecksumValidatorTest.cc BtAllowedFastMessageTest.cc \ BtBitfieldMessageTest.cc BtCancelMessageTest.cc \ @@ -235,11 +237,12 @@ am__aria2c_SOURCES_DIST = AllTest.cc SocketCoreTest.cc \ MetalinkEntryTest.cc Metalink2RequestGroupTest.cc \ MetalinkPostDownloadHandlerTest.cc MetalinkHelperTest.cc \ MetalinkParserControllerTest.cc MetalinkProcessorTest.cc -@ENABLE_MESSAGE_DIGEST_TRUE@am__objects_1 = \ +@HAVE_LIBZ_TRUE@am__objects_1 = GZipDecoderTest.$(OBJEXT) +@ENABLE_MESSAGE_DIGEST_TRUE@am__objects_2 = \ @ENABLE_MESSAGE_DIGEST_TRUE@ MessageDigestHelperTest.$(OBJEXT) \ @ENABLE_MESSAGE_DIGEST_TRUE@ IteratableChunkChecksumValidatorTest.$(OBJEXT) \ @ENABLE_MESSAGE_DIGEST_TRUE@ IteratableChecksumValidatorTest.$(OBJEXT) -@ENABLE_BITTORRENT_TRUE@am__objects_2 = \ +@ENABLE_BITTORRENT_TRUE@am__objects_3 = \ @ENABLE_BITTORRENT_TRUE@ BtAllowedFastMessageTest.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ BtBitfieldMessageTest.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ BtCancelMessageTest.$(OBJEXT) \ @@ -313,7 +316,7 @@ am__aria2c_SOURCES_DIST = AllTest.cc SocketCoreTest.cc \ @ENABLE_BITTORRENT_TRUE@ MSEHandshakeTest.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ DHTUtilTest.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ RarestPieceSelectorTest.$(OBJEXT) -@ENABLE_METALINK_TRUE@am__objects_3 = MetalinkerTest.$(OBJEXT) \ +@ENABLE_METALINK_TRUE@am__objects_4 = MetalinkerTest.$(OBJEXT) \ @ENABLE_METALINK_TRUE@ MetalinkEntryTest.$(OBJEXT) \ @ENABLE_METALINK_TRUE@ Metalink2RequestGroupTest.$(OBJEXT) \ @ENABLE_METALINK_TRUE@ MetalinkPostDownloadHandlerTest.$(OBJEXT) \ @@ -349,7 +352,8 @@ am_aria2c_OBJECTS = AllTest.$(OBJEXT) SocketCoreTest.$(OBJEXT) \ MultiFileAllocationIteratorTest.$(OBJEXT) \ ProtocolDetectorTest.$(OBJEXT) StringFormatTest.$(OBJEXT) \ ExceptionTest.$(OBJEXT) DownloadHandlerFactoryTest.$(OBJEXT) \ - $(am__objects_1) $(am__objects_2) $(am__objects_3) + $(am__objects_1) $(am__objects_2) $(am__objects_3) \ + $(am__objects_4) aria2c_OBJECTS = $(am_aria2c_OBJECTS) am__DEPENDENCIES_1 = aria2c_DEPENDENCIES = ../src/libaria2c.a $(am__DEPENDENCIES_1) @@ -444,6 +448,8 @@ LIBPTH = @LIBPTH@ LIBPTH_PREFIX = @LIBPTH_PREFIX@ LIBS = @LIBS@ LIBTHREAD = @LIBTHREAD@ +LIBZ_CPPFLAGS = @LIBZ_CPPFLAGS@ +LIBZ_LIBS = @LIBZ_LIBS@ LTLIBC = @LTLIBC@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ @@ -562,14 +568,14 @@ aria2c_SOURCES = AllTest.cc SocketCoreTest.cc array_funTest.cc \ MultiFileAllocationIteratorTest.cc FixedNumberRandomizer.h \ ProtocolDetectorTest.cc StringFormatTest.cc ExceptionTest.cc \ DownloadHandlerFactoryTest.cc $(am__append_1) $(am__append_2) \ - $(am__append_3) + $(am__append_3) $(am__append_4) #aria2c_CXXFLAGS = ${CPPUNIT_CFLAGS} -I../src -I../lib -Wall -D_FILE_OFFSET_BITS=64 #aria2c_LDFLAGS = ${CPPUNIT_LIBS} aria2c_LDADD = ../src/libaria2c.a\ @LIBINTL@ @LIBGNUTLS_LIBS@\ @LIBGCRYPT_LIBS@ @OPENSSL_LIBS@ @XML_LIBS@ @LIBARES_LIBS@\ - @LIBCARES_LIBS@ @WINSOCK_LIBS@ @LIBEXPAT_LIBS@\ + @LIBCARES_LIBS@ @WINSOCK_LIBS@ @LIBEXPAT_LIBS@ @LIBZ_LIBS@\ ${CPPUNIT_LIBS} AM_CPPFLAGS = -Wall\ @@ -578,7 +584,7 @@ AM_CPPFLAGS = -Wall\ -I../lib -I../intl -I$(top_srcdir)/intl\ @LIBGNUTLS_CFLAGS@ @LIBGCRYPT_CFLAGS@ @OPENSSL_CFLAGS@ @XML_CPPFLAGS@\ @LIBARES_CPPFLAGS@ @LIBCARES_CPPFLAGS@ @LIBEXPAT_CPPFLAGS@\ - -DLOCALEDIR=\"$(localedir)\" @DEFS@ + @LIBZ_CPPFLAGS@ -DLOCALEDIR=\"$(localedir)\" @DEFS@ EXTRA_DIST = 4096chunk.txt\ chunkChecksumTestFile250.txt\ @@ -588,6 +594,7 @@ EXTRA_DIST = 4096chunk.txt\ file2r.txt\ file3r.txt\ filelist1.txt\ + gzip_decode_test.gz\ load-nonBt.aria2\ load.aria2\ malformed.netrc\ @@ -723,6 +730,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)/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@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HelpItemTest.Po@am__quote@ diff --git a/test/gzip_decode_test.gz b/test/gzip_decode_test.gz new file mode 100644 index 0000000000000000000000000000000000000000..09bb8996ca0f9ef51ff16f416220601cf258e22d GIT binary patch literal 79842 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%0DUyIyCj=&wskQkuhPDV_#FKg_v; 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 A{Qv*} literal 0 HcmV?d00001